flycatcher_parser/lib.rs
1//! A hand-written parser that emits an AST tree.
2
3pub mod ast;
4pub mod error;
5
6use ast::{Ast, AstMeta};
7use ast::opcode::get_operator;
8use codespan_reporting::diagnostic::{Diagnostic, Label};
9use error::ErrorKind;
10use flycatcher_lexer::{Lexer, Logos, Token};
11
12/// A Parser struct that takes an input string, tokenizes it and parses it into a more or less
13/// readable AST tree.
14pub struct Parser<'a> {
15
16 /// The name of the input file that is being parsed. This property helps make more precise
17 /// diagnostic messages, by providing the name of the file that the diagnostic originated
18 /// from.
19 pub filename: &'a str,
20
21 /// The string of Flycatcher input that is tokenized and parsed by the parser. The source
22 /// is also used to emit code snippets in diagnostic messages.
23 pub source: &'a str,
24
25 /// A list of diagnostics that were created during parsing. These are not logged to the
26 /// console by the parser, so they can be used to recieve information for IDEs and such.
27 pub diagnostics: Vec<Diagnostic<()>>,
28
29 /// The lexer that the parser recieves input tokens from.
30 lexer: Lexer<'a, Token>,
31
32}
33
34impl<'a> Parser<'a> {
35
36 /// Allocates a new parser object. This does not start the parsing process, it only
37 /// initializes a lexer and parser and returns the parser.
38 ///
39 /// # Arguments
40 /// - `filename`: The absolute file path to the file being parsed, if any. If you don't
41 /// have an actual file to put here, put `@anonymous`.
42 /// - `source`: The string that will be tokenized and parsed by the parser that is allocated
43 /// by this function.
44 pub fn new(filename: &'a str, source: &'a str) -> Self {
45 Self {
46 filename,
47 source,
48 diagnostics: vec![],
49 lexer: Token::lexer(source)
50 }
51 }
52
53 /// Parses a list of Flycatcher values. The token provided is the token used to close the
54 /// list.
55 fn parse_list(&mut self, close: Token) -> Result<Vec<AstMeta>, ErrorKind> {
56 let mut state = 0; // 0 = value, 1 = ,
57 let mut args = vec![]; // list of items in the list.
58
59 let start = self.lexer.span().start;
60
61 loop {
62 let mut peekable = self.lexer.clone();
63
64 if let Some(tok) = peekable.next() {
65 if tok == close {
66 self.lexer.next();
67 break;
68 }
69 }
70
71 if state == 0 {
72 state = 1;
73 match self.parse_expression() {
74 Ok(ast) => {
75 args.push(ast);
76 },
77 Err(e) => {
78 if e == ErrorKind::EndOfFile {
79 let label = Label::primary((), start..self.lexer.span().end)
80 .with_message(format!("this here array never closes."));
81
82 let help = Label::secondary((), self.lexer.span())
83 .with_message("try inserting a ']' here.");
84
85 let diagnostic = Diagnostic::error()
86 .with_code("FC0011")
87 .with_labels(vec![label, help])
88 .with_message(format!("array never closes."));
89
90 self.diagnostics.push(diagnostic);
91
92 return Err(ErrorKind::SyntaxError);
93 }
94
95 return Err(e);
96 }
97 }
98 } else if state == 1 {
99 state = 0;
100
101 if let Some(tok) = self.lexer.next() {
102 if tok != Token::Comma {
103 let label = Label::primary((), self.lexer.span())
104 .with_message(format!("expected a comma here."));
105
106 let diagnostic = Diagnostic::error()
107 .with_code("FC0012")
108 .with_labels(vec![label])
109 .with_message(format!("expected comma in array, got '{}'", self.lexer.slice()));
110
111 self.diagnostics.push(diagnostic);
112
113 return Err(ErrorKind::SyntaxError);
114 }
115 } else {
116 let label = Label::primary((), start..self.lexer.span().end)
117 .with_message(format!("this here array never closes."));
118
119 let help = Label::secondary((), self.lexer.span())
120 .with_message("try inserting a '[' here.");
121
122 let diagnostic = Diagnostic::error()
123 .with_code("FC0011")
124 .with_labels(vec![label, help])
125 .with_message(format!("array never closes."));
126
127 self.diagnostics.push(diagnostic);
128
129 return Err(ErrorKind::SyntaxError);
130 }
131 }
132 }
133
134 Ok(args)
135 }
136
137 /// Parses a single literal token from the lexer.
138 fn parse_literal(&mut self) -> Result<AstMeta, ErrorKind> {
139 if let Some(tok) = self.lexer.next() {
140 if tok == Token::Identifier {
141 // At this phase, certain keywords don't exist, like `true`, `false` and `null`,
142 // so we'll need to implement them here.
143
144 let slice = self.lexer.slice();
145
146 if slice == "true" {
147 return Ok(
148 AstMeta::new(
149 self.lexer.span(),
150 Ast::BooleanLiteral(true)
151 )
152 );
153 } else if slice == "false" {
154 return Ok(
155 AstMeta::new(
156 self.lexer.span(),
157 Ast::BooleanLiteral(false)
158 )
159 );
160 } else if slice == "null" {
161 return Ok(
162 AstMeta::new(
163 self.lexer.span(),
164 Ast::NullLiteral
165 )
166 );
167 }
168
169 Ok(AstMeta::new(
170 self.lexer.span(),
171 Ast::IdentifierLiteral(slice.into())
172 ))
173 } else if tok == Token::Number {
174 let slice = self.lexer.slice().to_string();
175
176 if slice.contains('.') || slice.contains('e') || slice.contains('E') {
177 let f = slice.parse::<f64>().unwrap();
178 Ok(AstMeta::new(
179 self.lexer.span(),
180 Ast::FloatLiteral(f)
181 ))
182 } else {
183 let i = slice.parse::<i64>().unwrap();
184 Ok(AstMeta::new(
185 self.lexer.span(),
186 Ast::IntegerLiteral(i)
187 ))
188 }
189 /*
190 let f = self.lexer.slice().parse::<f64>().unwrap();
191 Ok(AstMeta::new(
192 self.lexer.span(),
193 Ast::NumberLiteral(f)
194 ))*/
195 } else if tok == Token::String {
196 let str = &self.lexer.slice()[1..self.lexer.slice().len() - 1];
197 Ok(AstMeta::new(
198 self.lexer.span(),
199 Ast::StringLiteral(str.into())
200 ))
201 } else if tok == Token::OBrack {
202 // Array literal.
203 let start = self.lexer.span().start;
204 match self.parse_list(Token::CBrack) {
205 Ok(ast) => {
206 Ok(
207 AstMeta::new(
208 start..self.lexer.span().end,
209 Ast::ListLiteral(ast)
210 )
211 )
212 }
213 Err(e) => Err(e),
214 }
215 } else if tok == Token::OParen {
216 let start = self.lexer.span().start;
217 match self.parse_expression() {
218 Ok(ast) => {
219 if let Some(t) = self.lexer.next() {
220 if t != Token::CParen {
221 let label = Label::primary((), start..self.lexer.span().end)
222 .with_message("expected closing parenthesis in this expression.");
223
224 let diagnostic = Diagnostic::error()
225 .with_code("FC0016")
226 .with_labels(vec![label])
227 .with_message(format!("expected a closing parenthesis."));
228
229 self.diagnostics.push(diagnostic);
230
231 return Err(ErrorKind::SyntaxError);
232 }
233 } else {
234 let label = Label::primary((), start..self.lexer.span().end)
235 .with_message("expected closing parenthesis in this expression.");
236
237 let diagnostic = Diagnostic::error()
238 .with_code("FC0016")
239 .with_labels(vec![label])
240 .with_message(format!("expected a closing parenthesis."));
241
242 self.diagnostics.push(diagnostic);
243
244 return Err(ErrorKind::SyntaxError);
245 }
246
247 Ok(
248 ast
249 )
250 }
251 Err(e) => {
252 if e == ErrorKind::EndOfFile {
253 let label = Label::primary((), start..self.lexer.span().end)
254 .with_message("expected an expression inside of these parenthesis.");
255
256 let diagnostic = Diagnostic::error()
257 .with_code("FC0015")
258 .with_labels(vec![label])
259 .with_message(format!("expected an expression."));
260
261 self.diagnostics.push(diagnostic);
262
263 return Err(ErrorKind::SyntaxError);
264 }
265
266 Err(e)
267 },
268 }
269 } else {
270 // The token is unrecognized, so we have to give the correct error message.
271 if tok == Token::Invalid {
272 let label = Label::primary((), self.lexer.span())
273 .with_message("this character is unrecognized by flycatcher.");
274
275 let diagnostic = Diagnostic::error()
276 .with_code("FC0001")
277 .with_labels(vec![label])
278 .with_message(format!("invalid character '{}'", self.lexer.slice()));
279
280 self.diagnostics.push(diagnostic);
281
282 Err(ErrorKind::SyntaxError)
283 } else {
284 let label = Label::primary((), self.lexer.span())
285 .with_message("expected a proper value here");
286
287 let diagnostic = Diagnostic::error()
288 .with_code("FC0002")
289 .with_labels(vec![label])
290 .with_message(format!("expected a value here, got '{}'", self.lexer.slice()));
291
292 self.diagnostics.push(diagnostic);
293
294 Err(ErrorKind::SyntaxError)
295 }
296 }
297 } else {
298 // No token was found, so we return ErrorKind::EndOfFile
299 Err(ErrorKind::EndOfFile)
300 }
301 }
302
303 /// Parses an index statement, such as `item1.item2` or `item["item2"]`.
304 fn parse_index(&mut self, first: AstMeta) -> Result<AstMeta, ErrorKind> {
305 // This is the state of the parser, basically what the parser expects. 1 means that the
306 // parser expects either a `.` or a `["key"]`. 0 means that the parser expects an
307 // identifier.
308 let mut state = 1;
309 let start = first.range.start;
310
311 let mut items = vec![first];
312
313 loop {
314 // Clone the lexer to not disturb its original state, in the case that the index
315 // statement ends.
316 let mut peekable = self.lexer.clone();
317
318 if let Some(tok) = peekable.next() {
319 if state == 0 {
320 state = 1;
321
322 if tok == Token::Identifier {
323 self.lexer.next();
324 items.push(
325 AstMeta::new(
326 self.lexer.span(),
327 Ast::IdentifierLiteral(self.lexer.slice().into())
328 )
329 );
330 // Move on to the next token.
331 //self.lexer.next();
332 } else {
333 // Trying to use a `.` to index with anything other than an identifier
334 // always results in an error.
335 self.lexer.next();
336 let label = Label::primary((), start..self.lexer.span().end)
337 .with_message(format!("expected a property name, got '{}'", self.lexer.slice()));
338
339 let help = Label::secondary((), self.lexer.span())
340 .with_message(format!("try wrapping it in []: '[{}]'", self.lexer.slice()));
341
342 let diagnostic = Diagnostic::error()
343 .with_code("FC0004")
344 .with_labels(vec![label, help])
345 .with_message(format!("you indexed with a '.', expected a property name."));
346
347 self.diagnostics.push(diagnostic);
348
349 return Err(ErrorKind::SyntaxError);
350 }
351 } else if state == 1 {
352 if tok == Token::Dot {
353 // It's a `.`, so we can set the state to 0 and skip over it.
354 state = 0;
355 self.lexer.next();
356 } else if tok == Token::OBrack {
357 // Uses a recursive call to `parse_expression` inside of the opened
358 // bracket, to recieve the inners ;)
359 self.lexer.next();
360 let start = self.lexer.span().start;
361 match self.parse_expression() {
362 Ok(index) => {
363 // Check if there's a closing bracket
364
365 if let Some(tok) = self.lexer.next() {
366 if tok == Token::CBrack {
367 items.push(
368 AstMeta::new(
369 start..self.lexer.span().end,
370 Ast::BracketIndex(
371 index.as_box()
372 )
373 )
374 )
375 } else {
376 let label = Label::primary((), self.lexer.span())
377 .with_message(format!("expected a closing bracket before this."));
378
379 let diagnostic = Diagnostic::error()
380 .with_code("FC0006")
381 .with_labels(vec![label])
382 .with_message(format!("expected a closing bracket instead of '{}'", self.lexer.slice()));
383
384 self.diagnostics.push(diagnostic);
385
386 return Err(ErrorKind::SyntaxError);
387 }
388 } else {
389 let label = Label::primary((), start..self.lexer.span().end)
390 .with_message(format!("unclosed brackets here."));
391
392 let diagnostic = Diagnostic::error()
393 .with_code("FC0005")
394 .with_labels(vec![label])
395 .with_message(format!("you indexed an object with unclosed brackets."));
396
397 self.diagnostics.push(diagnostic);
398
399 return Err(ErrorKind::SyntaxError);
400 }
401 },
402 Err(e) => {
403 // We need to check if an error message has been sent, if not,
404 // we'll need to send our own.
405 if e == ErrorKind::EndOfFile {
406 // No error was emitted.
407 let label = Label::primary((), self.lexer.span())
408 .with_message(format!("unclosed brackets here."));
409
410 let diagnostic = Diagnostic::error()
411 .with_code("FC0005")
412 .with_labels(vec![label])
413 .with_message(format!("you indexed an object with unclosed brackets."));
414
415 self.diagnostics.push(diagnostic);
416
417 return Err(ErrorKind::SyntaxError);
418 }
419
420 return Err(e);
421 }
422 }
423 } else {
424 break;
425 }
426 }
427 } else {
428 // There was no token, if the state was 1, everything should be fine.
429 // Otherwise, the rule of no open index statements (such as `item1.item2.`)
430 // is broken.
431 if state == 0 {
432 self.lexer.next();
433 let label = Label::primary((), start..self.lexer.span().end)
434 .with_message("this index expression is unclosed.");
435
436 let help = Label::secondary((), self.lexer.span())
437 .with_message("there is an extra period here.");
438
439 let diagnostic = Diagnostic::error()
440 .with_code("FC0003")
441 .with_labels(vec![label, help])
442 .with_message(format!("unclosed index expression"));
443
444 self.diagnostics.push(diagnostic);
445
446 return Err(ErrorKind::SyntaxError);
447 } else {
448 // No actual syntax errors occurred, so we break the loop.
449 break;
450 }
451 }
452 }
453
454 Ok(
455 AstMeta::new(
456 start..self.lexer.span().end,
457 Ast::IndexExpression(items)
458 )
459 )
460 }
461
462 /// Parses an expression operand.
463 fn parse_secondary(&mut self) -> Result<AstMeta, ErrorKind> {
464 let mut peekable = self.lexer.clone();
465
466 if let Some(tok) = peekable.next() {
467 if tok == Token::Dash {
468 self.lexer.next();
469
470 let start = self.lexer.span().start;
471 let end = self.lexer.span().end;
472
473 match self.parse_primary() {
474 Ok(ast) => {
475 return Ok(
476 AstMeta::new(
477 start..self.lexer.span().end,
478 Ast::NegativeUnary(
479 ast.as_box()
480 )
481 )
482 );
483 },
484 Err(e) => {
485 if e == ErrorKind::EndOfFile {
486 self.lexer.next();
487 let label = Label::primary((), start..end)
488 .with_message("expression starts here");
489
490 let help = Label::secondary((), self.lexer.span())
491 .with_message("expected a value here");
492
493 let diagnostic = Diagnostic::error()
494 .with_code("FC0007")
495 .with_labels(vec![label, help])
496 .with_message(format!("no value found in `-` expression."));
497
498 self.diagnostics.push(diagnostic);
499
500 return Err(ErrorKind::SyntaxError);
501 }
502
503 return Err(e);
504 }
505 }
506 } if tok == Token::Plus {
507 self.lexer.next();
508
509 let start = self.lexer.span().start;
510 let end = self.lexer.span().end;
511
512 match self.parse_primary() {
513 Ok(ast) => {
514 return Ok(
515 AstMeta::new(
516 start..self.lexer.span().end,
517 Ast::PositiveUnary(
518 ast.as_box()
519 )
520 )
521 );
522 },
523 Err(e) => {
524 if e == ErrorKind::EndOfFile {
525 self.lexer.next();
526 let label = Label::primary((), start..end)
527 .with_message("expression starts here");
528
529 let help = Label::secondary((), self.lexer.span())
530 .with_message("expected a value here");
531
532 let diagnostic = Diagnostic::error()
533 .with_code("FC0007")
534 .with_labels(vec![label, help])
535 .with_message(format!("no value found in `+` expression."));
536
537 self.diagnostics.push(diagnostic);
538
539 return Err(ErrorKind::SyntaxError);
540 }
541
542 return Err(e);
543 }
544 }
545 } else {
546 return self.parse_literal()
547 }
548 }
549
550 return Err(ErrorKind::EndOfFile);
551 }
552
553 /// Parses a binary expression with operator precedence, providing a minimum precedence for
554 /// operators.
555 fn parse_binary(&mut self, mut left: AstMeta, min: usize) -> Result<AstMeta, ErrorKind> {
556 let mut tok = self.lexer.clone().next();
557
558 while let Some(lookahead) = tok {
559 if let Some(op) = get_operator(lookahead) {
560 if op.precedence() >= min {
561 self.lexer.next();
562 let mut right = match self.parse_primary() {
563 Ok(ast) => ast,
564 Err(e) => {
565 if e == ErrorKind::EndOfFile {
566 // No error was emitted.
567 let label = Label::primary((), self.lexer.span())
568 .with_message(format!("expected right hand side of expression here."));
569
570 let diagnostic = Diagnostic::error()
571 .with_code("FC0010")
572 .with_labels(vec![label])
573 .with_message(format!("expected right hand side of expression."));
574
575 self.diagnostics.push(diagnostic);
576
577 return Err(ErrorKind::SyntaxError);
578 }
579
580 return Err(e);
581 }
582 };
583
584 tok = self.lexer.clone().next();
585
586 while let Some(lookahead2) = tok {
587 if let Some(op2) = get_operator(lookahead2) {
588 if op2.precedence() >= op.precedence() {
589 right = match self.parse_binary(right, min + 1) {
590 Ok(ast) => ast,
591 Err(e) => {
592 if e == ErrorKind::EndOfFile {
593 // No error was emitted.
594 let label = Label::primary((), self.lexer.span())
595 .with_message(format!("expected right hand side of expression here."));
596
597 let diagnostic = Diagnostic::error()
598 .with_code("FC0010")
599 .with_labels(vec![label])
600 .with_message(format!("expected right hand side of expression."));
601
602 self.diagnostics.push(diagnostic);
603
604 return Err(ErrorKind::SyntaxError);
605 }
606
607 return Err(e);
608 }
609 };
610
611 tok = self.lexer.clone().next();
612 } else {
613 break;
614 }
615
616 } else {
617 break;
618 }
619 }
620
621
622 left = AstMeta::new(
623 left.range.start..self.lexer.span().end,
624 Ast::BinaryExpression(
625 op,
626 left.as_box(),
627 right.as_box()
628 )
629 );
630 tok = self.lexer.clone().next();
631 } else {
632 self.lexer.next();
633 break;
634 }
635 } else {
636 break;
637 }
638 }
639
640 Ok(left)
641 /*
642 loop {
643 let mut peekable = self.lexer.clone();
644
645 if let Some(tok) = peekable.next() {
646 if let Some(op) = get_operator(tok) {
647 if op.precedence() >= min {
648
649 } else {
650 break;
651 }
652 } else {
653 // The next token isn't an operator, which means the expression is ending.
654 break;
655 }
656 }
657 }*/
658 /*
659 let peekable = self.lexer.clone();
660
661 if let Some(lookahead) = peekable.next() {
662
663 }*/
664 }
665
666 /// Recursively parses function calls and object indexes.
667 fn parse_opt_ending(&mut self, left: AstMeta) -> Result<AstMeta, ErrorKind> {
668 if let Some(tok) = self.lexer.clone().next() {
669 if tok == Token::OParen {
670 self.lexer.next();
671 match self.parse_list(Token::CParen) {
672 Ok(args) => {
673 return self.parse_opt_ending(
674 AstMeta::new(
675 left.range.start..self.lexer.span().end,
676 Ast::FunctionCall(
677 left.as_box(),
678 args
679 )
680 )
681 )
682 },
683 Err(e) => {
684 if e == ErrorKind::EndOfFile {
685 // Throw our own diagnostic messages.
686 // No error was emitted.
687 let label = Label::primary((), left.range.start..self.lexer.span().end)
688 .with_message(format!("this function call's argument list is never closed."));
689
690 let help = Label::secondary((), self.lexer.span())
691 .with_message("try inserting a ')' here.");
692
693 let diagnostic = Diagnostic::error()
694 .with_code("FC0013")
695 .with_labels(vec![label, help])
696 .with_message(format!("argument list never closes."));
697
698 self.diagnostics.push(diagnostic);
699
700 return Err(ErrorKind::SyntaxError);
701 }
702
703 return Err(e);
704 }
705 }
706 } else if tok == Token::Dot || tok == Token::OBrack {
707 let l = left.clone();
708 match self.parse_index(left) {
709 Ok(args) => {
710 return self.parse_opt_ending(args)
711 },
712 Err(e) => {
713 if e == ErrorKind::EndOfFile {
714 // Throw our own diagnostic messages.
715 // No error was emitted.
716 let start = l.range.start;
717 let label = Label::primary((), start..self.lexer.span().end)
718 .with_message(format!("this function call's argument list is never closed."));
719
720 let help = Label::secondary((), self.lexer.span())
721 .with_message("try inserting a ')' here.");
722
723 let diagnostic = Diagnostic::error()
724 .with_code("FC0013")
725 .with_labels(vec![label, help])
726 .with_message(format!("argument list never closes."));
727
728 self.diagnostics.push(diagnostic);
729
730 return Err(ErrorKind::SyntaxError);
731 }
732
733 return Err(e);
734 }
735 }
736 }
737 }
738
739 self.parse_binary(left, 0)
740 }
741
742 /// Wraps the parse_literal function and allows function calls.
743 fn parse_primary(&mut self) -> Result<AstMeta, ErrorKind> {
744 if let Some(tok) = self.lexer.clone().next() {
745 if tok == Token::Exclaimation {
746 self.lexer.next();
747
748 let start = self.lexer.span().start;
749
750 match self.parse_primary() {
751 Ok(ast) => {
752 return Ok(
753 AstMeta::new(
754 start..self.lexer.span().end,
755 Ast::NotUnary(
756 ast.as_box()
757 )
758 )
759 )
760 },
761 Err(e) => {
762 if e == ErrorKind::EndOfFile {
763 let label = Label::primary((), start..self.lexer.span().end)
764 .with_message(format!("'!' expression requires an operand (a.k.a, another expression)."));
765
766 let help = Label::secondary((), self.lexer.span())
767 .with_message("expected an expression here, we see the end of the file.");
768
769 let diagnostic = Diagnostic::error()
770 .with_code("FC0014")
771 .with_labels(vec![label, help])
772 .with_message(format!("expected an expression."));
773
774 self.diagnostics.push(diagnostic);
775
776 return Err(ErrorKind::SyntaxError);
777 }
778
779 return Err(e)
780 },
781 }
782 } else if tok == Token::PreprocessorIdentifier {
783 // Preprocessors do nothing at the base parsing phase.
784 self.lexer.next();
785 let name = self.lexer.slice();
786 let start = self.lexer.span().start;
787 //let name_end = self.lexer.span().end;
788
789 let n = AstMeta::new(
790 self.lexer.span(),
791 Ast::IdentifierLiteral(name[1..].into())
792 );
793
794 if let Some(arg) = self.lexer.clone().next() {
795 if arg == Token::String {
796 self.lexer.next();
797 let t = self.lexer.slice();
798
799 return Ok(
800 AstMeta::new(
801 start..self.lexer.span().end,
802 Ast::PreprocessorStatement(
803 n.as_box(),
804 vec![
805 AstMeta::new(
806 self.lexer.span(),
807 Ast::StringLiteral(t[1..t.len() - 1].into())
808 )
809 ]
810 )
811 )
812 )
813 } else if arg == Token::OParen {
814 self.lexer.next();
815
816 match self.parse_list(Token::CParen) {
817 Ok(ast) => {
818 return Ok(
819 AstMeta::new(
820 start..self.lexer.span().end,
821 Ast::PreprocessorStatement(
822 n.as_box(),
823 ast
824 )
825 )
826 )
827 },
828 Err(e) => return Err(e)
829 }
830 } else if arg == Token::OBrack {
831 self.lexer.next();
832
833 match self.parse_list(Token::CBrack) {
834 Ok(ast) => {
835 return Ok(
836 AstMeta::new(
837 start..self.lexer.span().end,
838 Ast::PreprocessorStatement(
839 n.as_box(),
840 ast
841 )
842 )
843 )
844 },
845 Err(e) => return Err(e)
846 }
847 } else if arg == Token::Identifier {
848 self.lexer.next();
849 let t = self.lexer.slice();
850
851 return Ok(
852 AstMeta::new(
853 start..self.lexer.span().end,
854 Ast::PreprocessorStatement(
855 n.as_box(),
856 vec![
857 AstMeta::new(
858 self.lexer.span(),
859 Ast::IdentifierLiteral(t.into())
860 )
861 ]
862 )
863 )
864 )
865 } else {
866 return Ok(
867 AstMeta::new(
868 start..self.lexer.span().end,
869 Ast::PreprocessorStatement(
870 n.as_box(),
871 vec![]
872 )
873 )
874 )
875 }
876 } else {
877 return Ok(
878 AstMeta::new(
879 start..self.lexer.span().end,
880 Ast::PreprocessorStatement(
881 n.as_box(),
882 vec![]
883 )
884 )
885 )
886 }
887 } else {
888 match self.parse_secondary() {
889 Ok(ast) => return self.parse_opt_ending(ast),
890 Err(e) => return Err(e),
891 }
892 }
893 }
894
895 Err(ErrorKind::EndOfFile)
896 }
897
898 /// Parses a single expression from the lexer, returning a single AST object that represents
899 /// it, or an ErrorKind enum object describing how it ended. If `Err(ErrorKind::EndOfFile)`
900 /// was returned, that only means that there was no expression left, not that an actual
901 /// error occurred.
902 pub fn parse_expression(&mut self) -> Result<AstMeta, ErrorKind> {
903 self.parse_primary()
904 }
905
906 /// Iterates through all tokens until there is no tokens left to read. This will return all
907 /// of the AST items found while parsing, if no errors occur.
908 pub fn parse(&mut self) -> Result<Vec<AstMeta>, ErrorKind> {
909 let mut ast = vec![];
910 loop {
911 // Ignore semicolons by peeking into the lexer's tokens, if there is in fact a
912 // semicolon, it should be skipped over.
913
914 if let Some(tok) = self.lexer.clone().next() {
915 if tok == Token::Semicolon {
916 // Skip over the semicolon and continue the loop.
917 self.lexer.next();
918 continue;
919 }
920
921 match self.parse_expression() {
922 Ok(item) => {
923 ast.push(item);
924
925 if let Some(tok) = self.lexer.clone().next() {
926 if tok == Token::Semicolon {
927 // Skip over the semicolon and continue the loop.
928 self.lexer.next();
929 continue;
930 } else {
931 let label = Label::primary((), self.lexer.span())
932 .with_message(format!("you should add a semicolon after this."));
933
934 let diagnostic = Diagnostic::warning()
935 .with_code("FC0015")
936 .with_labels(vec![label])
937 .with_message(format!("add semicolon to the end of this statement."))
938 .with_notes(vec!["expressions without semicolons can lead to\nunexpected behavior.".into()]);
939 self.diagnostics.push(diagnostic);
940 }
941 }
942 },
943 Err(e) => {
944 if e == ErrorKind::EndOfFile {
945 break;
946 }
947
948 return Err(e)
949 }
950 }
951 } else {
952 break;
953 }
954 }
955
956 Ok(ast)
957 }
958
959}