Example #1
0
 internal void Accept(NodeEndL endl)
 {
     builder.currentLineNumber = endl.EndLine;
     builder.OpEndL();
 }
Example #2
0
 void ASTVisitor.Accept(NodeEndL value)
 {
     Accept(value);
 }
Example #3
0
 private Node PrimaryExpression(bool allowPostfixInvocation = true)
 {
     if (!TokensRemain)
         return null;
     var loc = Location;
     Node node;
     switch (Current.type)
     {
         case WILDCARD:
             // If we aren't in a truly anon function, we ignore this
             if (CurrentFunction != null && CurrentFunction.fullAnon && CurrentFunction.paramNames.Count == 0)
                 CurrentFunction.paramNames.Add(null);
             node = new NodeWildcard(loc);
             Advance();
             break;
         case PARAM_INDEX:
             var index = (uint)Current.intValue;
             // If we aren't in a truly anon function, we ignore this
             if (CurrentFunction != null && CurrentFunction.fullAnon)
                 while (CurrentFunction.paramNames.Count <= index)
                     CurrentFunction.paramNames.Add(null);
             node = new NodeParamIndex(loc, index);
             Advance();
             break;
         case IDENTIFIER:
             node = new NodeIdentifier(loc, Current.image);
             Advance();
             break;
         case SYMBOL:
             node = new NodeSymbol(loc, Current.image);
             Advance();
             break;
         case NULL:
             node = new NodeNull(loc);
             Advance();
             break;
         case TRUE:
         case FALSE:
             node = new NodeBool(loc, Check(TRUE));
             Advance();
             break;
         case ENDL:
             node = new NodeEndL(loc);
             Advance();
             break;
         case THIS:
             node = new NodeThis(loc);
             Advance();
             break;
         case SELF:
             node = new NodeSelf(loc);
             Advance();
             break;
         case INT:
             node = new NodeInt(loc, Current.intValue);
             Advance();
             break;
         case FLOAT:
             node = new NodeFloat(loc, Current.floatValue);
             Advance();
             break;
         case STRING:
             node = new NodeString(loc, Current.image);
             Advance();
             break;
         case OPEN_BRACE:
             Advance();
             if (Check(CLOSE_BRACE))
             {
                 // 0-length tuple:
                 node = new NodeTuple(loc, new List<Node>());
                 node.EndLine = Current.location.line;
                 Advance();
             }
             else
             {
                 var values = CommaExpressions();
                 if (values.Count != 1)
                 {
                     // This is a tuple :D
                     node = new NodeTuple(loc, values);
                     Expect(CLOSE_BRACE, "Closing brace (')') expected to end tuple expression.");
                     node.EndLine = tokens[-1].location.line;
                 }
                 else
                 {
                     Expect(CLOSE_BRACE, "Closing brace (')') expected to surround expression.");
                     // Just an expression, carry on:
                     node = values[0];
                 }
             }
             break;
         case OPEN_SQUARE_BRACE:
             // This is a list :D
             Advance();
             node = new NodeList(loc, (TokensRemain && Current.type != CLOSE_SQUARE_BRACE) ? CommaExpressions() : new List<Node>());
             Expect(CLOSE_SQUARE_BRACE, "Closing square brace (']') expected to end list expression.");
             node.EndLine = tokens[-1].location.line;
             break;
         case OPEN_CURLY_BRACE:
             // This is a code block :D
             Advance();
             var exprs = new List<Node>();
             while (!Check(CLOSE_CURLY_BRACE))
             {
                 if (!TokensRemain)
                 {
                     log.Error(tokens[-1].location, "Unfinished block. A closing curly brace ('}') should be used to end blocks.");
                     break;
                 }
                 var expr = Expression();
                 if (expr != null)
                     exprs.Add(expr);
             }
             Expect(CLOSE_CURLY_BRACE, "Closing curly brace ('}') expected to end block.");
             node = new NodeBlock(loc, exprs);
             node.EndLine = tokens[-1].location.line;
             break;
         case TAILREC:
             Advance();
             Expect(OPEN_BRACE, "Expected an open brace ('(') to begin the tailrec argument list.");
             List<Node> args;
             if (!Check(CLOSE_BRACE))
                 args = CommaExpressions();
             else args = new List<Node>();
             Expect(CLOSE_BRACE, "Expected a close brace (')') to end the tailrec argument list.");
             node = new NodeTailRec(loc, args);
             break;
         // These can't be postfix'd, so we don't allow it.
         case OPERATOR:
             var prefix = Current.image;
             Advance();
             if (!TokensRemain)
                 log.Error(loc, "An expression is expected after prefix operator, but the end of the file was reached.");
             var prefixValue = PrimaryExpression();
             return new NodePrefix(loc, prefix, prefixValue);
         case NOT:
             Advance();
             if (!TokensRemain)
                 log.Error(loc, "An expression is expected after the 'not' keyword, but the end of the file was reached.");
             return new NodeNot(loc, Expression());
         case THROW:
             Advance();
             if (!TokensRemain)
                 log.Error(loc, "An expression is expected after the 'throw' keyword, but the end of the file was reached.");
             return new NodeThrow(loc, Expression());
         case YIELD:
             Advance();
             if (!TokensRemain)
                 log.Error(loc, "An expression is expected after the 'yield' keyword, but the end of the file was reached.");
             return new NodeYield(loc, Expression());
         case RES:
             Advance();
             if (!TokensRemain)
                 log.Error(loc, "An expression is expected after the 'res' keyword, but the end of the file was reached.");
             return new NodeRes(loc, Expression());
         case BREAK:
             Advance();
             string bLabel = null;
             if (Check(IDENTIFIER) && Current.location.line == loc.line)
             {
                 bLabel = Current.image;
                 Advance();
             }
             return new NodeBreak(loc, bLabel);
         case CONT:
             Advance();
             string cLabel = null;
             if (Check(IDENTIFIER) && Current.location.line == loc.line)
             {
                 cLabel = Current.image;
                 Advance();
             }
             return new NodeCont(loc, cLabel);
         case FN: return ParseFn();
         case GEN: return ParseFn(true);
         case VAR: return ParseVar();
         case IF: return ParseIf();
         case WHILE: return ParseWhile();
         case TRY: return ParseTry();
         case ITER: return ParseIter();
         case EACH: return ParseEach();
         // And here, we don't know what they want... oops.
         default:
             log.Error(Location, "Unexpected token '{0}', skipping...", Current.ToString());
             // We don't know what to do with this, let's skip and try to recover.
             Advance();
             // Error saying we couldn't understand the token:
             // return a new primary expression.
             return PrimaryExpression();
     }
     // TODO postfix
     return Postfix(node, allowPostfixInvocation);
 }