private static AstNode ParseArgumentList(TokenStream stream) { ArgumentList argList = new ArgumentList (stream.Location); stream.Expect (TokenClass.OpenParan); KeywordArgumentList kwargs = null; while (!stream.Match (TokenClass.CloseParan)) { if (stream.Accept (TokenClass.Operator, "*")) { argList.Packed = true; argList.Add (ParseExpression (stream)); break; } AstNode arg = ParseExpression (stream); if (stream.Accept (TokenClass.Colon)) { if (kwargs == null) { kwargs = new KeywordArgumentList (arg.Location); } NameExpression ident = arg as NameExpression; AstNode val = ParseExpression (stream); if (ident == null) { stream.ErrorLog.AddError (ErrorType.ParserError, arg.Location, "Keyword must be a valid identifier"); } else { kwargs.Add (ident.Value, val); } } else argList.Add (arg); if (!stream.Accept (TokenClass.Comma)) { break; } } if (kwargs != null) { argList.Add (kwargs); } stream.Expect (TokenClass.CloseParan); return argList; }
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; }
private static ArgumentList ParseTypeList(TokenStream stream) { ArgumentList argList = new ArgumentList (stream.Location); while (!stream.Match (TokenClass.CloseParan)) { argList.Add (ParseExpression (stream)); if (!stream.Accept (TokenClass.Comma)) { break; } } return argList; }