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 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 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)); 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}