public void ToString_OfForNext_Converts() { var forNext = new ForNext(new ScalarVariable("I"), new Constant("1"), new Constant("5"), new Constant("1"), new PrintLine(new[] { new ScalarVariable("I") })); var actual = forNext.ToString(); Assert.AreEqual("FOR I = 1 TO 5 STEP 1 PRINT I NEXT", actual); }
public void Execute_OfForNext_RepeatsInnerStatement() { var rte = MakeRunTimeEnvironment(); var i = new ScalarVariable("I"); var from = new Constant(1); var to = new Constant(10); var step = new Constant(1); var shoudBeEqualTo50 = 0; var forNext = new ForNext(i, from, to, step, MakeStatement(() => { shoudBeEqualTo50 += 5; })); forNext.Execute(rte); Assert.AreEqual(50, shoudBeEqualTo50); }
public static bool TryReadFor(this Scanner scanner, out IStatement result) { if (scanner.TryReadToken(Token.For)) { ILValue loopVariable = scanner.ReadLValue(); scanner.ReadToken(Token.Eq); IExpression from = scanner.ReadExpression(); scanner.ReadToken(Token.To); IExpression to = scanner.ReadExpression(); IExpression step = null; if (scanner.TryReadToken(Token.Step)) { step = scanner.ReadExpression(); } if (scanner.CurrentToken == Token.Next) { throw new ParserException(ErrorMessages.MissingStatement); } IStatement statement; if (scanner.TryReadStatementExcludingNext(out statement)) { scanner.ReadToken(Token.Next); result = new ForNext(loopVariable, from, to, step, statement); } else { result = new For(loopVariable, from, to, step); } return(true); } result = null; return(false); }
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); }
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); } }