private Statement ParseStatement() { if (index == Tokens.Count) { throw new ParserException("Unexpected EOF - Expected Statement"); } Statement result; var currentToken = Tokens[index]; if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.print) { // print statement index++; var endIndex = index; while (Tokens[endIndex].Item1 != TokenType.Semicolon) { endIndex++; } var print = new Print { Expr = ParseExpression(endIndex) }; result = print; } else if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.var) { // variable declaration index++; var declareVar = new DeclareVariable(); if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Identifier) { declareVar.Ident = (string)Tokens[index].Item2.Lexeme; } else { throw new ParserException("Expected variable name after 'var' keyword"); } index++; if (index == Tokens.Count || Tokens[index].Item1 != TokenType.EqualOp) { throw new ParserException("Expected assigning in variable declaration"); } index++; var endIndex = index; while (Tokens[endIndex].Item1 != TokenType.Semicolon) { endIndex++; } declareVar.Expr = ParseExpression(endIndex); result = declareVar; } else if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.read_integer) { // read_integer statement index++; var readInt = new ReadInteger(); if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Identifier) { readInt.Ident = (string)Tokens[index++].Item2.Lexeme; result = readInt; } else { throw new ParserException("Expected variable name after 'read_integer' expression"); } } else if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.@for) { // for-loop statement index++; var forLoop = new ForLoop(); if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Identifier) { forLoop.Ident = (string)Tokens[index].Item2.Lexeme; } else { throw new ParserException("Expected loop counter-variable after 'for'"); } index++; if (index == Tokens.Count || Tokens[index].Item1 != TokenType.EqualOp) { throw new ParserException("Missing '=' in for loop"); } index++; forLoop.From = ParseExpression(); if (index == Tokens.Count || (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords) Tokens[index].Item2.Lexeme != Keywords.to))) { throw new ParserException("Expected 'to' keyword in for-loop statement"); } index++; forLoop.To = ParseExpression(); if (index == Tokens.Count || (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords) Tokens[index].Item2.Lexeme != Keywords.@do))) { throw new ParserException("Expected 'do' keyword in for-loop statement"); } index++; forLoop.Body = ParseStatement(); result = forLoop; if (index == Tokens.Count || (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords) Tokens[index].Item2.Lexeme != Keywords.end))) { throw new ParserException("Unterminated for-loop body"); } index++; } else if (Tokens[index].Item1 == TokenType.Identifier) { // variable assigning statement var assignStatement = new Assign { Ident = (string)Tokens[index++].Item2.Lexeme }; if (index == Tokens.Count || Tokens[index].Item1 != TokenType.EqualOp) { throw new ParserException("Expected '=' operator"); } index++; var endIndex = index; while (Tokens[endIndex].Item1 != TokenType.Semicolon) { endIndex++; } assignStatement.Expr = ParseExpression(endIndex); result = assignStatement; } else { // unknown statement throw new ParserException("Parse error at token " + index + ": " + Tokens[index]); } if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Semicolon) { index++; if (index < Tokens.Count) { if (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords) Tokens[index].Item2.Lexeme != Keywords.end)) { var sequenceStatement = new StatementList {First = result, Second = ParseStatement()}; result = sequenceStatement; } } } return result; }
private Statement ParseStatement() { if (index == Tokens.Count) { throw new ParserException("Unexpected EOF - Expected Statement"); } Statement result; var currentToken = Tokens[index]; if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.print) { // print statement index++; var endIndex = index; while (Tokens[endIndex].Item1 != TokenType.Semicolon) { endIndex++; } var print = new Print { Expr = ParseExpression(endIndex) }; result = print; } else if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.var) { // variable declaration index++; var declareVar = new DeclareVariable(); if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Identifier) { declareVar.Ident = (string)Tokens[index].Item2.Lexeme; } else { throw new ParserException("Expected variable name after 'var' keyword"); } index++; if (index == Tokens.Count || Tokens[index].Item1 != TokenType.EqualOp) { throw new ParserException("Expected assigning in variable declaration"); } index++; var endIndex = index; while (Tokens[endIndex].Item1 != TokenType.Semicolon) { endIndex++; } declareVar.Expr = ParseExpression(endIndex); result = declareVar; } else if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.read_integer) { // read_integer statement index++; var readInt = new ReadInteger(); if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Identifier) { readInt.Ident = (string)Tokens[index++].Item2.Lexeme; result = readInt; } else { throw new ParserException("Expected variable name after 'read_integer' expression"); } } else if (currentToken.Item1 == TokenType.Keyword && (Keywords)currentToken.Item2.Lexeme == Keywords.@for) { // for-loop statement index++; var forLoop = new ForLoop(); if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Identifier) { forLoop.Ident = (string)Tokens[index].Item2.Lexeme; } else { throw new ParserException("Expected loop counter-variable after 'for'"); } index++; if (index == Tokens.Count || Tokens[index].Item1 != TokenType.EqualOp) { throw new ParserException("Missing '=' in for loop"); } index++; forLoop.From = ParseExpression(); if (index == Tokens.Count || (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords)Tokens[index].Item2.Lexeme != Keywords.to))) { throw new ParserException("Expected 'to' keyword in for-loop statement"); } index++; forLoop.To = ParseExpression(); if (index == Tokens.Count || (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords)Tokens[index].Item2.Lexeme != Keywords.@do))) { throw new ParserException("Expected 'do' keyword in for-loop statement"); } index++; forLoop.Body = ParseStatement(); result = forLoop; if (index == Tokens.Count || (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords)Tokens[index].Item2.Lexeme != Keywords.end))) { throw new ParserException("Unterminated for-loop body"); } index++; } else if (Tokens[index].Item1 == TokenType.Identifier) { // variable assigning statement var assignStatement = new Assign { Ident = (string)Tokens[index++].Item2.Lexeme }; if (index == Tokens.Count || Tokens[index].Item1 != TokenType.EqualOp) { throw new ParserException("Expected '=' operator"); } index++; var endIndex = index; while (Tokens[endIndex].Item1 != TokenType.Semicolon) { endIndex++; } assignStatement.Expr = ParseExpression(endIndex); result = assignStatement; } else { // unknown statement throw new ParserException("Parse error at token " + index + ": " + Tokens[index]); } if (index < Tokens.Count && Tokens[index].Item1 == TokenType.Semicolon) { index++; if (index < Tokens.Count) { if (Tokens[index].Item1 != TokenType.Keyword || (Tokens[index].Item1 == TokenType.Keyword && (Keywords)Tokens[index].Item2.Lexeme != Keywords.end)) { var sequenceStatement = new StatementList { First = result, Second = ParseStatement() }; result = sequenceStatement; } } } return(result); }
private void GenerateStatements(Statement stmt) { if (stmt is StatementList) { var seq = (StatementList)stmt; GenerateStatements(seq.First); GenerateStatements(seq.Second); } else if (stmt is DeclareVariable) { var declare = (DeclareVariable)stmt; symbolsTable[declare.Ident] = ilgenerator.DeclareLocal(TypeOfExpr(declare.Expr)); var assign = new Assign { Ident = declare.Ident, Expr = declare.Expr }; GenerateStatements(assign); } else if (stmt is Assign) { var assign = (Assign)stmt; GenerateExpression(assign.Expr, TypeOfExpr(assign.Expr)); Store(assign.Ident, TypeOfExpr(assign.Expr)); } else if (stmt is Print) { GenerateExpression(((Print)stmt).Expr, typeof(string)); ilgenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); } else if (stmt is ReadInteger) { ilgenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine", BindingFlags.Public | BindingFlags.Static, null, new Type[] { }, null)); ilgenerator.Emit(OpCodes.Call, typeof(int).GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null)); Store(((ReadInteger)stmt).Ident, typeof(int)); } else if (stmt is ForLoop) { var forLoop = (ForLoop)stmt; var assign = new Assign { Ident = forLoop.Ident, Expr = forLoop.From }; GenerateStatements(assign); var test = ilgenerator.DefineLabel(); ilgenerator.Emit(OpCodes.Br, test); var body = ilgenerator.DefineLabel(); ilgenerator.MarkLabel(body); GenerateStatements(forLoop.Body); ilgenerator.Emit(OpCodes.Ldloc, symbolsTable[forLoop.Ident]); ilgenerator.Emit(OpCodes.Ldc_I4, 1); ilgenerator.Emit(OpCodes.Add); Store(forLoop.Ident, typeof(int)); ilgenerator.MarkLabel(test); ilgenerator.Emit(OpCodes.Ldloc, symbolsTable[forLoop.Ident]); GenerateExpression(forLoop.To, typeof(int)); ilgenerator.Emit(OpCodes.Blt, body); } else { throw new CodeGeneratorException("Cant generate a " + stmt.GetType().Name); } }