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, Conditional, Error, Identifier, Include, Lang, Makefile,
30    MakefileItem, MakefileVariant, ParseError, Rule, RuleItem, 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    TARGETS,       // Container for targets before the colon
62    PREREQUISITES, // Container for prerequisites after the colon
63    PREREQUISITE,  // A single prerequisite item
64
65    // Directives
66    CONDITIONAL,       // The entire conditional block (ifdef...endif)
67    CONDITIONAL_IF,    // The initial conditional (ifdef/ifndef/ifeq/ifneq)
68    CONDITIONAL_ELSE,  // An else or else-conditional clause
69    CONDITIONAL_ENDIF, // The endif keyword
70    INCLUDE,
71
72    // Archive members
73    ARCHIVE_MEMBERS, // Container for just the members inside parentheses
74    ARCHIVE_MEMBER,  // Individual member like "bar.o" or "baz.o"
75
76    // Blank lines
77    BLANK_LINE, // A blank line between top-level items
78}
79
80/// Convert our `SyntaxKind` into the rowan `SyntaxKind`.
81impl From<SyntaxKind> for rowan::SyntaxKind {
82    fn from(kind: SyntaxKind) -> Self {
83        Self(kind as u16)
84    }
85}