nameless_peg_parser/peg/
grammar.rs

1use crate::peg::expression::Expression;
2use crate::peg::grammar::PEGError::{ParsingError, TransformationError};
3use crate::peg::parsing::{ParserError, ParserOutput};
4use crate::peg::transformer::{TransformError, Transformer};
5use log::{debug, warn};
6use std::collections::HashMap;
7use std::fmt::{Display, Formatter};
8use std::rc::Rc;
9
10#[derive(Clone, Debug)]
11#[allow(dead_code)]
12pub enum PEGError {
13    ParsingError(ParserError),
14    TransformationError(TransformError),
15}
16
17#[derive(Clone, Debug)]
18pub struct PEG {
19    pub rules: HashMap<String, Expression>,
20    pub start: String,
21}
22
23pub const GRAMMAR_STR: &'static str = "Grammar";
24pub const END_OF_FILE_STR: &'static str = "EndOfFile";
25pub const END_OF_LINE_STR: &'static str = "EndOfLine";
26pub const SPACE_STR: &'static str = "Space";
27pub const COMMENT_STR: &'static str = "Comment";
28pub const SPACING_STR: &'static str = "Spacing";
29pub const LEFT_ARROW_STR: &'static str = "LEFTARROW";
30pub const SLASH_STR: &'static str = "SLASH";
31pub const AND_STR: &'static str = "AND";
32pub const NOT_STR: &'static str = "NOT";
33pub const QUESTION_STR: &'static str = "QUESTION";
34pub const STAR_STR: &'static str = "STAR";
35pub const PLUS_STR: &'static str = "PLUS";
36pub const OPEN_STR: &'static str = "OPEN";
37pub const CLOSE_STR: &'static str = "CLOSE";
38pub const DOT_STR: &'static str = "DOT";
39pub const CHAR_STR: &'static str = "Char";
40pub const RANGE_STR: &'static str = "Range";
41pub const CLASS_MEMBER_STR: &'static str = "ClassMember";
42pub const CLASS_STR: &'static str = "Class";
43pub const LITERAL_STR: &'static str = "Literal";
44pub const IDENTIFIER_STR: &'static str = "Identifier";
45pub const EXPRESSION_STR: &'static str = "Expression";
46pub const PRIMARY_STR: &'static str = "Primary";
47pub const SUFFIX_STR: &'static str = "Suffix";
48pub const PREFIX_STR: &'static str = "Prefix";
49pub const SEQUENCE_STR: &'static str = "Sequence";
50pub const DEFINITION_STR: &'static str = "Definition";
51
52impl PEG {
53    pub fn from_grammar(start: &str, grammar: &str) -> Result<Self, PEGError> {
54        // make actual error structure
55        match Self::peg_parser().parse(grammar) {
56            ParserOutput(_, _, Ok(tokens)) => match (Transformer {
57                input_string: grammar,
58            })
59            .transform(start, tokens)
60            {
61                Ok(peg) => Ok(peg),
62                Err(err) => Err(TransformationError(err)),
63            },
64            ParserOutput(_, _, Err(err)) => Err(ParsingError(err)),
65        }
66    }
67
68    pub fn parse(&self, input: &str) -> ParserOutput {
69        debug!("Begin Parsing");
70
71        let result = Expression::NonTerminal(self.start.clone()).parse(self, input, 0, 0);
72
73        if let ParserOutput(.., Err(err)) = &result {
74            warn!("{}", err)
75        }
76
77        debug!("Finished Parsing");
78
79        result
80    }
81
82    /// a PEG that parses the PEG syntax itself
83    pub fn peg_parser() -> Self {
84        use crate::peg::expression::Expression::*;
85
86        let start = String::from(GRAMMAR_STR);
87        let mut rules: HashMap<_, _> = Default::default();
88
89        macro_rules! add_rule {
90            ($name:expr => $expression:expr) => {{
91                rules.insert(String::from($name), $expression);
92                NonTerminal(String::from($name))
93            }};
94        }
95
96        let end_of_file = add_rule!(END_OF_FILE_STR => Not(Rc::new(Box::new(Any))));
97
98        let end_of_line = add_rule!(END_OF_LINE_STR => Choice(vec![
99            Literal(String::from("\r\n")),
100            Literal(String::from("\r")),
101            Literal(String::from("\n"))]));
102
103        let space = add_rule!(SPACE_STR => Choice(vec![
104            Literal(String::from(" ")),
105            Literal(String::from("\t")),
106            end_of_line.clone(),
107        ]));
108
109        let comment = add_rule!(COMMENT_STR => Sequence(vec![
110            Literal(String::from("#")),
111            ZeroOrMore(Sequence(vec![Not(end_of_line.clone().into_rc_box()), Any]).into_rc_box()),
112            end_of_line.clone()
113        ]));
114
115        let spacing = add_rule!(SPACING_STR => ZeroOrMore(Choice(vec![
116            space.clone(),
117            comment.clone(),
118        ]).into_rc_box()));
119
120        let leftarrow = add_rule!(LEFT_ARROW_STR => Sequence(vec![Literal(String::from("<-")), spacing.clone()]));
121        let slash =
122            add_rule!(SLASH_STR => Sequence(vec![Literal(String::from("/")), spacing.clone()]));
123        let and = add_rule!(AND_STR => Sequence(vec![Literal(String::from("&")), spacing.clone()]));
124        let not = add_rule!(NOT_STR => Sequence(vec![Literal(String::from("!")), spacing.clone()]));
125        let question =
126            add_rule!(QUESTION_STR => Sequence(vec![Literal(String::from("?")), spacing.clone()]));
127        let star =
128            add_rule!(STAR_STR => Sequence(vec![Literal(String::from("*")), spacing.clone()]));
129        let plus =
130            add_rule!(PLUS_STR => Sequence(vec![Literal(String::from("+")), spacing.clone()]));
131        let open =
132            add_rule!(OPEN_STR => Sequence(vec![Literal(String::from("(")), spacing.clone()]));
133        let close =
134            add_rule!(CLOSE_STR => Sequence(vec![Literal(String::from(")")), spacing.clone()]));
135        let dot = add_rule!(DOT_STR => Sequence(vec![Literal(String::from(".")), spacing.clone()]));
136        let char = add_rule!(CHAR_STR => Choice(vec![
137            Sequence(vec![Literal(String::from("\\")), Expression::make_class(&["n", "r", "t", "'", "\"", "[", "]", "\\"])]),
138            Sequence(vec![
139                Literal(String::from("\\")),
140                OneOrMore(Range(String::from("0"), String::from("9")).into_rc_box()),
141                Literal(String::from(";"))
142            ]),
143            Sequence(vec![Not(Literal(String::from("\\")).into_rc_box()), Any])
144        ]));
145
146        let range = add_rule!(RANGE_STR => Sequence(vec![
147            char.clone(),
148            Literal(String::from("-")),
149            char.clone()
150        ]));
151
152        let class_member = add_rule!(CLASS_MEMBER_STR => Choice(vec![
153            range.clone(),
154            char.clone()
155        ]));
156
157        let class = add_rule!(CLASS_STR => Sequence(vec![
158            Literal(String::from("[")),
159            ZeroOrMore(Sequence(vec![Not(Literal(String::from("]")).into_rc_box()), class_member.clone()]).into_rc_box()),
160            Literal(String::from("]")),
161            spacing.clone(),
162        ]));
163
164        let literal = add_rule!(LITERAL_STR => Choice(vec![
165            Sequence(vec![
166                Literal(String::from("'")),
167                ZeroOrMore(Sequence(vec![
168                    Not(Literal(String::from("'")).into_rc_box()),
169                    char.clone(),
170                ]).into_rc_box()),
171                Literal(String::from("'")),
172                spacing.clone(),
173            ]),
174            Sequence(vec![
175                Literal(String::from("\"")),
176                ZeroOrMore(Sequence(vec![
177                    Not(Literal(String::from("\"")).into_rc_box()),
178                    char.clone(),
179                ]).into_rc_box()),
180                Literal(String::from("\"")),
181                spacing.clone(),
182            ]),
183        ]));
184
185        let identifier = add_rule!(IDENTIFIER_STR => Sequence(vec![
186            Choice(vec![
187                Range(String::from("a"), String::from("z")),
188                Range(String::from("A"), String::from("Z")),
189                Literal(String::from("_")),
190            ]),
191            ZeroOrMore(Choice(vec![
192                Range(String::from("a"), String::from("z")),
193                Range(String::from("A"), String::from("Z")),
194                Literal(String::from("_")),
195                Range(String::from("0"), String::from("9")),
196            ]).into_rc_box()),
197            spacing.clone(),
198        ]));
199
200        let expression = NonTerminal(String::from(EXPRESSION_STR)); // cyclical
201
202        let primary = add_rule!(PRIMARY_STR => Choice(vec![
203            Sequence(vec![identifier.clone(), Not(leftarrow.clone().into_rc_box())]),
204            Sequence(vec![open.clone(), expression.clone(), close.clone()]),
205            literal.clone(),
206            class.clone(),
207            dot.clone(),
208        ]));
209
210        let suffix = add_rule!(SUFFIX_STR => Optional(Choice(vec![
211            question.clone(),
212            star.clone(),
213            plus.clone(),
214        ]).into_rc_box()));
215
216        let prefix = add_rule!(PREFIX_STR => Optional(Choice(vec![
217            and.clone(),
218            not.clone(),
219        ]).into_rc_box()));
220
221        let sequence = add_rule!(SEQUENCE_STR => ZeroOrMore(Sequence(vec![
222            prefix.clone(),
223            primary.clone(),
224            suffix.clone(),
225        ]).into_rc_box()));
226
227        let expression = add_rule!(EXPRESSION_STR => Sequence(vec![
228            sequence.clone(),
229            ZeroOrMore(Sequence(vec![
230                slash.clone(), sequence.clone()
231            ]).into_rc_box())
232        ]));
233
234        let definition = add_rule!(DEFINITION_STR => Sequence(vec![
235            identifier.clone(),
236            leftarrow.clone(),
237            expression.clone(),
238        ]));
239
240        let _ = add_rule!(start.clone() => Sequence(vec![
241            spacing.clone(),
242            ZeroOrMore(definition.clone().into_rc_box()),
243            end_of_file.clone(),
244        ]));
245
246        Self { start, rules }
247    }
248}
249
250impl Display for PEG {
251    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
252        let mut rules = self
253            .rules
254            .iter()
255            .map(|(name, expr)| format!("\t{} <- {}", name, expr))
256            .collect::<Vec<_>>();
257        rules.sort();
258        write!(f, "PEG ({}) {{\n{}\n}}", self.start, rules.join("\n"))
259    }
260}