private List <Action> ParseBlock() { List <Action> actions = new List <Action>(); while (Peek().type != Token.TokenType.BraceClose) { if (Peek().type == Token.TokenType.Semicolon) { Consume(Token.TokenType.Semicolon); continue; } if (Peek().type == Token.TokenType.BraceOpen) { Consume(Token.TokenType.BraceOpen); continue; } // Instructions if (Peek().type == Token.TokenType.FuncName) // Means we are calling a void function { string fnName = Consume(Token.TokenType.FuncName).content; Function func = this.program.functions.Find(f => f.name == fnName); List <Expression> arguments = ParseFunctionArguments(); Consume(Token.TokenType.Semicolon); actions.Add(new FunctionCall() { function = func, arguments = arguments }); } else if (Peek().type == Token.TokenType.TypeName) { // Declaring a local variable! Token typeName = Consume(Token.TokenType.TypeName); string newVarName = Consume(Token.TokenType.VarName).content; Variable.VarType newVarType; switch (typeName.content) { case "int": { newVarType = Variable.VarType.Int; } break; case "int*": { newVarType = Variable.VarType.IntPtr; } break; default: { throw new InvalidTypeException(typeName.content); } } Expression initValue; // Are we initializing with a value? if (Peek().type == Token.TokenType.OpAssign) { Consume(Token.TokenType.OpAssign); initValue = ParseExpression(); } else { initValue = new LiteralConstant() { value = 0 }; } Variable newVar = new Variable { name = newVarName, type = newVarType }; currentLocals.Add(newVar); actions.Add(new LocalVarDeclaration() { variable = newVar, initValue = initValue }); } else if (Peek().type == Token.TokenType.VarName) { // Variable assignment! Token targetName = Consume(Token.TokenType.VarName); Consume(Token.TokenType.OpAssign); // What value? Expression newVal = ParseExpression(); // Is it a global? if (program.globalVars.Any(v => v.name == targetName.content)) { actions.Add(new GlobalVarAssignment() { variable = program.globalVars.Find(v => v.name == targetName.content), newValue = newVal }); } else { actions.Add(new VarAssignment() { variable = this.currentLocals.Find(v => v.name == targetName.content), newValue = newVal }); } } else if (Peek().type == Token.TokenType.Assembly) { Token inlineAsm = Consume(Token.TokenType.Assembly); actions.Add(new InlineAssembly() { code = inlineAsm.content.Split(";").ToList() }); } else if (Peek().type == Token.TokenType.KwIf) { Consume(Token.TokenType.KwIf); Consume(Token.TokenType.ParenOpen); Expression condition = ParseExpression(); Consume(Token.TokenType.ParenClose); List <Action> body = ParseBlock(); if (Peek().type == Token.TokenType.KwElse) { Consume(Token.TokenType.BraceOpen); List <Action> elseBody = ParseBlock(); actions.Add(new IfElse() { condition = condition, ifActions = body, elseActions = elseBody }); } else { actions.Add(new If() { condition = condition, ifActions = body }); } } else if (Peek().type == Token.TokenType.KwWhile) { Consume(Token.TokenType.KwWhile); Consume(Token.TokenType.ParenOpen); Expression condition = ParseExpression(); List <Action> body = ParseBlock(); actions.Add(new While() { condition = condition, actions = body }); } //TODO: For //TODO: Goto else if (Peek().type == Token.TokenType.KwReturn) { Consume(Token.TokenType.KwReturn); if (Peek().type == Token.TokenType.Semicolon) { Consume(Token.TokenType.Semicolon); actions.Add(new ReturnInstruction() { returnValue = null }); } else { Expression returnValue = ParseExpression(); actions.Add(new ReturnInstruction() { returnValue = returnValue }); } } else { throw new UnexpectedTokenException(Consume()); } } if (Peek().type == Token.TokenType.BraceClose) { Consume(Token.TokenType.BraceClose); } return(actions); }
private Expression ParseExpression() { // What's the first token? if (Peek().type == Token.TokenType.LiteralInt) { Expression firstLiteral = new LiteralConstant() { value = int.Parse(Consume(Token.TokenType.LiteralInt).content) }; var restOfExpr = RestOfExpr(firstLiteral); if (restOfExpr is null) { return(firstLiteral); } else { return(restOfExpr); } } else if (Peek().type == Token.TokenType.LiteralChar) { Expression firstLiteral = new LiteralConstant() { value = char.Parse(Consume(Token.TokenType.LiteralChar).content) }; var restOfExpr = RestOfExpr(firstLiteral); if (restOfExpr is null) { return(firstLiteral); } else { return(restOfExpr); } } else if (Peek().type == Token.TokenType.ParenOpen) { // Sub-expression Consume(Token.TokenType.ParenOpen); Expression subExpr = ParseExpression(); Consume(Token.TokenType.ParenClose); var restOfExpr = RestOfExpr(subExpr); if (restOfExpr is null) { return(subExpr); } else { return(restOfExpr); } } else if (Peek().type == Token.TokenType.VarName) { Token varName = Consume(Token.TokenType.VarName); Variable var = this.currentLocals.Find(v => v.name == varName.content); var restOfExpr = RestOfExpr(var); if (restOfExpr is null) { return(var); } else { return(restOfExpr); } } else if (Peek().type == Token.TokenType.FuncName) { Token funcName = Consume(Token.TokenType.FuncName); Function func = program.functions.Find(f => f.name == funcName.content); List <Expression> ps = ParseFunctionArguments(); return(new FunctionCall() { function = func, arguments = ps }); } else { throw new UnexpectedTokenException(Consume()); } }