public FunctionNode(Token sourceToken, IdentifierNode identifier, FunctionParameterNode[] parameters, TypeIdentifierNode type, BlockNode body) : base(sourceToken) { Identifier = identifier; Parameters = parameters; Type = type; Body = body; }
public ASTNode Parse(Token sourceToken, ParseContext context) { var typeID = TypeIdentifierNode.Parse(context); // stupid hack: if we parsed an array type, then "peel off" the last array expression and use it as an array initializer // dumb? yes. works? also yes. if (typeID.IsArray) { if (typeID.ArraySizeExpression == null) { throw new CompileException(typeID.Source, "Array size expected"); } ASTNode sizeExpr = typeID.ArraySizeExpression; typeID.IsArray = false; // TODO: really ought to support nested arrays typeID.ArraySizeExpression = null; return(new NewArrayNode(sourceToken, typeID, sizeExpr)); } else { // otherwise this is a new object expression which invokes a constructor if (!typeID.IsMinimal) { context.Errors.Add(new CompileError(typeID.Source, "Incompatible type for 'new' keyword here")); } context.Expect(TokenType.OpenParenthesis); List <ASTNode> args = new List <ASTNode>(); if (!context.TryMatch(TokenType.CloseParenthesis)) { do { args.Add(context.ParseExpression()); } while(context.TryMatch(TokenType.Comma)); context.Expect(TokenType.CloseParenthesis); } return(new NewNode(sourceToken, typeID, args.ToArray())); } }
public ASTNode Parse(Token sourceToken, ParseContext context) { IdentifierNode interfaceID = context.ParseExpression <IdentifierNode>(); List <TypeIdentifierNode> interfaces = new List <TypeIdentifierNode>(); if (context.TryMatch(TokenType.Colon)) { do { TypeIdentifierNode interfaceType = TypeIdentifierNode.ParseMinimal(context); interfaces.Add(interfaceType); } while(context.TryMatch(TokenType.Comma)); } BlockNode block = context.ParseExpression <BlockNode>(); List <FunctionNode> functions = new List <FunctionNode>(); foreach (var expr in block.Children) { if (expr is FunctionNode func) { if (func.Body != null) { context.Errors.Add(new CompileError(func.Source, "Interface function definition must be abstract")); } else { functions.Add(func); } } else { context.Errors.Add(new CompileError(expr.Source, "Only functions can be declared in an interface block")); } } return(new InterfaceNode(sourceToken, interfaceID, interfaces.ToArray(), functions.ToArray())); }
public ASTNode Parse(Token sourceToken, ParseContext context) { var identifier = context.ParseExpression <IdentifierNode>(); context.Expect(TokenType.OpenParenthesis); List <FunctionParameterNode> parameters = new List <FunctionParameterNode>(); if (!context.TryMatch(TokenType.CloseParenthesis)) { do { parameters.Add(FunctionParameterNode.Parse(context)); } while(context.TryMatch(TokenType.Comma)); context.Expect(TokenType.CloseParenthesis); } // note: type is optional, but if omitted means "void" is assumed TypeIdentifierNode type = null; if (context.TryMatch(TokenType.Colon)) { type = TypeIdentifierNode.Parse(context); } if (context.TryMatch(TokenType.Semicolon)) { return(new FunctionNode(sourceToken, identifier, parameters.ToArray(), type, null)); } else { BlockNode body = context.ParseExpression <BlockNode>(); return(new FunctionNode(sourceToken, identifier, parameters.ToArray(), type, body)); } }
public NewNode(Token sourceToken, TypeIdentifierNode type, ASTNode[] args) : base(sourceToken) { Type = type; ConstructorArguments = args; }
public NewArrayNode(Token sourceToken, TypeIdentifierNode type, ASTNode sizeExpr) : base(sourceToken) { Type = type; SizeExpr = sizeExpr; }