private static AstNode ParseClass (TokenStream stream) { stream.Expect (TokenClass.Keyword, "class"); string name = stream.Expect (TokenClass.Identifier).Value; List<string> baseClass = new List<string> (); if (stream.Accept (TokenClass.Colon)) { do { baseClass.Add (ParseClassName (stream)); } while (stream.Accept (TokenClass.Comma)); } ClassDeclaration clazz = new ClassDeclaration (stream.Location, name, baseClass); stream.Expect (TokenClass.OpenBrace); while (!stream.Match (TokenClass.CloseBrace)) { if (stream.Match (TokenClass.Keyword, "func") || stream.Match (TokenClass.Operator, "@")) { FunctionDeclaration func = ParseFunction (stream, false, clazz) as FunctionDeclaration; if (func.Name == name) { clazz.Constructor = func; } else { clazz.Add (func); } } else { clazz.Add (ParseStatement (stream)); } } stream.Expect (TokenClass.CloseBrace); return clazz; }
public static AstNode ParseAnd(TokenStream stream) { AstNode expr = ParseEquals (stream); while (stream.Accept (TokenClass.Operator, "&")) { expr = new BinaryExpression (stream.Location, BinaryOperation.And, expr, ParseEquals (stream)); } return expr; }
public TokenStream Scan() { TokenStream retStream = new TokenStream (errorLog); EatWhiteSpaces (); while (PeekChar () != -1) { Token nextToken = NextToken (); if (nextToken != null) retStream.AddToken (nextToken); EatWhiteSpaces (); } return retStream; }
public TokenStream Scan () { TokenStream retStream = new TokenStream (errorLog); EatWhiteSpaces (); while (PeekChar () != -1) { Token nextToken = NextToken (); if (nextToken != null) retStream.AddToken (nextToken); EatWhiteSpaces (); } if (errorLog.ErrorCount > 0) { throw new SyntaxException (errorLog); } return retStream; }
public static AstNode ParseAdditive(TokenStream stream) { AstNode expr = ParseMultiplicative (stream); while (stream.Match (TokenClass.Operator)) { switch (stream.Current.Value) { case "+": stream.Accept (TokenClass.Operator); expr = new BinaryExpression (stream.Location, BinaryOperation.Add, expr, ParseMultiplicative (stream)); continue; case "-": stream.Accept (TokenClass.Operator); expr = new BinaryExpression (stream.Location, BinaryOperation.Sub, expr, ParseMultiplicative (stream)); continue; default: break; } break; } return expr; }
private static AstNode ParseHash(TokenStream stream) { stream.Expect (TokenClass.OpenBrace); HashExpression ret = new HashExpression (stream.Location); while (!stream.Match (TokenClass.CloseBrace)) { ret.Add (ParseExpression (stream)); stream.Expect (TokenClass.Colon); ret.Add (ParseExpression (stream)); if (!stream.Accept (TokenClass.Comma)) { break; } } stream.Expect (TokenClass.CloseBrace); return ret; }
private static AstNode ParseIf(TokenStream stream) { IfStatement ifStmt = new IfStatement (stream.Location); stream.Expect (TokenClass.Keyword, "if"); stream.Expect (TokenClass.OpenParan); ifStmt.Add (ParseExpression (stream)); stream.Expect (TokenClass.CloseParan); ifStmt.Add (ParseStatement (stream)); if (stream.Accept (TokenClass.Keyword, "else")) { ifStmt.Add (ParseStatement (stream)); } else { ifStmt.Add (new CodeBlock (stream.Location)); } return ifStmt; }
private static AstNode ParseBoolOr(TokenStream stream) { AstNode expr = ParseBoolAnd (stream); while (stream.Match (TokenClass.Operator)) { switch (stream.Current.Value) { case "||": stream.Accept (TokenClass.Operator); expr = new BinaryExpression (stream.Location, BinaryOperation.BoolOr, expr, ParseBoolAnd (stream)); continue; case "??": stream.Accept (TokenClass.Operator); expr = new BinaryExpression (stream.Location, BinaryOperation.NullCoalescing, expr, ParseBoolAnd (stream)); continue; default: break; } break; } return expr; }
private static AstNode ParseGiven(TokenStream stream) { GivenStatement switchStmt = new GivenStatement (stream.Location); stream.Expect (TokenClass.Keyword, "given"); stream.Expect (TokenClass.OpenParan); switchStmt.Add (ParseExpression (stream)); stream.Expect (TokenClass.CloseParan); stream.Expect (TokenClass.OpenBrace); AstNode defaultBlock = new AstRoot (stream.Location); AstRoot caseStatements = new AstRoot (stream.Location); while (!stream.EndOfStream && !stream.Match (TokenClass.CloseBrace)) { caseStatements.Add (ParseWhen (stream)); if (stream.Accept (TokenClass.Keyword, "default")) { defaultBlock = ParseStatement (stream); } } switchStmt.Add (caseStatements); switchStmt.Add (defaultBlock); stream.Expect (TokenClass.CloseBrace); return switchStmt; }
private static AstNode ParseMatch(TokenStream stream) { MatchExpression expr = new MatchExpression (stream.Location); stream.Expect (TokenClass.Keyword, "match"); expr.Add (ParseExpression (stream)); stream.Expect (TokenClass.OpenBrace); while (stream.Accept (TokenClass.Keyword, "case")) { AstNode condition = null; AstNode pattern = ParsePattern (stream); if (stream.Accept (TokenClass.Keyword, "when")) { condition = ParseExpression (stream); } stream.Expect (TokenClass.Operator, "=>"); AstNode value = ParseExpression (stream); expr.Children.Add (new CaseExpression (pattern.Location, pattern, condition, value)); } stream.Expect (TokenClass.CloseBrace); return expr; }
private static AstNode ParsePattern(TokenStream stream) { return ParsePatternOr (stream); }
private static AstNode ParseForeach(TokenStream stream) { stream.Expect (TokenClass.Keyword, "foreach"); stream.Expect (TokenClass.OpenParan); Token identifier = stream.Expect (TokenClass.Identifier); stream.Expect (TokenClass.Keyword, "in"); AstNode expr = ParseExpression (stream); stream.Expect (TokenClass.CloseParan); AstNode body = ParseStatement (stream); return new ForeachStatement (stream.Location, identifier.Value, expr, body); }
private static AstNode ParseLambda(TokenStream stream) { stream.Expect (TokenClass.Keyword, "lambda"); bool isInstanceMethod; bool isVariadic; bool acceptsKwargs; List<string> parameters = ParseFuncParameters (stream, out isInstanceMethod, out isVariadic, out acceptsKwargs); LambdaExpression decl = new LambdaExpression (stream.Location, isInstanceMethod, isVariadic, acceptsKwargs, parameters); if (stream.Accept (TokenClass.Operator, "=>")) decl.Add (new ReturnStatement (stream.Location, ParseExpression (stream))); else decl.Add (ParseStatement (stream)); return decl; }
private static AstNode ParseExpression(TokenStream stream) { return ParseAssign (stream); }
private static AstNode ParseFor(TokenStream stream) { ForStatement ret = new ForStatement (stream.Location); stream.Expect (TokenClass.Keyword, "for"); stream.Expect (TokenClass.OpenParan); ret.Add (new Expression (stream.Location, ParseExpression (stream))); stream.Expect (TokenClass.SemiColon); ret.Add (ParseExpression (stream)); stream.Expect (TokenClass.SemiColon); ret.Add (new Expression (stream.Location, ParseExpression (stream))); stream.Expect (TokenClass.CloseParan); ret.Add (ParseStatement (stream)); return ret; }
private static AstNode ParseEnum(TokenStream stream) { stream.Expect (TokenClass.Keyword, "enum"); string name = stream.Expect (TokenClass.Identifier).Value; EnumDeclaration decl = new EnumDeclaration (stream.Location, name); stream.Expect (TokenClass.OpenBrace); int defaultVal = -1; while (!stream.Match (TokenClass.CloseBrace)) { string ident = stream.Expect (TokenClass.Identifier).Value; if (stream.Accept (TokenClass.Operator, "=")) { string val = stream.Expect (TokenClass.IntLiteral).Value; int numVal = 0; if (val != "") { numVal = Int32.Parse (val); } decl.Items [ident] = numVal; } else { decl.Items [ident] = defaultVal--; } if (!stream.Accept (TokenClass.Comma)) { break; } } stream.Expect (TokenClass.CloseBrace); return decl; }
private static AstNode ParseDoWhile(TokenStream stream) { DoStatement ret = new DoStatement (stream.Location); stream.Expect (TokenClass.Keyword, "do"); ret.Add (ParseStatement (stream)); stream.Expect (TokenClass.Keyword, "while"); stream.Expect (TokenClass.OpenParan); ret.Add (ParseExpression (stream)); stream.Expect (TokenClass.CloseParan); return ret; }
private static string ParseClassName(TokenStream stream) { StringBuilder ret = new StringBuilder (); do { string attr = stream.Expect (TokenClass.Identifier).Value; ret.Append (attr); if (stream.Match (TokenClass.Operator, ".")) ret.Append ('.'); } while (stream.Accept (TokenClass.Operator, ".")); return ret.ToString (); }
private static AstNode ParseIndexer(AstNode lvalue, TokenStream stream) { stream.Expect (TokenClass.OpenBracket); AstNode index = ParseExpression (stream); stream.Expect (TokenClass.CloseBracket); return new IndexerExpression (stream.Location, lvalue, index); }
private static List<string> ParseFuncParameters(TokenStream stream, out bool isInstanceMethod, out bool isVariadic, out bool hasKeywordArgs) { isVariadic = false; hasKeywordArgs = false; isInstanceMethod = false; List<string> ret = new List<string> (); stream.Expect (TokenClass.OpenParan); if (stream.Accept (TokenClass.Keyword, "self")) { isInstanceMethod = true; if (!stream.Accept (TokenClass.Comma)) { stream.Expect (TokenClass.CloseParan); return ret; } } while (!stream.Match (TokenClass.CloseParan)) { if (!hasKeywordArgs && stream.Accept (TokenClass.Operator, "*")) { if (stream.Accept (TokenClass.Operator, "*")) { hasKeywordArgs = true; Token ident = stream.Expect (TokenClass.Identifier); ret.Add (ident.Value); } else { isVariadic = true; Token ident = stream.Expect (TokenClass.Identifier); ret.Add (ident.Value); } } else { if (hasKeywordArgs) { stream.ErrorLog.AddError (ErrorType.ParserError, stream.Location, "Argument after keyword arguments!"); } if (isVariadic) { stream.ErrorLog.AddError (ErrorType.ParserError, stream.Location, "Argument after params keyword!"); } Token param = stream.Expect (TokenClass.Identifier); ret.Add (param.Value); } if (!stream.Accept (TokenClass.Comma)) { break; } } stream.Expect (TokenClass.CloseParan); return ret; }
private static AstNode ParseInterface(TokenStream stream) { stream.Expect (TokenClass.Keyword, "interface"); string name = stream.Expect (TokenClass.Identifier).Value; InterfaceDeclaration contract = new InterfaceDeclaration (stream.Location, name); stream.Expect (TokenClass.OpenBrace); while (!stream.Match (TokenClass.CloseBrace)) { if (stream.Match (TokenClass.Keyword, "func")) { FunctionDeclaration func = ParseFunction (stream, true) as FunctionDeclaration; contract.Add (func); } else { stream.ErrorLog.AddError (ErrorType.ParserError, stream.Location, "Interface may only contain function prototypes!"); } while (stream.Accept (TokenClass.SemiColon)); } stream.Expect (TokenClass.CloseBrace); return contract; }
private static AstNode ParsePatternTerm(TokenStream stream) { return ParseTerm (stream); }
private static AstNode ParseList(TokenStream stream) { stream.Expect (TokenClass.OpenBracket); ListExpression ret = new ListExpression (stream.Location); while (!stream.Match (TokenClass.CloseBracket)) { AstNode expr = ParseExpression (stream); if (stream.Accept (TokenClass.Keyword, "for")) { string ident = stream.Expect (TokenClass.Identifier).Value; stream.Expect (TokenClass.Keyword, "in"); AstNode iterator = ParseExpression (stream); AstNode predicate = null; if (stream.Accept (TokenClass.Keyword, "when")) { predicate = ParseExpression (stream); } stream.Expect (TokenClass.CloseBracket); return new ListCompExpression (expr.Location, expr, ident, iterator, predicate); } ret.Add (expr); if (!stream.Accept (TokenClass.Comma)) { break; } } stream.Expect (TokenClass.CloseBracket); return ret; }
private static AstNode ParseBoolAnd(TokenStream stream) { AstNode expr = ParseOr (stream); while (stream.Accept (TokenClass.Operator, "&&")) { expr = new BinaryExpression (stream.Location, BinaryOperation.BoolAnd, expr, ParseOr (stream)); } return expr; }
private static string ParseModuleName(TokenStream stream) { Token initIdent = stream.Expect (TokenClass.Identifier); if (stream.Match (TokenClass.Operator, ".")) { StringBuilder accum = new StringBuilder (); accum.Append (initIdent.Value); while (stream.Accept (TokenClass.Operator, ".")) { Token ident = stream.Expect (TokenClass.Identifier); accum.Append (Path.DirectorySeparatorChar); accum.Append (ident.Value); } return accum.ToString (); } else { return initIdent.Value; } }
private static AstNode ParseGet(AstNode lvalue, TokenStream stream) { stream.Expect (TokenClass.Operator, "."); Token ident = stream.Expect (TokenClass.Identifier); return new GetExpression (stream.Location, lvalue, ident.Value); }
private static AstNode ParsePatternOr(TokenStream stream) { AstNode expr = ParsePatternAnd (stream); while (stream.Match (TokenClass.Operator, "|")) { stream.Accept (TokenClass.Operator); expr = new BinaryExpression (stream.Location, BinaryOperation.Or, expr, ParsePatternAnd (stream)); } return expr; }
public Parser(TokenStream tokenStream) { this.tokenStream = tokenStream; }
private static AstNode ParsePipeline(TokenStream stream) { AstNode expr = ParseRange (stream); while (stream.Accept (TokenClass.Operator, "|>")) { CallExpression call = ParseRange (stream) as CallExpression; if (call == null) { stream.ErrorLog.AddError (ErrorType.ParserError, stream.Location, "Right value must be function call"); } else { call.Arguments.Children.Insert (0, expr); expr = call; } } return expr; }
private static AstNode ParseFunction(TokenStream stream, bool prototype = false, ClassDeclaration cdecl = null) { if (stream.Accept (TokenClass.Operator, "@")) { /* * Function decorators in the form of * @myDecorator * func foo () { * } * are merely syntatic sugar for * func foo () { * } * foo = myDecorator (foo) */ AstNode expr = ParseExpression (stream); // Decorator expression /* This is the original function which is to be decorated */ FunctionDeclaration idecl = ParseFunction (stream, prototype, cdecl) as FunctionDeclaration; /* We must construct an arglist which will be passed to the decorator */ ArgumentList args = new ArgumentList (stream.Location); args.Add (new NameExpression (stream.Location, idecl.Name)); /* * Since two values can not be returned, we must return a single node containing both * the function declaration and call to the decorator */ AstRoot nodes = new AstRoot (stream.Location); nodes.Add (idecl); nodes.Add (new Expression (stream.Location, new BinaryExpression (stream.Location, BinaryOperation.Assign, new NameExpression (stream.Location, idecl.Name), new CallExpression (stream.Location, expr, args)))); return nodes; } stream.Expect (TokenClass.Keyword, "func"); bool isInstanceMethod; bool isVariadic; bool hasKeywordArgs; Token ident = stream.Expect (TokenClass.Identifier); List<string> parameters = ParseFuncParameters (stream, out isInstanceMethod, out isVariadic, out hasKeywordArgs); FunctionDeclaration decl = new FunctionDeclaration (stream.Location, ident != null ? ident.Value : "", isInstanceMethod, isVariadic, hasKeywordArgs, parameters); if (!prototype) { if (stream.Accept (TokenClass.Operator, "=>")) { decl.Add (new ReturnStatement (stream.Location, ParseExpression (stream))); } else { stream.Expect (TokenClass.OpenBrace); CodeBlock scope = new CodeBlock (stream.Location); if (stream.Match (TokenClass.Keyword, "super")) { scope.Add (ParseSuperCall (stream, cdecl)); } while (!stream.Match (TokenClass.CloseBrace)) { scope.Add (ParseStatement (stream)); } decl.Add (scope); stream.Expect (TokenClass.CloseBrace); } } return decl; }