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}