makefile_lossless/
lib.rs

1#![allow(clippy::tabs_in_doc_comments)] // Makefile uses tabs
2#![deny(missing_docs)]
3
4//! A lossless parser for Makefiles
5//!
6//! Example:
7//!
8//! ```rust
9//! use std::io::Read;
10//! let contents = r#"PYTHON = python3
11//!
12//! .PHONY: all
13//!
14//! all: build
15//!
16//! build:
17//! 	$(PYTHON) setup.py build
18//! "#;
19//! let makefile: makefile_lossless::Makefile = contents.parse().unwrap();
20//!
21//! assert_eq!(makefile.rules().count(), 3);
22//! ```
23
24mod lex;
25mod lossless;
26mod parse;
27
28pub use lossless::{
29    ArchiveMember, ArchiveMembers, Error, Identifier, Include, Lang, Makefile, ParseError, Rule,
30    VariableDefinition,
31};
32pub use parse::Parse;
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
35#[allow(non_camel_case_types)]
36#[repr(u16)]
37#[allow(missing_docs)]
38pub enum SyntaxKind {
39    IDENTIFIER = 0,
40    INDENT,
41    TEXT,
42    WHITESPACE,
43    NEWLINE,
44    DOLLAR,
45    LPAREN,
46    RPAREN,
47    QUOTE,
48    BACKSLASH,
49    COMMA,
50    OPERATOR,
51
52    COMMENT,
53    ERROR,
54
55    // composite nodes
56    ROOT,          // The entire file
57    RULE,          // A single rule
58    RECIPE,        // A command/recipe line
59    VARIABLE,      // A variable definition
60    EXPR,          // An expression (e.g., targets before colon, or old-style prerequisites)
61    PREREQUISITES, // Container for prerequisites after the colon
62    PREREQUISITE,  // A single prerequisite item
63
64    // Directives
65    CONDITIONAL,
66    INCLUDE,
67
68    // Archive members
69    ARCHIVE_MEMBERS, // Container for just the members inside parentheses
70    ARCHIVE_MEMBER,  // Individual member like "bar.o" or "baz.o"
71}
72
73/// Convert our `SyntaxKind` into the rowan `SyntaxKind`.
74impl From<SyntaxKind> for rowan::SyntaxKind {
75    fn from(kind: SyntaxKind) -> Self {
76        Self(kind as u16)
77    }
78}