Example #1
0
    private Stmt ParseStmt()
    {
        Stmt result;

        if (this.index == this.tokens.Count)
        {
            throw new System.Exception("expected statement, got EOF");
        }

        // <stmt> := print <expr>

        // <expr> := <string>
        // | <int>
        // | <arith_expr>
        // | <ident>
        if (this.tokens[this.index].Equals("print"))
        {
            this.index++;
            Print print = new Print();

            //Если есть текстовое описание
            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is Text.StringBuilder)
            {
                print.Expression = this.ParseExpr();
            }

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                print.VarExpression = this.ParseExpr();
            }

            result = print;
        }
        else if (this.tokens[this.index].Equals("var"))
        {
            this.index++;
            DeclareVar declareVar = new DeclareVar();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                declareVar.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected variable name after 'var'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected = after 'var ident'");
            }

            this.index++;

            declareVar.Expression = this.ParseExpr();
            result = declareVar;
        }
        else if (this.tokens[this.index].Equals("input"))
        {
            this.index++;
            ReadValue readValue = new ReadValue();

            //Если есть текстовое описание
            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is Text.StringBuilder)
            {
                readValue.Exp = this.ParseExpr();
            }

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                readValue.Ident = (string)this.tokens[this.index++];
                result          = readValue;
            }
            else
            {
                throw new System.Exception("expected variable name after 'input'");
            }
        }

        /*else if (this.tokens[this.index].Equals("read_int"))
         *      {
         *              this.index++;
         *              ReadValue readValue = new ReadValue();
         *
         *              if (this.index < this.tokens.Count &&
         *                      this.tokens[this.index] is string)
         *              {
         *                      readValue.Ident = (string)this.tokens[this.index++];
         *                      result = readValue;
         *              }
         *              else
         *              {
         *                      throw new System.Exception("expected variable name after 'read_int'");
         *              }
         *      }*/
        else if (this.tokens[this.index].Equals("for"))
        {
            this.index++;
            ForNext forNext = new ForNext();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                forNext.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected identifier after 'for'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("for missing '='");
            }

            this.index++;

            forNext.From = this.ParseExpr();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("to"))
            {
                throw new System.Exception("expected 'to' after for");
            }

            this.index++;

            forNext.To = this.ParseExpr();

            /*if (this.index == this.tokens.Count ||
             *      !this.tokens[this.index].Equals("do"))
             * {
             *      throw new System.Exception("expected 'do' after from expression in for next");
             * }*/

            this.index++;

            forNext.Body = this.ParseStmt();
            result       = forNext;

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("next"))
            {
                throw new System.Exception("unterminated 'for' loop body");
            }

            this.index++;
        }
        else if (this.tokens[this.index].Equals("if"))
        {
            this.index++;
            IfElse ifthen = new IfElse();
            ifthen.Condition = new ConExpression();

            //Запишем первый операнд в условии
            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                ifthen.Condition.Left = this.ParseExpr();
            }
            else
            {
                throw new System.Exception("expected identifier after 'if'");
            }

            // Запишем условный оператор
            if (this.tokens[this.index] == Scanner.More) //Больше
            {
                ifthen.Condition.Operation = ConOperation.More;
            }
            else if (this.tokens[this.index] == Scanner.MoreEqual) //Больше-равно
            {
                ifthen.Condition.Operation = ConOperation.MoreEqual;
            }
            else if (this.tokens[this.index] == Scanner.Less) //Меньше
            {
                ifthen.Condition.Operation = ConOperation.Less;
            }
            else if (this.tokens[this.index] == Scanner.LessEqual) //Меньше-равно
            {
                ifthen.Condition.Operation = ConOperation.LessEqual;
            }
            else if (this.tokens[this.index] == Scanner.Equal) //Равенство
            {
                ifthen.Condition.Operation = ConOperation.Equal;
            }
            else
            {
                throw new System.Exception("missing condition operator");
            }

            //Запишем второй операнд в условии
            this.index++;
            ifthen.Condition.Right = this.ParseExpr();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("then"))
            {
                throw new System.Exception("expected 'then' after if");
            }

            this.index++;
            ifthen.BodyThen = this.ParseStmt();

            if (this.index < this.tokens.Count && this.tokens[this.index].Equals("else"))
            {
                this.index++;
                ifthen.BodyElse = this.ParseStmt();
            }

            result = ifthen;

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("endif"))
            {
                throw new System.Exception("unterminated 'if' body");
            }

            this.index++;
        }
        else if (this.tokens[this.index] is string)
        {
            //---------------------------------------------------------
            // assignment
            Assign assign = new Assign();
            assign.Ident = (string)this.tokens[this.index++];

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected '='");
            }

            this.index++;

            assign.Expression = this.ParseExpr();

            //Проверим наличие операции

            if (this.tokens[this.index] != Scanner.Semi)
            {
                assign.Expression = this.ParseBinExpr(assign.Expression);
            }

            result = assign;
        }
        else
        {
            throw new System.Exception("parse error at token " + this.index + ": " + this.tokens[this.index]);
        }


        if (this.index < this.tokens.Count && this.tokens[this.index] == Scanner.Semi)
        {
            this.index++;

            if (this.index < this.tokens.Count &&
                !this.tokens[this.index].Equals("next") && !this.tokens[this.index].Equals("endif") && !this.tokens[this.index].Equals("else"))
            {
                Sequence sequence = new Sequence();
                sequence.First  = result;
                sequence.Second = this.ParseStmt();
                result          = sequence;
            }
        }

        return(result);
    }
Example #2
0
    private void GenStmt(Stmt stmt)
    {
        if (stmt is Sequence)
        {
            Sequence seq = (Sequence)stmt;
            this.GenStmt(seq.First);
            this.GenStmt(seq.Second);
        }

        else if (stmt is DeclareVar)
        {
            // declare a local
            DeclareVar declare = (DeclareVar)stmt;
            this.symbolTable[declare.Ident] = this.il.DeclareLocal(this.TypeOfExpr(declare.Expr));

            // set the initial value
            Assign assign = new Assign();
            assign.Ident = declare.Ident;
            assign.Expr  = declare.Expr;
            this.GenStmt(assign);
        }

        else if (stmt is Assign)
        {
            Assign assign = (Assign)stmt;
            this.GenExpr(assign.Expr, this.TypeOfExpr(assign.Expr));
            this.Store(assign.Ident, this.TypeOfExpr(assign.Expr));
        }
        else if (stmt is Print)
        {
            // the "print" statement is an alias for System.Console.WriteLine.
            // it uses the string case
            this.GenExpr(((Print)stmt).Expr, typeof(string));
            this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) }));
        }

        else if (stmt is ReadInt)
        {
            this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("ReadLine", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { }, null));
            this.il.Emit(Emit.OpCodes.Call, typeof(int).GetMethod("Parse", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { typeof(string) }, null));
            this.Store(((ReadInt)stmt).Ident, typeof(int));
        }
        //*******************
        else if (stmt is mcIf)
        {
            mcIf mcif = (mcIf)stmt;
            //this.GenExpr(mcif.compExpr, typeof(int));
            Emit.Label Else   = this.il.DefineLabel();
            Emit.Label Then   = this.il.DefineLabel();
            Emit.Label Salida = this.il.DefineLabel();
            if (mcif.compExpr is CompExpr)
            {
                CompExpr compExpr = (CompExpr)mcif.compExpr;
                this.GenExpr(compExpr.Left, typeof(int));
                this.GenExpr(compExpr.Rigth, typeof(int));
                genCodComp(compExpr.Op, Then);
            }
            else
            {
                GenExpr(mcif.compExpr, typeof(string));
                this.il.Emit(Emit.OpCodes.Ldc_I4, 0);
                this.il.Emit(Emit.OpCodes.Bne_Un, Then);
            }
            if (mcif.Else != null)
            {
                this.il.Emit(Emit.OpCodes.Br, Else);
            }
            else
            {
                this.il.Emit(Emit.OpCodes.Br, Salida);
            }
            this.il.MarkLabel(Then);
            GenStmt(mcif.Then);
            this.il.Emit(Emit.OpCodes.Br, Salida);
            this.il.MarkLabel(Else);
            if (mcif.Else != null)
            {
                GenStmt(mcif.Else);
            }
            this.il.MarkLabel(Salida);
        }
        else if (stmt is WhileLoop)
        {
            WhileLoop  whileLoop = (WhileLoop)stmt;
            Emit.Label Body      = this.il.DefineLabel();
            Emit.Label Salida    = this.il.DefineLabel();
            Emit.Label Cond      = this.il.DefineLabel();
            this.il.MarkLabel(Cond);
            if (whileLoop.Cond is CompExpr)
            {
                CompExpr compExpr = (CompExpr)whileLoop.Cond;
                this.GenExpr(compExpr.Left, typeof(int));
                this.GenExpr(compExpr.Rigth, typeof(int));
                genCodComp(compExpr.Op, Body);
            }
            else
            {
                GenExpr(whileLoop.Cond, typeof(string));
                this.il.Emit(Emit.OpCodes.Ldc_I4, 0);
                this.il.Emit(Emit.OpCodes.Bne_Un, Body);
            }
            this.il.Emit(Emit.OpCodes.Br, Salida);
            this.il.MarkLabel(Body);
            GenStmt(whileLoop.Body);
            this.il.Emit(Emit.OpCodes.Br, Cond);
            this.il.MarkLabel(Salida);
        }
        //*******************
        else if (stmt is ForLoop)
        {
            // example:
            // for x = 0 to 100 do
            //   print "hello";
            // end;

            // x = 0
            ForLoop forLoop = (ForLoop)stmt;
            Assign  assign  = new Assign();
            assign.Ident = forLoop.Ident;
            assign.Expr  = forLoop.From;
            this.GenStmt(assign);
            // jump to the test
            Emit.Label test = this.il.DefineLabel();
            this.il.Emit(Emit.OpCodes.Br, test);

            // statements in the body of the for loop
            Emit.Label body = this.il.DefineLabel();
            this.il.MarkLabel(body);
            this.GenStmt(forLoop.Body);

            // to (increment the value of x)
            this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]);
            this.il.Emit(Emit.OpCodes.Ldc_I4, 1);
            this.il.Emit(Emit.OpCodes.Add);
            this.Store(forLoop.Ident, typeof(int));

            // **test** does x equal 100? (do the test)
            this.il.MarkLabel(test);
            this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]);
            this.GenExpr(forLoop.To, typeof(int));
            this.il.Emit(Emit.OpCodes.Blt, body);
        }
        else
        {
            throw new System.Exception("imposible generar: " + stmt.GetType().Name);
        }
    }
Example #3
0
    private void GenStmt(Stmt stmt)
    {
        if (stmt is Sequence)
        {
            Sequence seq = (Sequence)stmt;
            this.GenStmt(seq.First);
            this.GenStmt(seq.Second);
        }

        else if (stmt is DeclareVar)
        {
            // declare a local
            DeclareVar declare = (DeclareVar)stmt;
            this.symbolTable[declare.Ident] = this.il.DeclareLocal(this.TypeOfExpr(declare.Expr));

            // set the initial value
            Assign assign = new Assign();
            assign.Ident = declare.Ident;
            assign.Expr  = declare.Expr;
            this.GenStmt(assign);
        }

        else if (stmt is Assign)
        {
            Assign assign = (Assign)stmt;
            this.GenExpr(assign.Expr, this.TypeOfExpr(assign.Expr));
            this.Store(assign.Ident, this.TypeOfExpr(assign.Expr));
        }
        else if (stmt is Print)
        {
            // the "print" statement is an alias for System.Console.WriteLine.
            // it uses the string case
            this.GenExpr(((Print)stmt).Expr, typeof(string));
            this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) }));
        }

        else if (stmt is ReadInt)
        {
            this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("ReadLine", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { }, null));
            this.il.Emit(Emit.OpCodes.Call, typeof(int).GetMethod("Parse", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { typeof(string) }, null));
            this.Store(((ReadInt)stmt).Ident, typeof(int));
        }
        else if (stmt is ForLoop)
        {
            // example:
            // for x = 0 to 100 do
            //   print "hello";
            // end;

            // x = 0
            ForLoop forLoop = (ForLoop)stmt;
            Assign  assign  = new Assign();
            assign.Ident = forLoop.Ident;
            assign.Expr  = forLoop.From;
            this.GenStmt(assign);
            // jump to the test
            Emit.Label test = this.il.DefineLabel();
            this.il.Emit(Emit.OpCodes.Br, test);

            // statements in the body of the for loop
            Emit.Label body = this.il.DefineLabel();
            this.il.MarkLabel(body);
            this.GenStmt(forLoop.Body);

            // to (increment the value of x)
            this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]);
            this.il.Emit(Emit.OpCodes.Ldc_I4, 1);
            this.il.Emit(Emit.OpCodes.Add);
            this.Store(forLoop.Ident, typeof(int));

            // **test** does x equal 100? (do the test)
            this.il.MarkLabel(test);
            this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]);
            this.GenExpr(forLoop.To, typeof(int));
            this.il.Emit(Emit.OpCodes.Blt, body);
        }
        else
        {
            throw new System.Exception("don't know how to gen a " + stmt.GetType().Name);
        }
    }
Example #4
0
    private void GenStmt(Stmt stmt)
    {
        //Обработка элемента последовательности дерева
        if (stmt is Sequence)
        {
            Sequence seq = (Sequence)stmt;
            //Выполним обработку левой части дерева
            this.GenStmt(seq.First);
            //Выполним обработку правой части дерева
            this.GenStmt(seq.Second);
        }

        //Обработка элемента дерева - "Объявление"
        else if (stmt is DeclareVar)
        {
            // Добавим переменную в список переменных
            DeclareVar declare = (DeclareVar)stmt;
            this.varTable[declare.Ident] = this.TypeOfExpr(declare.Expression);

            //Приведем элемент типа "Объевление" к типу "Присвоение"
            Assign assign = new Assign();
            assign.Ident      = declare.Ident;
            assign.Expression = declare.Expression;

            //Запишем тип переменной
            accum.Append(string.Format("\n{0} ", this.TypeOfExpr(declare.Expression).Name));
            //Запустим на обработку
            this.GenStmt(assign);
        }

        //Обработка элемента дерева - "Присвоение"
        else if (stmt is Assign)
        {
            Assign assign = (Assign)stmt;
            accum.Append(string.Format("{0}=", assign.Ident));

            //Обработка правой части элемента
            this.GenAssign(assign.Expression);
            accum.Append(";");
        }

        //Обработка элемента дерева - "Вывод данных"
        else if (stmt is Print)
        {
            Print print = (Print)stmt;
            accum.Append(print.VarExpression != null
                             ? string.Format("\nConsole.WriteLine(\"{0}\", {1});", this.GetExprValue(print.Expression),
                                             this.GetExprValue(print.VarExpression))
                             : string.Format("\nConsole.WriteLine(\"{0}\");", this.GetExprValue(print.Expression)));
        }

        //Обработка элемента дерева - "Ввод данных"
        else if (stmt is ReadValue)
        {
            ReadValue readValue = (ReadValue)stmt;
            accum.Append(readValue.Exp != null
                             ? string.Format("\n{0} = Console.ReadLine(\"{1}\");", readValue.Ident, this.GetExprValue(readValue.Exp))
                             : string.Format("\n{0} = Console.ReadLine();", readValue.Ident));

            //Проверка, что переменная объявлена ранее
            //CheckVariable
        }
        else if (stmt is IfElse)
        {
            IfElse ifElse    = (IfElse)stmt;
            string operation = string.Empty;

            switch (ifElse.Condition.Operation)
            {
            case ConOperation.Equal: operation = "="; break;

            case ConOperation.Less: operation = "<"; break;

            case ConOperation.LessEqual: operation = "<="; break;

            case ConOperation.More: operation = ">"; break;

            case ConOperation.MoreEqual: operation = ">="; break;
            }
            accum.Append(string.Format("\nif ({0}{1}{2})", this.GetExprValue(ifElse.Condition.Left), operation, this.GetExprValue(ifElse.Condition.Right)));


            if (ifElse.BodyThen != null)
            {
                accum.Append("\n{\n");
                this.GenStmt(ifElse.BodyThen);
                accum.Append("\n}");
            }

            if (ifElse.BodyElse != null)
            {
                if (ifElse.BodyThen == null)
                {
                    throw new System.Exception("error if - else");
                }
                accum.Append("\nelse\n{\n");
                this.GenStmt(ifElse.BodyElse);
                accum.Append("\n}");
            }
        }
        else if (stmt is ForNext)
        {
            ForNext forNext = (ForNext)stmt;

            accum.Append(string.Format("\nfor("));
            Assign assign = new Assign();
            assign.Ident      = forNext.Ident;
            assign.Expression = forNext.From;
            this.GenStmt(assign);
            accum.Append(string.Format("{0}<{1};{2}++)", forNext.Ident, this.GetExprValue(forNext.To), forNext.Ident));

            this.varTable[forNext.Ident] = typeof(int);

            if (forNext.Body != null)
            {
                accum.Append("\n{");
                this.GenStmt(forNext.Body);
                accum.Append("\n}");
            }
        }
        else
        {
            throw new System.Exception("Отсутствует инструкция для генерирования операции: " + stmt.GetType().Name);
        }
    }
Example #5
0
    private Stmt ParseStmt()
    {
        Stmt result = null;

        if (this.index == this.tokens.Count)
        {
            throw new System.Exception("expected statement, got EOF");
        }

        // <stmt> := print <expr>

        // <expr> := <string>
        // | <int>
        // | <arith_expr>
        // | <ident>
        if (this.tokens[this.index].Equals(languageSetting["End"]))
        {
            this.index++;
        }
        else if (this.tokens[this.index].Equals(languageSetting["Start"]))
        {
            this.index++;
            return(ParseStmt());
        }

        else if (this.tokens[this.index].Equals(languageSetting["Print"]))
        {
            this.index++;
            Print print = new Print();
            print.Expr = this.ParseExpr();
            result     = print;
        }

        else if (this.tokens[this.index] == Scanner.Call)
        {
            VoidMethodCall vmc = new VoidMethodCall();
            vmc.Expr = this.ParseExpr();
            result   = vmc;
        }
        else if (this.tokens[this.index].Equals(languageSetting["VariableDeclaration"]))
        {
            this.index++;
            DeclareVar declareVar = new DeclareVar();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                declareVar.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected variable name after 'var'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected = after 'var ident'");
            }

            this.index++;

            declareVar.Expr = this.ParseExpr();
            result          = declareVar;
        }
        else if (this.tokens[this.index].Equals(languageSetting["if"]))
        {
            this.index++;
            IfCondition ifCon = new IfCondition();
            ifCon.BooleanExp = this.ParseExpr();

            if (!this.tokens[++this.index].Equals(languageSetting["Start"]))
            {
                throw new System.Exception("Start Expected");
            }

            ifCon.Body = this.ParseStmt();

            if (!this.tokens[this.index++].Equals(languageSetting["End"]))
            {
                throw new System.Exception("End Expected");
            }

            result = ifCon;
        }


        else if (this.tokens[this.index].Equals(languageSetting["while"]))
        {
            this.index++;
            WhileLoop whileLoop = new WhileLoop();
            whileLoop.BooleanExp = this.ParseExpr();

            if (!this.tokens[++this.index].Equals(languageSetting["Start"]))
            {
                throw new System.Exception("Start Expected");
            }

            whileLoop.Body = this.ParseStmt();

            if (!this.tokens[this.index++].Equals(languageSetting["End"]))
            {
                throw new System.Exception("End Expected");
            }

            result = whileLoop;
        }


        else if (this.tokens[this.index].Equals("read_int"))
        {
            this.index++;
            ReadInt readInt = new ReadInt();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                readInt.Ident = (string)this.tokens[this.index++];
                result        = readInt;
            }
            else
            {
                throw new System.Exception("expected variable name after 'read_int'");
            }
        }
        else if (this.tokens[this.index].Equals("for"))
        {
            this.index++;
            ForLoop forLoop = new ForLoop();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                forLoop.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected identifier after 'for'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("for missing '='");
            }

            this.index++;

            forLoop.From = this.ParseSingleExpression();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("to"))
            {
                throw new System.Exception("expected 'to' after for");
            }

            this.index++;

            forLoop.To = this.ParseSingleExpression();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("do"))
            {
                throw new System.Exception("expected 'do' after from expression in for loop");
            }

            this.index++;

            forLoop.Body = this.ParseStmt();
            result       = forLoop;

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("end"))
            {
                throw new System.Exception("unterminated 'for' loop body");
            }

            this.index++;
        }
        else if (this.tokens[this.index] is string)
        {
            // assignment

            Assign assign = new Assign();
            assign.Ident = (string)this.tokens[this.index++];

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected '='");
            }

            this.index++;

            assign.Expr = this.ParseExpr();
            result      = assign;
        }
        else
        {
            throw new System.Exception("parse error at token " + this.index + ": " + this.tokens[this.index]);
        }

        if (this.index < this.tokens.Count && this.tokens[this.index] == Scanner.Semi)
        {
            this.index++;

            if (this.index < this.tokens.Count &&
                !this.tokens[this.index].Equals(languageSetting["End"]))
            {
                Sequence sequence = new Sequence();
                sequence.First  = result;
                sequence.Second = this.ParseStmt();
                result          = sequence;
            }
        }

        return(result);
    }
Example #6
0
    private Stmt ParseStmt()
    {
        Stmt resultado;

        if (this.indice == this.tokens.Count)
        {
            throw new System.Exception("se esperaban sentencias, se llego al final del archivo");
        }

        // <stmt> := print <expr>

        // <expr> := <string>
        // | <int>
        // | <arith_expr>
        // | <ident>
        if (this.tokens[this.indice].Equals("print"))
        {
            this.indice++;
            Print print = new Print();
            print.Expr = this.ParseExpr();
            resultado = print;
        }
        else if (this.tokens[this.indice].Equals("var"))
        {
            this.indice++;
            DeclareVar declareVar = new DeclareVar();

            if (this.indice < this.tokens.Count &&
                this.tokens[this.indice] is string)
            {
                declareVar.Ident = (string)this.tokens[this.indice];
            }
            else
            {
                throw new System.Exception("Se esperaba nombre de variable despues de 'var'");
            }

            this.indice++;

            if (this.indice == this.tokens.Count ||
                this.tokens[this.indice] != Scanner.Igual)
            {
                throw new System.Exception("se esperaba = despues de 'var ident'");
            }

            this.indice++;

            declareVar.Expr = this.ParseExpr();
            resultado = declareVar;
        }
        else if (this.tokens[this.indice].Equals("read_int"))
        {
            this.indice++;
            ReadInt readInt = new ReadInt();

            if (this.indice < this.tokens.Count &&
                this.tokens[this.indice] is string)
            {
                readInt.Ident = (string)this.tokens[this.indice++];
                resultado = readInt;
            }
            else
            {
                throw new System.Exception("Se esperaba el nombre de la variable 'read_int'");
            }
        }
        //*******************
        else if (this.tokens[this.indice].Equals("if"))
        {
            this.indice++;
            mcIf mcif = new mcIf();
            Expr temp = ParseExpr();
            if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq ||
                this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte ||
                this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte)
            {
                CompExpr compExpr = new CompExpr();
                compExpr.Left = temp;
                object op = this.tokens[this.indice++];
                if (op == Scanner.Eq)
                    compExpr.Op = CompOp.Eq;
                else if (op == Scanner.Neq)
                    compExpr.Op = CompOp.Neq;
                else if (op == Scanner.Gt)
                    compExpr.Op = CompOp.Gt;
                else if (op == Scanner.Gte)
                    compExpr.Op = CompOp.Gte;
                else if (op == Scanner.Lt)
                    compExpr.Op = CompOp.Lt;
                else if (op == Scanner.Lte)
                    compExpr.Op = CompOp.Lte;
                compExpr.Rigth = ParseExpr();
                temp = compExpr;
            }
            mcif.compExpr = temp;
            if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("then"))
            {
                throw new System.Exception("Se esperaba el identificador 'then' despues de 'if'");
            }
            this.indice++;
            mcif.Then = ParseStmt();
            if (this.tokens[this.indice].Equals("else"))
            {
                this.indice++;
                mcif.Else = ParseStmt();
            }

            resultado = mcif;
            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("end"))
            {
                throw new System.Exception("Sentencia if inconclusa");
            }

            this.indice++;

        }
        else if (this.tokens[this.indice].Equals("while"))
        {
            this.indice++;
            WhileLoop whileLoop = new WhileLoop();
            Expr temp = ParseExpr();
            if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq ||
                this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte ||
                this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte)
            {
                CompExpr compExpr = new CompExpr();
                compExpr.Left = temp;
                object op = this.tokens[this.indice++];
                if (op == Scanner.Eq)
                    compExpr.Op = CompOp.Eq;
                else if (op == Scanner.Neq)
                    compExpr.Op = CompOp.Neq;
                else if (op == Scanner.Gt)
                    compExpr.Op = CompOp.Gt;
                else if (op == Scanner.Gte)
                    compExpr.Op = CompOp.Gte;
                else if (op == Scanner.Lt)
                    compExpr.Op = CompOp.Lt;
                else if (op == Scanner.Lte)
                    compExpr.Op = CompOp.Lte;
                compExpr.Rigth = ParseExpr();
                temp = compExpr;
            }
            whileLoop.Cond = temp;
            if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("do"))
            {
                throw new System.Exception("Se esperaba el identificador 'do' despues de 'while'");
            }
            this.indice++;
            whileLoop.Body = ParseStmt();
            resultado = whileLoop;
            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("end"))
            {
                throw new System.Exception("sentencia while inconclusa");
            }
            this.indice++;
        }
        //*******************
        else if (this.tokens[this.indice].Equals("for"))
        {
            this.indice++;
            ForLoop forLoop = new ForLoop();

            if (this.indice < this.tokens.Count &&
                this.tokens[this.indice] is string)
            {
                forLoop.Ident = (string)this.tokens[this.indice];
            }
            else
            {
                throw new System.Exception("se esperaba un indentificador despues de 'for'");
            }

            this.indice++;

            if (this.indice == this.tokens.Count ||
                this.tokens[this.indice] != Scanner.Igual)
            {
                throw new System.Exception("no se encontro en la sentencia for '='");
            }

            this.indice++;

            forLoop.From = this.ParseExpr();

            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("to"))
            {
                throw new System.Exception("se epsaraba 'to' despues de for");
            }

            this.indice++;

            forLoop.To = this.ParseExpr();

            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("do"))
            {
                throw new System.Exception("se esperaba 'do' despues de la expresion en el ciclo for");
            }

            this.indice++;

            forLoop.Body = this.ParseStmt();
            resultado = forLoop;

            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("end"))
            {
                throw new System.Exception("setencia for inconclusa");
            }

            this.indice++;
        }
        else if (this.tokens[this.indice] is string)
        {
            // assignment

            Assign assign = new Assign();
            assign.Ident = (string)this.tokens[this.indice++];

            if (this.indice == this.tokens.Count ||
                this.tokens[this.indice] != Scanner.Igual)
            {
                throw new System.Exception("se esperaba '='");
            }

            this.indice++;

            assign.Expr = this.ParseExpr();
            resultado = assign;
        }
        else
        {
            throw new System.Exception("Error en el token " + this.indice + ": " + this.tokens[this.indice]);
        }

        if (this.indice < this.tokens.Count && this.tokens[this.indice] == Scanner.PyC)
        {
            this.indice++;

            if (this.indice < this.tokens.Count &&
                !this.tokens[this.indice].Equals("end") && !this.tokens[this.indice].Equals("else"))
            {
                Sequence sequence = new Sequence();
                sequence.First = resultado;
                sequence.Second = this.ParseStmt();
                resultado = sequence;
            }
        }

        return resultado;
    }
Example #7
0
    private Stmt ParseStmt()
    {
        Stmt result;

        if (this.index == this.tokens.Count)
        {
            throw new System.Exception("expected statement, got EOF");
        }

        // <stmt> := print <expr>

        // <expr> := <string>
        // | <int>
        // | <arith_expr>
        // | <ident>
        if (this.tokens[this.index].Equals("print"))
        {
            this.index++;
            Print print = new Print();
            print.Expr = this.ParseExpr();
            result     = print;
        }
        else if (this.tokens[this.index].Equals("var"))
        {
            this.index++;
            DeclareVar declareVar = new DeclareVar();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                declareVar.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected variable name after 'var'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected = after 'var ident'");
            }

            this.index++;

            declareVar.Expr = this.ParseExpr();
            result          = declareVar;
        }
        else if (this.tokens[this.index].Equals("read_int"))
        {
            this.index++;
            ReadInt readInt = new ReadInt();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                readInt.Ident = (string)this.tokens[this.index++];
                result        = readInt;
            }
            else
            {
                throw new System.Exception("expected variable name after 'read_int'");
            }
        }
        else if (this.tokens[this.index].Equals("for"))
        {
            this.index++;
            ForLoop forLoop = new ForLoop();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                forLoop.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected identifier after 'for'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("for missing '='");
            }

            this.index++;

            forLoop.From = this.ParseExpr();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("to"))
            {
                throw new System.Exception("expected 'to' after for");
            }

            this.index++;

            forLoop.To = this.ParseExpr();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("do"))
            {
                throw new System.Exception("expected 'do' after from expression in for loop");
            }

            this.index++;

            forLoop.Body = this.ParseStmt();
            result       = forLoop;

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("end"))
            {
                throw new System.Exception("unterminated 'for' loop body");
            }

            this.index++;
        }
        else if (this.tokens[this.index] is string)
        {
            // assignment

            Assign assign = new Assign();
            assign.Ident = (string)this.tokens[this.index++];

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected '='");
            }

            this.index++;

            assign.Expr = this.ParseExpr();
            result      = assign;
        }
        else
        {
            throw new System.Exception("parse error at token " + this.index + ": " + this.tokens[this.index]);
        }

        if (this.index < this.tokens.Count && this.tokens[this.index] == Scanner.Semi)
        {
            this.index++;

            if (this.index < this.tokens.Count &&
                !this.tokens[this.index].Equals("end"))
            {
                Sequence sequence = new Sequence();
                sequence.First  = result;
                sequence.Second = this.ParseStmt();
                result          = sequence;
            }
        }

        return(result);
    }
Example #8
0
    private Stmt ParseStmt()
    {
        Stmt resultado;

        if (this.indice == this.tokens.Count)
        {
            throw new System.Exception("se esperaban sentencias, se llego al final del archivo");
        }

        // <stmt> := print <expr>

        // <expr> := <string>
        // | <int>
        // | <arith_expr>
        // | <ident>
        if (this.tokens[this.indice].Equals("print"))
        {
            this.indice++;
            Print print = new Print();
            print.Expr = this.ParseExpr();
            resultado  = print;
        }
        else if (this.tokens[this.indice].Equals("var"))
        {
            this.indice++;
            DeclareVar declareVar = new DeclareVar();

            if (this.indice < this.tokens.Count &&
                this.tokens[this.indice] is string)
            {
                declareVar.Ident = (string)this.tokens[this.indice];
            }
            else
            {
                throw new System.Exception("Se esperaba nombre de variable despues de 'var'");
            }

            this.indice++;

            if (this.indice == this.tokens.Count ||
                this.tokens[this.indice] != Scanner.Igual)
            {
                throw new System.Exception("se esperaba = despues de 'var ident'");
            }

            this.indice++;

            declareVar.Expr = this.ParseExpr();
            resultado       = declareVar;
        }
        else if (this.tokens[this.indice].Equals("read_int"))
        {
            this.indice++;
            ReadInt readInt = new ReadInt();

            if (this.indice < this.tokens.Count &&
                this.tokens[this.indice] is string)
            {
                readInt.Ident = (string)this.tokens[this.indice++];
                resultado     = readInt;
            }
            else
            {
                throw new System.Exception("Se esperaba el nombre de la variable 'read_int'");
            }
        }
        //*******************
        else if (this.tokens[this.indice].Equals("if"))
        {
            this.indice++;
            mcIf mcif = new mcIf();
            Expr temp = ParseExpr();
            if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq ||
                this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte ||
                this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte)
            {
                CompExpr compExpr = new CompExpr();
                compExpr.Left = temp;
                object op = this.tokens[this.indice++];
                if (op == Scanner.Eq)
                {
                    compExpr.Op = CompOp.Eq;
                }
                else if (op == Scanner.Neq)
                {
                    compExpr.Op = CompOp.Neq;
                }
                else if (op == Scanner.Gt)
                {
                    compExpr.Op = CompOp.Gt;
                }
                else if (op == Scanner.Gte)
                {
                    compExpr.Op = CompOp.Gte;
                }
                else if (op == Scanner.Lt)
                {
                    compExpr.Op = CompOp.Lt;
                }
                else if (op == Scanner.Lte)
                {
                    compExpr.Op = CompOp.Lte;
                }
                compExpr.Rigth = ParseExpr();
                temp           = compExpr;
            }
            mcif.compExpr = temp;
            if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("then"))
            {
                throw new System.Exception("Se esperaba el identificador 'then' despues de 'if'");
            }
            this.indice++;
            mcif.Then = ParseStmt();
            if (this.tokens[this.indice].Equals("else"))
            {
                this.indice++;
                mcif.Else = ParseStmt();
            }

            resultado = mcif;
            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("end"))
            {
                throw new System.Exception("Sentencia if inconclusa");
            }

            this.indice++;
        }
        else if (this.tokens[this.indice].Equals("while"))
        {
            this.indice++;
            WhileLoop whileLoop = new WhileLoop();
            Expr      temp      = ParseExpr();
            if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq ||
                this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte ||
                this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte)
            {
                CompExpr compExpr = new CompExpr();
                compExpr.Left = temp;
                object op = this.tokens[this.indice++];
                if (op == Scanner.Eq)
                {
                    compExpr.Op = CompOp.Eq;
                }
                else if (op == Scanner.Neq)
                {
                    compExpr.Op = CompOp.Neq;
                }
                else if (op == Scanner.Gt)
                {
                    compExpr.Op = CompOp.Gt;
                }
                else if (op == Scanner.Gte)
                {
                    compExpr.Op = CompOp.Gte;
                }
                else if (op == Scanner.Lt)
                {
                    compExpr.Op = CompOp.Lt;
                }
                else if (op == Scanner.Lte)
                {
                    compExpr.Op = CompOp.Lte;
                }
                compExpr.Rigth = ParseExpr();
                temp           = compExpr;
            }
            whileLoop.Cond = temp;
            if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("do"))
            {
                throw new System.Exception("Se esperaba el identificador 'do' despues de 'while'");
            }
            this.indice++;
            whileLoop.Body = ParseStmt();
            resultado      = whileLoop;
            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("end"))
            {
                throw new System.Exception("sentencia while inconclusa");
            }
            this.indice++;
        }
        //*******************
        else if (this.tokens[this.indice].Equals("for"))
        {
            this.indice++;
            ForLoop forLoop = new ForLoop();

            if (this.indice < this.tokens.Count &&
                this.tokens[this.indice] is string)
            {
                forLoop.Ident = (string)this.tokens[this.indice];
            }
            else
            {
                throw new System.Exception("se esperaba un indentificador despues de 'for'");
            }

            this.indice++;

            if (this.indice == this.tokens.Count ||
                this.tokens[this.indice] != Scanner.Igual)
            {
                throw new System.Exception("no se encontro en la sentencia for '='");
            }

            this.indice++;

            forLoop.From = this.ParseExpr();

            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("to"))
            {
                throw new System.Exception("se epsaraba 'to' despues de for");
            }

            this.indice++;

            forLoop.To = this.ParseExpr();

            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("do"))
            {
                throw new System.Exception("se esperaba 'do' despues de la expresion en el ciclo for");
            }

            this.indice++;

            forLoop.Body = this.ParseStmt();
            resultado    = forLoop;

            if (this.indice == this.tokens.Count ||
                !this.tokens[this.indice].Equals("end"))
            {
                throw new System.Exception("setencia for inconclusa");
            }

            this.indice++;
        }
        else if (this.tokens[this.indice] is string)
        {
            // assignment

            Assign assign = new Assign();
            assign.Ident = (string)this.tokens[this.indice++];

            if (this.indice == this.tokens.Count ||
                this.tokens[this.indice] != Scanner.Igual)
            {
                throw new System.Exception("se esperaba '='");
            }

            this.indice++;

            assign.Expr = this.ParseExpr();
            resultado   = assign;
        }
        else
        {
            throw new System.Exception("Error en el token " + this.indice + ": " + this.tokens[this.indice]);
        }

        if (this.indice < this.tokens.Count && this.tokens[this.indice] == Scanner.PyC)
        {
            this.indice++;

            if (this.indice < this.tokens.Count &&
                !this.tokens[this.indice].Equals("end") && !this.tokens[this.indice].Equals("else"))
            {
                Sequence sequence = new Sequence();
                sequence.First  = resultado;
                sequence.Second = this.ParseStmt();
                resultado       = sequence;
            }
        }

        return(resultado);
    }
Example #9
0
        private void GenStmt(Stmt stmt)
        {
            if (stmt is Sequence)
            {
                Sequence seq = (Sequence)stmt;
                this.GenStmt(seq.First);
                this.GenStmt(seq.Second);
            }

            else if (stmt is DeclareVar)
            {
                // declare a local
                DeclareVar declare = (DeclareVar)stmt;
                this.symbolTable[declare.Ident] = this.il.DeclareLocal(this.TypeOfExpr(declare.Expr));

                // set the initial value
                Assign assign = new Assign();
                assign.Ident = declare.Ident;
                assign.Expr  = declare.Expr;
                this.GenStmt(assign);
            }

            else if (stmt is Assign)
            {
                Assign assign = (Assign)stmt;

                if (this.typefieldList.ContainsKey(assign.Ident))
                {
                    if (!this.typefieldList[assign.Ident].IsStatic)
                    {
                        this.il.Emit(Emit.OpCodes.Ldarg_0);
                    }
                }


                // if(assign.Ident
                this.GenExpr(assign.Expr, this.TypeOfExpr(assign.Expr));
                this.Store(assign.Ident, this.TypeOfExpr(assign.Expr));
            }
            else if (stmt is Print)
            {
                // the "print" statement is an alias for System.Console.WriteLine.
                // it uses the string case
                this.GenExpr(((Print)stmt).Expr, typeof(string));
                this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) }));
                // this.il.Emit(
            }
            else if (stmt is VoidMethodCall)
            {
                this.GenerteMethodCallCode((MethodCall)((VoidMethodCall)stmt).Expr);
            }

            else if (stmt is IfCondition)
            {
                IfCondition ifCon = (IfCondition)stmt;
                this.GenExpr(ifCon.BooleanExp, /*harcoded for string */ typeof(string));

                Emit.Label endOfIfBlock = this.il.DefineLabel();


                if (((BinExpr)ifCon.BooleanExp).Op == BinOp.EqualTo)
                {
                    this.il.Emit(Emit.OpCodes.Brfalse_S, endOfIfBlock);
                }
                else
                {
                    this.il.Emit(Emit.OpCodes.Brtrue_S, endOfIfBlock);
                }

                this.GenStmt(ifCon.Body);

                this.il.MarkLabel(endOfIfBlock);
                // this.GenerteMethodCallCode((MethodCall)((VoidMethodCall)stmt).Expr);
            }

            else if (stmt is WhileLoop)
            {
                WhileLoop whileLoop = (WhileLoop)stmt;

                Emit.Label whileBodyStart = this.il.DefineLabel();
                Emit.Label whileBodyEnd   = this.il.DefineLabel();
                Emit.Label whileCondition = this.il.DefineLabel();

                this.il.Emit(Emit.OpCodes.Br_S, whileBodyEnd);

                this.il.MarkLabel(whileBodyStart);
                this.GenStmt(whileLoop.Body);
                this.il.MarkLabel(whileBodyEnd);

                this.GenExpr(whileLoop.BooleanExp, /*harcoded for int */ typeof(int));

                if (((BinExpr)whileLoop.BooleanExp).Op == BinOp.EqualTo)
                {
                    this.il.Emit(Emit.OpCodes.Brtrue_S, whileBodyStart);
                }
                else
                {
                    this.il.Emit(Emit.OpCodes.Brfalse_S, whileBodyStart);
                }
            }


            // System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();

            else if (stmt is ReadInt)
            {
                this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("ReadLine", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { }, null));
                this.il.Emit(Emit.OpCodes.Call, typeof(int).GetMethod("Parse", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { typeof(string) }, null));
                this.Store(((ReadInt)stmt).Ident, typeof(int));
            }
            else if (stmt is ForLoop)
            {
                // example:
                // for x = 0 to 100 do
                //   print "hello";
                // end;

                // x = 0
                ForLoop forLoop = (ForLoop)stmt;
                Assign  assign  = new Assign();
                assign.Ident = forLoop.Ident;
                assign.Expr  = forLoop.From;
                this.GenStmt(assign);
                // jump to the test
                Emit.Label test = this.il.DefineLabel();
                this.il.Emit(Emit.OpCodes.Br, test);

                // statements in the body of the for loop
                Emit.Label body = this.il.DefineLabel();
                this.il.MarkLabel(body);
                this.GenStmt(forLoop.Body);

                // to (increment the value of x)
                this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]);
                this.il.Emit(Emit.OpCodes.Ldc_I4, 1);
                this.il.Emit(Emit.OpCodes.Add);
                this.Store(forLoop.Ident, typeof(int));

                // **test** does x equal 100? (do the test)
                this.il.MarkLabel(test);
                this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]);
                this.GenExpr(forLoop.To, typeof(int));
                this.il.Emit(Emit.OpCodes.Blt, body);
            }
            else
            {
                throw new System.Exception("don't know how to gen a " + stmt.GetType().Name);
            }
        }
Example #10
0
    private Stmt ParseStmt()
    {
        Stmt result;

        if (this.index == this.tokens.Count)
        {
            throw new System.Exception("expected statement, got EOF");
        }

        // <stmt> := print <expr>

        // <expr> := <string>
        // | <int>
        // | <arith_expr>
        // | <ident>
        if (this.tokens[this.index].Equals("print"))
        {
            this.index++;
            Print print = new Print();
            print.Expr = this.ParseExpr();
            result = print;
        }
        else if (this.tokens[this.index].Equals("var"))
        {
            this.index++;
            DeclareVar declareVar = new DeclareVar();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                declareVar.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected variable name after 'var'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected = after 'var ident'");
            }

            this.index++;

            declareVar.Expr = this.ParseExpr();
            result = declareVar;
        }
        else if (this.tokens[this.index].Equals("read_int"))
        {
            this.index++;
            ReadInt readInt = new ReadInt();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                readInt.Ident = (string)this.tokens[this.index++];
                result = readInt;
            }
            else
            {
                throw new System.Exception("expected variable name after 'read_int'");
            }
        }
        else if (this.tokens[this.index].Equals("for"))
        {
            this.index++;
            ForLoop forLoop = new ForLoop();

            if (this.index < this.tokens.Count &&
                this.tokens[this.index] is string)
            {
                forLoop.Ident = (string)this.tokens[this.index];
            }
            else
            {
                throw new System.Exception("expected identifier after 'for'");
            }

            this.index++;

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("for missing '='");
            }

            this.index++;

            forLoop.From = this.ParseExpr();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("to"))
            {
                throw new System.Exception("expected 'to' after for");
            }

            this.index++;

            forLoop.To = this.ParseExpr();

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("do"))
            {
                throw new System.Exception("expected 'do' after from expression in for loop");
            }

            this.index++;

            forLoop.Body = this.ParseStmt();
            result = forLoop;

            if (this.index == this.tokens.Count ||
                !this.tokens[this.index].Equals("end"))
            {
                throw new System.Exception("unterminated 'for' loop body");
            }

            this.index++;
        }
        else if (this.tokens[this.index] is string)
        {
            // assignment

            Assign assign = new Assign();
            assign.Ident = (string)this.tokens[this.index++];

            if (this.index == this.tokens.Count ||
                this.tokens[this.index] != Scanner.Equal)
            {
                throw new System.Exception("expected '='");
            }

            this.index++;

            assign.Expr = this.ParseExpr();
            result = assign;
        }
        else
        {
            throw new System.Exception("parse error at token " + this.index + ": " + this.tokens[this.index]);
        }

        if (this.index < this.tokens.Count && this.tokens[this.index] == Scanner.Semi)
        {
            this.index++;

            if (this.index < this.tokens.Count &&
                !this.tokens[this.index].Equals("end"))
            {
                Sequence sequence = new Sequence();
                sequence.First = result;
                sequence.Second = this.ParseStmt();
                result = sequence;
            }
        }

        return result;
    }