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);
        }
示例#3
0
        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);
            }
        }
示例#4
0
        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);
            }
        }