1use super::{expr, bracket, Tree, Location, Loc, Stream, Context, Parse};
4use expr::{MaybeExpr, Expr, Op};
5use bracket::{Brace};
6
7pub const MISSING_SEMICOLON: &'static str = "Missing `;`";
8pub const MISSING_ELSE_BODY: &'static str = "Missing `else` body";
9pub const MISSING_IF_BODY: &'static str = "Missing `if` body";
10pub const MISSING_LOOP_BODY: &'static str = "Missing loop body";
11pub const MISSING_CASE_BODY: &'static str = "Missing `case` body";
12pub const SPURIOUS_CASE: &'static str = "Unexpected `case` without a preceding `switch`";
13pub const SPURIOUS_ELSE: &'static str = "Unexpected `else` without a preceding `switch`, `if`, `while` or `for`";
14
15#[derive(Debug, Copy, Clone, PartialEq)]
21pub enum Verb { Break, Continue, Return, Throw, Assert, Assume }
22
23#[derive(Debug, Copy, Clone, PartialEq)]
25pub enum Keyword { Case, Else, Switch, If, While, For, Verb(Verb) }
26
27impl Tree for Keyword {
28 fn declare_keywords(mut declare: impl FnMut(&'static str, Self)) {
29 declare("case", Self::Case);
30 declare("else", Self::Else);
31 declare("switch", Self::Switch);
32 declare("if", Self::If);
33 declare("while", Self::While);
34 declare("for", Self::For);
35 declare("break", Self::Verb(Verb::Break));
36 declare("continue", Self::Verb(Verb::Continue));
37 declare("return", Self::Verb(Verb::Return));
38 declare("throw", Self::Verb(Verb::Throw));
39 declare("assert", Self::Verb(Verb::Assert));
40 declare("assume", Self::Verb(Verb::Assume));
41 }
42}
43
44#[derive(Debug, Copy, Clone, PartialEq)]
46pub enum AssignOp {
47 Let,
49
50 Set,
52
53 Op(Op),
55}
56
57impl Tree for AssignOp {
58 fn declare_keywords(mut declare: impl FnMut(&'static str, Self)) {
59 declare("=", Self::Let);
60 declare(":=", Self::Set);
61 declare("|=", Self::Op(Op::BitOr));
62 declare("^=", Self::Op(Op::BitXor));
63 declare("&=", Self::Op(Op::BitAnd));
64 declare("<<=", Self::Op(Op::SL));
65 declare(">>=", Self::Op(Op::ASR));
66 declare(">>>=", Self::Op(Op::LSR));
67 declare("+=", Self::Op(Op::Add));
68 declare("-=", Self::Op(Op::Sub));
69 declare("*=", Self::Op(Op::Mul));
70 declare("/=", Self::Op(Op::Div));
71 declare("%=", Self::Op(Op::Rem));
72 declare("**=", Self::Op(Op::Pow));
73 }
74}
75
76#[derive(Debug)]
82pub struct Case(pub Location, pub MaybeExpr, pub Brace);
83
84#[derive(Debug)]
86pub struct Else(pub Location, pub Brace);
87
88#[derive(Debug)]
94pub enum Stmt {
95 Expr(MaybeExpr),
97
98 Assign(MaybeExpr, Loc<AssignOp>, MaybeExpr),
100
101 If(Location, MaybeExpr, Brace, Option<Else>),
105
106 While(Location, MaybeExpr, Brace, Option<Else>),
110
111 For(Location, MaybeExpr, Brace, Option<Else>),
116
117 Switch(Location, MaybeExpr, Vec<Case>, Option<Else>),
121
122 Verb(Loc<Verb>, MaybeExpr),
127}
128
129impl Tree for Stmt {}
130
131#[derive(Default, Debug)]
135pub struct Parser;
136
137impl Parser {
138 fn parse_semicolon(
140 &self,
141 input: &mut Context<impl Stream>,
142 ) -> Result<char, String> {
143 Ok(*input.read_if(|&k| k == ';')?.ok_or(MISSING_SEMICOLON)?)
144 }
145
146 fn parse_case(
150 &self,
151 input: &mut Context<impl Stream>,
152 ) -> Result<Option<Case>, String> {
153 let loc = input.last();
154 Ok(if input.read_if(|k| matches!(k, Keyword::Case))?.is_some() {
155 let pattern = input.read::<Expr>()?;
156 let body = input.read::<Brace>()?.ok_or(MISSING_CASE_BODY);
157 Some(Case(loc, pattern, *body?))
158 } else { None })
159 }
160
161 fn parse_else(
165 &self,
166 input: &mut Context<impl Stream>,
167 ) -> Result<Option<Else>, String> {
168 Ok(if input.read_if(|k| matches!(k, Keyword::Else))?.is_some() {
169 let loc = input.last();
170 let brace = *input.read::<Brace>()?.ok_or(MISSING_ELSE_BODY)?;
171 Some(Else(loc, brace))
172 } else { None })
173 }
174
175 fn parse_control(
183 &self,
184 input: &mut Context<impl Stream>,
185 constructor: fn(Location, MaybeExpr, Brace, Option<Else>) -> Stmt,
186 missing_body: &'static str,
187 ) -> Result<Box<dyn Tree>, String> {
188 let loc = input.last();
189 let condition = input.read::<Expr>()?;
190 let body = input.read::<Brace>()?.ok_or(missing_body);
191 let else_ = self.parse_else(input)?;
192 Ok(Box::new(constructor(loc, condition, *body?, else_)))
193 }
194}
195
196impl Parse for Parser {
197 fn parse(
198 &self,
199 input: &mut Context<impl Stream>,
200 ) -> Result<Box<dyn Tree>, String> {
201 if let Some(expr) = input.read::<Expr>()? {
202 if let Some(op) = input.read::<AssignOp>()? {
203 let op = input.locate(*op);
204 let rhs = input.read::<Expr>()?;
205 self.parse_semicolon(input)?;
206 Ok(Box::new(Stmt::Assign(Some(expr), op, rhs)))
207 } else {
208 self.parse_semicolon(input)?;
209 Ok(Box::new(Stmt::Expr(Some(expr))))
210 }
211 } else if let Some(keyword) = input.read::<Keyword>()? {
212 let loc = input.last();
213 match *keyword {
214 Keyword::Case => {
215 let _ = input.read::<Expr>()?;
216 let _ = input.read::<Brace>()?;
217 Err(SPURIOUS_CASE)?
218 },
219 Keyword::Else => {
220 let _ = input.read::<Brace>()?;
221 Err(SPURIOUS_ELSE)?
222 },
223 Keyword::Switch => {
224 let discriminant = input.read::<Expr>()?;
225 let mut cases = Vec::new();
226 while let Some(case) = self.parse_case(input)? { cases.push(case); }
227 let else_ = self.parse_else(input)?;
228 Ok(Box::new(Stmt::Switch(loc, discriminant, cases, else_)))
229 },
230 Keyword::If => {
231 self.parse_control(input, Stmt::If, MISSING_IF_BODY)
232 },
233 Keyword::While => {
234 self.parse_control(input, Stmt::While, MISSING_LOOP_BODY)
235 },
236 Keyword::For => {
237 self.parse_control(input, Stmt::For, MISSING_LOOP_BODY)
238 },
239 Keyword::Verb(verb) => {
240 let verb = input.locate(verb);
241 let expr = input.read::<Expr>()?;
242 self.parse_semicolon(input)?;
243 Ok(Box::new(Stmt::Verb(verb, expr)))
244 },
245 }
246 } else if let Some(op) = input.read::<AssignOp>()? {
247 let op = input.locate(*op);
249 let rhs = input.read::<Expr>()?;
250 Ok(Box::new(Stmt::Assign(None, op, rhs)))
251 } else if input.read_if::<char>(|&k| k == ';')?.is_some() {
252 Ok(Box::new(Stmt::Expr(None)))
254 } else { input.read_any() }
255 }
256}
257
258#[cfg(test)]
261mod tests {
262 use super::*;
263 use crate::{parsers, EndOfFile, Characters};
264 use bracket::{Round};
265 use parsers::{Brackets};
266
267 fn round(input: impl Stream) -> impl Stream {
269 Parser.parse_stream(parsers::EXPR.parse_stream(Brackets::new('(', ')', |contents| {
270 let contents = parsers::EXPR.parse_stream(contents.into_iter()).read_all();
271 Round::new(contents)
272 }, input)))
273 }
274
275 fn brace(input: impl Stream) -> impl Stream {
277 round(Brackets::new('{', '}', |contents| {
278 let contents = round(contents.into_iter()).read_all();
279 Brace::new(contents)
280 }, input))
281 }
282
283 fn parse(source: &'static str) -> impl Stream {
285 let stream = Characters::new(source, true);
286 let stream = parsers::LEXER.parse_stream(stream);
287 let mut word_parser = parsers::Word::default();
288 word_parser.add_keywords::<Keyword>();
289 word_parser.add_keywords::<AssignOp>();
290 let stream = word_parser.parse_stream(stream);
291 brace(stream)
292 }
293
294 fn parse_one(source: &'static str) -> Box<Stmt> {
296 let mut stream = parse(source);
297 let result = match stream.read().result() {
298 Ok(tree) => match tree.downcast::<Stmt>() {
299 Ok(tree) => tree,
300 Err(tree) => panic!("Got a non-Stmt: {:?}", tree),
301 },
302 Err(e) => panic!("Got error: {:?}", e),
303 };
304 assert_eq!(stream.read(), EndOfFile);
305 result
306 }
307
308 fn check_name(e: impl Into<MaybeExpr>, expected: &'static str) {
310 match *e.into().expect("Missing Expr::Name") {
311 Expr::Name(observed) => assert_eq!(observed, expected),
312 e => panic!("Expected an Expr::Name but got {:?}", e),
313 }
314 }
315
316 fn check_brace(b: impl Into<Option<Brace>>, expected: &'static str) {
318 let mut contents = b.into().expect("Missing Brace").0.into_iter();
319 match contents.read().unwrap::<Stmt>() {
320 Stmt::Expr(e) => check_name(e, expected),
321 s => panic!("Expected a Stmt::Expr but got {:#?}", s),
322 }
323 assert_eq!(contents.read(), EndOfFile);
324 }
325
326 fn check_else(e: impl Into<Option<Else>>, expected: &'static str) {
328 check_brace(e.into().expect("Missing Else").1, expected);
329 }
330
331 #[test]
332 fn print() {
333 let tree = parse_one("print;");
334 match *tree {
335 Stmt::Expr(e) => check_name(e, "print"),
336 s => panic!("Expected a Stmt::Expr but got {:#?}", s),
337 }
338 }
339
340 #[test]
341 fn assign() {
342 let tree = parse_one("x += 1;");
343 match *tree {
344 Stmt::Assign(left, op, right) => {
345 check_name(left, "x");
346 assert_eq!(op, AssignOp::Op(Op::Add));
347 check_name(right, "1");
348 },
349 s => panic!("Expected a Stmt::Assign but got {:#?}", s),
350 }
351 }
352
353 #[test]
354 fn if_() {
355 let tree = parse_one("if b { foo; } else { bar; }");
356 match *tree {
357 Stmt::If(_, b, then, else_) => {
358 check_name(b, "b");
359 check_brace(then, "foo");
360 check_else(else_, "bar");
361 },
362 s => panic!("Expected a Stmt::If but got {:#?}", s),
363 }
364 }
365
366 #[test]
367 fn switch() {
368 let tree = parse_one("switch d case FOO { foo; } else { bar; }");
369 match *tree {
370 Stmt::Switch(_, d, cases, else_) => {
371 check_name(d, "d");
372 let mut cases = cases.into_iter();
373 match cases.next() {
374 Some(Case(_, pattern, body)) => {
375 check_name(pattern, "FOO");
376 check_brace(body, "foo");
377 },
378 _ => panic!("Missing Case"),
379 }
380 assert!(cases.next().is_none());
381 check_else(else_, "bar");
382 },
383 s => panic!("Expected a Stmt::Switch but got {:#?}", s),
384 }
385 }
386
387 #[test]
388 fn break_() {
389 let tree = parse_one("break;");
390 match *tree {
391 Stmt::Verb(verb, None) => assert_eq!(verb, Verb::Break),
392 s => panic!("Expected a Stmt::Verb but got {:#?}", s),
393 }
394 }
395
396 #[test]
397 fn return_() {
398 let tree = parse_one("return 42;");
399 match *tree {
400 Stmt::Verb(verb, ans) => {
401 assert_eq!(verb, Verb::Return);
402 check_name(ans, "42");
403 },
404 s => panic!("Expected a Stmt::Verb but got {:#?}", s),
405 }
406 }
407}