33#define RSMS_PARSER_H
44
55#include " TokenBuffer.h"
6+ #include " ../Logger.h"
67#include " ../ast/Node.h"
78#include " ../ast/Block.h"
89#include " ../ast/Expression.h"
910#include " ../ast/Function.h"
1011
1112#include < vector>
1213
13- #define DEBUG_PARSER 0
14+ #define DEBUG_PARSER 1
1415#if DEBUG_PARSER
1516 #include " ../DebugTrace.h"
1617 #define DEBUG_TRACE_PARSER DEBUG_TRACE
@@ -29,9 +30,11 @@ static int BinaryOperatorPrecedence(const Token& token) {
2930 return -1 ;
3031 switch (token.stringValue [0 ]) {
3132 case ' *' : return 40 ;
33+ case ' /' : return 40 ;
3234 case ' -' : return 20 ;
3335 case ' +' : return 20 ;
3436 case ' <' : return 10 ;
37+ case ' >' : return 10 ;
3538 default : return -1 ;
3639 }
3740}
@@ -60,6 +63,7 @@ class Parser {
6063 uint32_t previousLineIndentation_ = 0 ;
6164 uint32_t currentLineIndentation_ = 0 ;
6265
66+ std::vector<Token> recentComments_;
6367 std::vector<std::string> errors_;
6468 // std::vector<std::string> warnings_;
6569 // std::vector<std::string> notices_;
@@ -429,12 +433,42 @@ class Parser {
429433 return (Function*)error (" Expected '->' after function interface" );
430434 }
431435 nextToken (); // eat '->'
436+
437+ // Is this potentially a multi-expression function body?
438+ uint32_t bodyStartedAtLineIndentation = UINT32_MAX ;
439+ if (token_.type == Token::NewLine) {
440+ rlog (" Yup, potentially a multi-expression func body ahead. line ind (prev/curr): "
441+ << previousLineIndentation_ << ' /' << currentLineIndentation_);
442+ bodyStartedAtLineIndentation = currentLineIndentation_;
443+ }
432444
433445 // Parse function body
434- Expression *body = parseExpression ();
435- if (body == 0 ) {
436- delete interface;
437- return 0 ;
446+ Block* body = new Block;
447+
448+ while (1 ) {
449+ // Read one expression
450+ Expression *expr = parseExpression ();
451+ if (expr == 0 ) {
452+ delete interface;
453+ return 0 ;
454+ }
455+
456+ // Add the expression to the function body
457+ body->addNode (expr);
458+
459+ // If we know this is a single-expression body, break after the first expression
460+ if (bodyStartedAtLineIndentation == UINT32_MAX ) {
461+ rlog (" Body ended (single-expression body)" );
462+ break ;
463+ } else {
464+
465+ // Body ends when we either get a non-newline (e.g. a terminating) token, or the
466+ // line indentation drops below the first line of the body
467+ if (token_.type != Token::NewLine || currentLineIndentation_ < bodyStartedAtLineIndentation) {
468+ rlog (" Body ended (" << (token_.type != Token::NewLine ? " line indent drop" : " terminating token" ) << " )" );
469+ break ;
470+ }
471+ }
438472 }
439473
440474 return new Function (interface, body);
@@ -491,6 +525,14 @@ class Parser {
491525 Expression *lhs = parsePrimary ();
492526 if (!lhs) return 0 ;
493527
528+ // // Backslash means "ignore the following sequence of linebreaks and comments
529+ // // and treat whatever is after it as the same line"
530+ // if (token_.type == Token::Backslash) {
531+ // // Eat <comment>*<LF><comment>* and continue
532+ // while (nextToken(/* newLineUpdatesLineIndentation = */false).type == Token::NewLine
533+ // || token_.type == Token::Comment ) {}
534+ // }
535+
494536 if (token_.type == Token::BinaryOperator) {
495537 // LHS binop RHS
496538 return parseBinOpRHS (0 , lhs);
@@ -501,12 +543,11 @@ class Parser {
501543 if (!assignment) delete lhs;
502544 return assignment;
503545 } else if (token_.type == Token::Unexpected) {
504- error (" Unexpected token when expecting a left-hand side expression" );
546+ error (" Unexpected token when expecting a left-hand- side expression" );
505547 nextToken (); // Skip token for error recovery.
506548 delete lhs;
507549 return 0 ;
508550 } else {
509- // LHS
510551 return lhs;
511552 }
512553 }
@@ -561,12 +602,23 @@ class Parser {
561602 nextToken ();
562603 goto entry;
563604 }
564- default : return error (" Unexpected token when expecting an expression " );
605+ default : return error (" Unexpected token when expecting: id|intlit|floatlit|func|external|comment|newline " );
565606 }
566607 }
567608
568609 // ------------------------------------------------------------------------
569610
611+ inline const Token& _nextToken () {
612+ if (token_.isNull ()) {
613+ token_ = const_cast <Token&>(tokens_.next ());
614+ futureToken_ = const_cast <Token&>(tokens_.next ());
615+ } else {
616+ token_ = futureToken_;
617+ futureToken_ = const_cast <Token&>(tokens_.next ());
618+ }
619+ return token_;
620+ }
621+
570622 // nextToken() -- Advances the token stream one token forward and returns
571623 // the new token (a reference to the token_ instance variable).
572624 //
@@ -587,14 +639,37 @@ class Parser {
587639 // The previous line number can be aquired from token_.line-1
588640 //
589641 const Token& nextToken () {
590- if (token_.isNull ()) {
591- token_ = const_cast <Token&>(tokens_.next ());
592- futureToken_ = const_cast <Token&>(tokens_.next ());
642+ _nextToken ();
643+
644+ recentComments_.clear ();
645+
646+ // Backslash means "ignore the following sequence of linebreaks and comments
647+ // and treat whatever is after it as the same line"
648+ if (token_.type == Token::Backslash) {
649+ // Eat <comment>*<LF><comment>*
650+ while (1 ) {
651+ _nextToken ();
652+ if (token_.type == Token::Comment) {
653+ recentComments_.push_back (token_);
654+ } else if (token_.type != Token::NewLine) {
655+ break ;
656+ }
657+ }
593658 } else {
594- token_ = futureToken_;
595- futureToken_ = const_cast <Token&>(tokens_.next ());
659+ // Eat <comment>*
660+ while (token_.type == Token::Comment) {
661+ recentComments_.push_back (token_);
662+ _nextToken ();
663+ }
596664 }
597665
666+ // if (recentComments_.size()) {
667+ // std::vector<Token>::const_iterator it = recentComments_.begin();
668+ // for (; it != recentComments_.end(); ++it) {
669+ // rlog("recentComments_[" << "] = " << (*it).toString());
670+ // }
671+ // }
672+
598673 #if DEBUG_PARSER
599674 fprintf (stderr, " \e[34;1m>> %s\e[0m\n " , token_.toString ().c_str ());
600675 #endif
0 commit comments