public override void Visit(ForNode node) { node.Counter.Visit(this); node.Begin.Visit(this); node.End.Visit(this); node.Stat.Visit(this); }
/// <summary> /// This method type checks the ForNode node in the AST. /// </summary> /// <param name="forNode">The node to check.</param> /// <returns>Returns null</returns> public override object Visit(ForNode forNode) { CurrentScope = GlobalScope.FindChild($"LOOPF_{forNode.Line}"); TypeContext fromType = (TypeContext)forNode.From.Accept(this); TypeContext toType = (TypeContext)forNode.To.Accept(this); if (null == CurrentScope.FindSymbol(forNode.CountingVariable)) { CurrentScope.Symbols.Add(new Symbol(forNode.CountingVariable.Id, NUMERIC, false, forNode.CountingVariable)); } else { CurrentScope.UpdateTypedef(forNode.CountingVariable, new TypeContext(TokenType.NUMERIC) { IsFloat = false }, CurrentScope.Name, true); } if (fromType.Type != toType.Type) { new InvalidTypeException($"Mismatch in range types at {forNode.Line}:{forNode.Offset}"); } forNode.Statements.ForEach(stmnt => stmnt.Accept(this)); CurrentScope = CurrentScope.Parent ?? GlobalScope; return(null); }
public override void VisitForNode(ForNode c) { c.Parent = st.Peek(); st.Push(c); base.VisitForNode(c); st.Pop(); }
public virtual ASTNode Transform(ForNode item) { var primaryBlock = item.PrimaryBlock.Transform(this) as ContainerNode; if (primaryBlock == default) { throw new NotImplementedException(); } ContainerNode?elseBlock = null; if (item.ElseBlock != null) { elseBlock = item.ElseBlock.Transform(this) as ContainerNode; if (elseBlock == default) { throw new NotImplementedException(); } } if (item.Expression != null) { return(new ForNode(primaryBlock, elseBlock, item.VariableNames, item.Expression, item.Filter, item.Recursive, item.EndParsingNode, item.WhiteSpaceControl)); } else { return(new ForNode(primaryBlock, elseBlock, item.VariableNames, item.AlreadyEvaluatedObject, item.Filter, item.Recursive, item.EndParsingNode, item.WhiteSpaceControl)); } }
public virtual void Visit(ForNode node) { if (node != null) { if (node.Initializer != null) { node.Initializer.Accept(this); } if (node.Condition != null) { node.Condition.Accept(this); } if (node.Incrementer != null) { node.Incrementer.Accept(this); } if (node.Body != null) { node.Body.Accept(this); } } }
public override void VisitForNode(ForNode c) { c.Assign.Visit(this); c.Expr.Visit(this); var limit = genc.DeclareLocal(typeof(int)); // переменная цикла cycle genc.Emit(OpCodes.Stloc, limit); Label startLoop = genc.DefineLabel(); Label endLoop = genc.DefineLabel(); genc.MarkLabel(startLoop); genc.Emit(OpCodes.Ldloc, vars[c.Assign.Id.Name]); genc.Emit(OpCodes.Ldloc, limit); genc.Emit(OpCodes.Bge, endLoop); c.Stat.Visit(this); genc.Emit(OpCodes.Ldloc, vars[c.Assign.Id.Name]); genc.Emit(OpCodes.Ldc_I4_1); genc.Emit(OpCodes.Add); genc.Emit(OpCodes.Stloc, vars[c.Assign.Id.Name]); genc.Emit(OpCodes.Br, startLoop); genc.MarkLabel(endLoop); }
public void Visit(ForNode forNode) { if (forNode.Initialize != null) { forNode.Initialize.Parent = forNode; forNode.Initialize.Accept(this); } if (forNode.Condition != null) { forNode.Condition.Parent = forNode; forNode.Condition.Accept(this); } forNode.Body.Parent = forNode; var loop = _currentLoop; _currentLoop = LoopType.Loop; forNode.Body.Accept(this); _currentLoop = loop; if (forNode.Increment != null) { forNode.Increment.Parent = forNode; forNode.Increment.Accept(this); } }
/// <summary> /// Посещение узла с циклом for /// </summary> /// <param name="w">Узел ForNode</param> public virtual void VisitForNode(ForNode w) { Text += IndentStr() + "for("; w.Assign.Visit(this); Text += ","; w.Border.Visit(this); if (w.Inc != null) { Text += ","; w.Inc.Visit(this); } Text += ")"; Text += Environment.NewLine; if (!(w.Body is BlockNode)) { IndentPlus(); w.Body.Visit(this); Text += ";" + Environment.NewLine; IndentMinus(); } else { w.Body.Visit(this); } }
public override void VisitForNode(ForNode f) { f.Start.Visit(this); f.Id.Visit(this); f.End.Visit(this); f.Stat.Visit(this); }
/// <summary> /// This method visits a for loop node /// It first checks count value start is smaller then the amount of loop required and then inserts the symbols /// It either increments or decrements /// The second if statements accepts the statements in the forloop /// </summary> /// <param name="forNode">The name of the node</param> /// <returns>It returns the for loop</returns> public override object Visit(ForNode forNode) { string forLoop = ""; if (forNode.From.IValue < forNode.To.IValue) { forLoop += "for(int " + forNode.CountingVariable.Id + "=" + forNode.From.IValue + ";" + forNode.CountingVariable.Id + "<" + forNode.To.IValue + ";" + forNode.CountingVariable.Id + "++){"; } else { forLoop += "for(int " + forNode.CountingVariable.Id + "=" + forNode.From.IValue + ";" + forNode.CountingVariable.Id + "<" + forNode.To.IValue + ";" + forNode.CountingVariable.Id + "--){"; } if (forNode.Statements.Any()) { forNode.Statements.ForEach(node => node.Parent = forNode); forNode.Statements.ForEach(node => forLoop += ((string)node.Accept(this))); } forLoop += "}"; return(forLoop); }
public override void VisitForNode(ForNode f) { string Id = f.Id.Name; string forHeadLabel = ThreeAddressCodeTmp.GenTmpLabel(); string forBodyLabel = ThreeAddressCodeTmp.GenTmpLabel(); string exitLabel = ThreeAddressCodeTmp.GenTmpLabel(); string fromTmpName = Gen(f.From); GenCommand("", "assign", fromTmpName, "", Id); string toTmpName = Gen(f.To); // Делаем допущение, что for шагает на +1 до границы, не включая ее string condTmpName = ThreeAddressCodeTmp.GenTmpName(); GenCommand(forHeadLabel, "LESS", Id, toTmpName, condTmpName); GenCommand("", "ifgoto", condTmpName, forBodyLabel, ""); GenCommand("", "goto", exitLabel, "", ""); var instructionIndex = Instructions.Count; f.Stat.Visit(this); Instructions[instructionIndex].Label = forBodyLabel; GenCommand("", "PLUS", Id, "1", Id); GenCommand("", "goto", forHeadLabel, "", ""); GenCommand(exitLabel, "noop", "", "", ""); }
public virtual void VisitForNode(ForNode f) { f.Assign.Visit(this); f.Border.Visit(this); f.Inc.Visit(this); f.Body.Visit(this); }
private void Parsing(ForNode node, StringBuilder sb, ref int lineNum) { Parsing(node.GetChild(0) as dynamic, sb, ref lineNum); // инициализация int logicLine = lineNum; Parsing(node.GetChild(1) as dynamic, sb, ref lineNum); // условие PrintCommand(sb, "clt", ref lineNum); // проверка условия // цикл int lineBlock = lineNum + 1; StringBuilder sb2 = new StringBuilder(); Parsing(node.Block, sb2, ref lineBlock); // блок кода Parsing(node.GetChild(2) as dynamic, sb2, ref lineBlock); //инкремент PrintCommand(sb2, String.Format("br L_{0:D6}", logicLine), ref lineBlock); // цикл PrintCommand(sb, String.Format("brfalse L_{0:D6}", lineBlock), ref lineNum); // выход из цикла sb.Append(sb2); lineNum = lineBlock; }
public override void VisitForNode(ForNode c) { c.Begin.Visit(this); c.End.Visit(this); c.Counter.Visit(this); c.Stat.Visit(this); }
public void VisitFor(ForNode node) { node.Declaration = _processor.ProcessReplacement(node.Declaration); node.Condition = _processor.ProcessReplacement(node.Condition); node.Update = _processor.ProcessReplacement(node.Update); node.Body = _processor.ProcessReplacement(node.Body); }
public void Accept(ForNode node) { var bodyLabel = nextLabel(); var repeatLabel = nextLabel(); var endLabel = nextLabel(); int breakLabelCount = methodStack.Peek().BreakLabels.Count; int continueLabelCount = methodStack.Peek().ContinueLabels.Count; methodStack.Peek().BreakLabels.Push(endLabel); methodStack.Peek().ContinueLabels.Push(repeatLabel); table.EnterScope(); node.InitialStatement.Visit(this); emitLabel(node.Condition.SourceLocation, bodyLabel); node.Condition.Visit(this); emit(node.Condition.SourceLocation, InstructionType.JumpIfFalse, endLabel); if (node.Body is CodeBlockNode) { node.Body.VisitChildren(this); } else { node.Body.Visit(this); } emitLabel(node.RepeatStatement.SourceLocation, repeatLabel); node.RepeatStatement.Visit(this); emit(node.RepeatStatement.SourceLocation, InstructionType.Jump, bodyLabel); emitLabel(node.RepeatStatement.SourceLocation, endLabel); table.LeaveScope(); restoreLabels(breakLabelCount, continueLabelCount); }
public void Transform(ForNode item, bool inner = false) { SetTrim(item.WhiteSpaceControl.Start); item.PrimaryBlock.Transform(this, inner: true); item.ElseBlock?.Transform(this, inner: true); _WhiteSpaceMode = item.WhiteSpaceControl.End; }
private Statement ProcessForStatement(ForNode node) { ForStatement statement = new ForStatement(); symbolTable.PushScope(); if (node.Initializer != null) { if (node.Initializer is VariableDeclarationNode) { VariableDeclarationStatement initializer = (VariableDeclarationStatement)BuildStatement((StatementNode)node.Initializer); statement.AddInitializer(initializer); } else { Debug.Assert(node.Initializer is ExpressionListNode); ICollection <Expression> initializers = expressionBuilder.BuildExpressionList((ExpressionListNode)node.Initializer); foreach (Expression initializer in initializers) { statement.AddInitializer(initializer); } } } if (node.Condition != null) { Expression condition = expressionBuilder.BuildExpression(node.Condition); if (condition is MemberExpression) { condition = expressionBuilder.TransformMemberExpression((MemberExpression)condition); } statement.AddCondition(condition); } if (node.Increment != null) { Debug.Assert(node.Increment is ExpressionListNode); ICollection <Expression> increments = expressionBuilder.BuildExpressionList((ExpressionListNode)node.Increment); foreach (Expression increment in increments) { statement.AddIncrement(increment); } } Statement body = BuildStatement((StatementNode)node.Body); statement.AddBody(body); symbolTable.PopScope(); return(statement); }
private void Parsing(ForNode node, string methodName) { Parsing(node.GetChild(0) as dynamic, methodName); dynamic temp = node.GetChild(1); // Logic operation Parsing(temp, methodName); Parsing(node.VarInitValue, methodName); Parsing(node.Block, methodName); }
public void VisitFor(ForNode node) { _visitor.VisitStatement(node); VisitDeclaration(node.Declaration); node.Condition.AcceptSyntaxTreeVisitor(_childrenVisitor); node.Update.AcceptSyntaxTreeVisitor(_childrenVisitor); VisitBody(node.Body); }
public void VisitFor(ForNode node) { Print("For"); VisitSubnode(node.Declaration); VisitSubnode(node.Condition); VisitSubnode(node.Update); VisitBody(node.Body); }
public override void VisitForNode(ForNode f) { if (WithinIf) { HasCycleNestedToIf = true; } base.VisitForNode(f); }
public void VisitFor(ForNode node) { // Don't insert unreachable code if (!_builder.InsertBlock.IsValid) { return; } Metadata oldLexicalScope = _lexicalScope; if (_genContext.DebugInfo) { _genContext.TryGetNodeSymbol(node.Declaration, out Symbol declRange); _lexicalScope = _genContext.DiBuilder.CreateLexicalBlock(_lexicalScope, _genContext.DiFile, declRange.LLVMLine, _genContext.ColumnInfo ? declRange.LLVMColumn : 0); } node.Declaration.AcceptStatementVisitor(this); BasicBlock condBasicBlock = _genContext.Context.AppendBasicBlock(_function.FunctionValue, "for.cond"); BasicBlock bodyBasicBlock = _genContext.Context.AppendBasicBlock(_function.FunctionValue, "for.body"); BasicBlock incBasicBlock = _genContext.Context.AppendBasicBlock(_function.FunctionValue, "for.inc"); BasicBlock endBasicBlock = _genContext.Context.AppendBasicBlock(_function.FunctionValue, "for.end"); SetCurrentDebugLocation(node); BuildBrIfNecessary(condBasicBlock); _builder.PositionAtEnd(condBasicBlock); node.Condition.AcceptExpressionVisitor(this); Value condVal = _visitedValue; if (!condVal.IsValid) { throw new InvalidOperationException("condition did not produce a usable rvalue"); } SetCurrentDebugLocation(node); condVal = ConvertToBool(condVal); _builder.BuildCondBr(condVal, bodyBasicBlock, endBasicBlock); _builder.PositionAtEnd(bodyBasicBlock); BreakContinue oldBreakContinueTop = _breakContinueTop; _breakContinueTop = new BreakContinue(endBasicBlock, incBasicBlock); VisitBody(node.Body); _breakContinueTop = oldBreakContinueTop; BuildBrIfNecessary(incBasicBlock); _builder.PositionAtEnd(incBasicBlock); node.Update.AcceptExpressionVisitor(this); BuildBrIfNecessary(condBasicBlock); _builder.PositionAtEnd(endBasicBlock); _lexicalScope = oldLexicalScope; }
public void TestForNodeLackInKeyword() { string t = "#{for i array[1, 2, 3]}"; LexicalParser lp = new LexicalParser(); lp.SetParseContent(t); var tokens = lp.Parse(); ForNode f = new ForNode(tokens[0]); }
public void TestForNodeInvalidVarName() { string t = "#{for $ in array[1, 2, 3]}"; LexicalParser lp = new LexicalParser(); lp.SetParseContent(t); var tokens = lp.Parse(); ForNode f = new ForNode(tokens[0]); }
public IEnumerable <ASTNode> Transform(ForNode item) { yield return(item); foreach (var child in TransformAll(new ASTNode?[] { item.PrimaryBlock, item.ElseBlock, item.Expression, item.Filter })) { yield return(child); } }
public void TestForNodeWithColon() { string t = "#{:for i in array[1 : 10]:}"; LexicalParser lp = new LexicalParser(); lp.SetParseContent(t); var tokens = lp.Parse(); ForNode f = new ForNode(tokens[0]); }
public override void VisitForNode(ForNode c) { Text += IndentStr() + "for "; c.Assign.Visit(this); Text += IndentStr() + " to "; c.Expr.Visit(this); Text += Environment.NewLine; c.Stat.Visit(this); }
public override void VisitForNode(ForNode f) { PreVisit(f); f.Id.Visit(this); f.From.Visit(this); f.To.Visit(this); f.Stat.Visit(this); PostVisit(f); }
public object VisitForNode(ForNode node, Context parameter) { foreach (var child in node.Children) { child.Accept(this, parameter); } return(null); }
public virtual void Visit(ForNode node) { if (node != null) { AcceptChildren(node); } }
public static ClassNode Parse(string sScript) { ArrayList aAllLines = new ArrayList(); string[] aKeywords = new string[]{"for", "else if", "if", "else", "while", "goto", "gosub", "return"}; //TODO: I don't handle keyword and a statement on the same line right now- //e.g. "if (true) blabla();" or "for (;;) put(1);" BaseNode rootNode = new BaseNode(); ClassNode classNode = new ClassNode(); rootNode.AppendChild("Class_01", classNode); BaseNode currentNode = classNode; //easier parsing if \r\n is replaced by \n sScript = sScript.Replace("\r\n", "\n"); //also a little easier if script always ends with a \n if (!sScript.EndsWith("\n")) sScript+="\n"; //structure will be [ScriptName:[MethodName:[LabelName:[clause:[clause]]]]] //Labels must be on top level in a method (e.g. not inside an if(){} clause) while (sScript.Length > 0) { //first divide into "lines" - EndOfLine represented by: return ; { or } string sLine = ""; string sDividerChar = ""; MatchCollection matches = Regex.Matches(sScript, "[^{};\\n]*[{};\\n]"); foreach (Match m in matches) { sLine = sScript.Substring(0, m.Index+m.Length); sDividerChar = m.Value.Substring(m.Value.Length-1,1); if (sDividerChar == ";") { //must check if the ";" is inside parenthesis - if so, it doesn't count (e.g. "for(;;)") //only when the number of "(" is the same as the number of ")", the ";" is outside string sCheck = sLine.Replace("(", ""); int nNumRight = sLine.Length-sCheck.Length; sCheck = sLine.Replace(")", ""); int nNumLeft = sLine.Length-sCheck.Length; if (nNumRight != nNumLeft) continue; } sScript = sScript.Remove(0, sLine.Length); sLine = sLine.Remove(sLine.Length-1,1); break; } sLine = sLine.Trim(); //handle if the line only consists of a { or } if (sLine.Length == 0) { if (HandleNodeBorderChars(sDividerChar, ref currentNode)) continue; } //empty and remmed lines are ignored: if (sLine.Length == 0 || sLine.IndexOf("//") == 0) { continue; } if (currentNode.GetType() == typeof(ClassNode)) //.Depth == 1) //class level, i.e. where methods are defined { //search for "on method([args])" Match m = Regex.Match(sLine, "on\\s*\\w*\\s*[(][^()]*[)]"); if (m.Success) { string sMethod = m.Value.Replace("on ", "").Trim(); string sArgs = sMethod.Remove(0,sMethod.IndexOf("(")); sMethod = sMethod.Substring(0,sMethod.IndexOf("(")); MethodNode methodNode = new MethodNode(); methodNode.DefineArguments(sArgs.Substring(1,sArgs.Length-2)); currentNode.AppendChild(sMethod, methodNode); currentNode = methodNode; continue; } } //separate code flow keywords/tokens from expressions if (sLine.IndexOf(":") == sLine.Length-1) { //it's a label. Labels can currently only occur on Method level if (currentNode.GetType() != typeof(MethodNode)) throw new Exception("Labels must be defined in Method scope!"); //TODO: Labels can't be nodes - they're not defined with {}'s... More like an HTML anchor //sLine.Substring(0,sLine.Length-2) } #region Check for keywords foreach (string sKeyword in aKeywords) { //[^\\w]+*[( ]* Match m = Regex.Match(sLine+" ", sKeyword+"[^\\w]+[( ]*"); //"\\s*[(]*"); if (m.Success) { ChunkNode newNode = null; string sArgs = GetStringWithinParenthesis(sLine); switch (sKeyword) { case "for": ForNode forNode = new ForNode(); forNode.SetConditions(sArgs); newNode = forNode; //With the current line seek method, the ";" in for(;;) forces us to look ahead in script //TODO: lookahead for(;;) break; case "if": if (sArgs == null) throw new Exception("If statement incomplete"); IfNode ifNode = new IfNode(); ifNode.SetIfStatement(sArgs); newNode = ifNode; break; case "else if": case "else": //is the current node an IfNode? if (currentNode.GetType() != typeof(IfNode)) throw new Exception("\""+sKeyword+"\" must come after an \"if\" statement"); IfNode elseifNode = new IfNode(); if (sKeyword == "else if") { //TODO: don't understand C# scopes... Why can't I define sArgs here too? Can't see any risk for confusion or mistakes!? //And sometimes it's too slack: //a member variable can have the same name as a variable in a method with no complaits, //although that is clearly a mistake in most cases? if (sArgs == null) throw new Exception("Else if statement incomplete"); elseifNode.SetIfStatement(sArgs); } IfNode oldIfNode = (IfNode)currentNode; oldIfNode.SetNextIfNode(elseifNode); newNode = elseifNode; break; } if (newNode!=null) { newNode.CloseNodeAfterNextLine = true; currentNode.AppendChild(sKeyword, newNode); currentNode = newNode; } break; } } #endregion if (HandleNodeBorderChars(sDividerChar, ref currentNode)) continue; string sStatement = sLine; ExpressionNode expNode = new ExpressionNode(); expNode.SetExpression(sStatement); currentNode.AppendChild(sStatement, expNode); //TODO: how to check nicely if ChunkNode is one of the base classes of currentNode?? This is ugly (?): try { ChunkNode chunkNode = (ChunkNode)currentNode; if (chunkNode.CloseNodeAfterNextLine) currentNode = (BaseNode)currentNode.ParentNode; } catch {} } // System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); // rootNode.AddToXml(doc); // doc.Save("Testing.xml"); return classNode; }
public virtual bool Walk(ForNode node) { return true; }
public virtual void PostWalk(ForNode node) { }
private static void GenerateFor(ForNode node, DataContext data) { StartLine(data, "for ("); data.CodeBlock.DisableNewLines = true; if (node.InitializeSyntax is VariableDeclarationNode) { GenerateStatement((VariableDeclarationNode)node.InitializeSyntax, data); } else if (node.InitializeSyntax is ExpressionNode) { GenerateExpression((ExpressionNode)node.InitializeSyntax, data); } else { ThrowUnableToGenerateException("For initializer", node.InitializeSyntax); } Append(data, " "); GenerateExpression(node.EvaluateExpression, data); Append(data, "; "); GenerateExpression(node.IncrementExpression, data); data.CodeBlock.DisableNewLines = false; EndLine(data, ") {{"); data.CodeBlock.Padding++; GenerateStatementBlock(node.BodyStatementBlock, data); data.CodeBlock.Padding--; WriteLine(data, "}}"); }
public ITreeNode Program() { ITreeNode programNode = new ErrorNode(); switch (curTokenType) { case TokenType.BEGINBL: Match(ref matchToken, TokenType.BEGINBL); ITreeNode someStatement = Program(); BlockNode block = new BlockNode(); block.addStatement(someStatement); while (curTokenType != TokenType.ENDBL) { someStatement = Program(); block.addStatement(someStatement); } Match(ref matchToken, TokenType.ENDBL); programNode = block; break; case TokenType.LABEL: Match(ref matchToken, TokenType.LABEL); LabelNode labeledBlock = new LabelNode(matchToken.getValue()); ITreeNode labeledStatement; do { labeledStatement = Program(); labeledBlock.addStatement(labeledStatement); } while (curTokenType != TokenType.EOF); programNode = labeledBlock; break; case TokenType.INTDEC: Match(ref matchToken, TokenType.INTDEC); Match(ref matchToken, TokenType.ID); programNode = new IdentifierDeclarationNode(IdentifierType.INT, matchToken.getValue()); Match(ref matchToken, TokenType.EOS); break; case TokenType.BOOLDEC: Match(ref matchToken, TokenType.BOOLDEC); Match(ref matchToken, TokenType.ID); programNode = new IdentifierDeclarationNode(IdentifierType.BOOL, matchToken.getValue()); Match(ref matchToken, TokenType.EOS); break; case TokenType.FOR: Match(ref matchToken, TokenType.FOR); Match(ref matchToken, TokenType.LPAREN); AssignmentNode init = (AssignmentNode)Program(); AssignmentNode step = (AssignmentNode)Program(); BooleanExpressionNode condition = (BooleanExpressionNode)BooleanExpression(); Match(ref matchToken, TokenType.RPAREN); BlockNode forBody = (BlockNode)Program(); programNode = new ForNode(init, step, condition, forBody); break; /*case TokenType.FUN: Match(ref matchToken, TokenType.FUN); IdentifierNode id = (IdentifierNode)Factor(); programNode = new FunctionNode(id); Match(ref matchToken, TokenType.EOS); break;*/ case TokenType.GOTO: Match(ref matchToken, TokenType.GOTO); Match(ref matchToken, TokenType.ID); IdentifierNode gotoLabel = new IdentifierNode(matchToken.getValue(), IdentifierType.LABEL); programNode = new GotoNode(gotoLabel); Match(ref matchToken, TokenType.EOS); break; case TokenType.ID: Match(ref matchToken, TokenType.ID); IdentifierNode assignId = new IdentifierNode(matchToken.getValue(), IdentifierType.UNKNOWN); Match(ref matchToken, TokenType.ASSIGN); BooleanExpressionNode assignValue = (BooleanExpressionNode)BooleanExpression(); programNode = new AssignmentNode(assignId, assignValue); Match(ref matchToken, TokenType.EOS); break; case TokenType.IF: Match(ref matchToken, TokenType.IF); ITreeNode thenBranch; ITreeNode elseBranch; Match(ref matchToken, TokenType.LPAREN); BooleanExpressionNode ifCondition = (BooleanExpressionNode)BooleanExpression(); Match(ref matchToken, TokenType.RPAREN); Match(ref matchToken, TokenType.THEN); thenBranch = (BlockNode)Program(); if (curTokenType == TokenType.ELSE) { Match(ref matchToken, TokenType.ELSE); elseBranch = (BlockNode)Program(); } else { elseBranch = new BlankNode(); } programNode = new IfNode(ifCondition, thenBranch, elseBranch); break; /*case TokenType.LET: Match(ref matchToken, TokenType.LET); IdentifierNode shortId = (IdentifierNode)Factor(); Match(ref matchToken, TokenType.ASSIGN); BooleanExpressionNode subst = (BooleanExpressionNode)BooleanExpression(); Match(ref matchToken, TokenType.IN); BooleanExpressionNode target = (BooleanExpressionNode)BooleanExpression(); programNode = new LetNode(shortId, subst, target); Match(ref matchToken, TokenType.EOS); break;*/ case TokenType.PRINT: Match(ref matchToken, TokenType.PRINT); Match(ref matchToken, TokenType.LPAREN); BooleanExpressionNode printArgument = (BooleanExpressionNode)BooleanExpression(); Match(ref matchToken, TokenType.RPAREN); programNode = new PrintNode(printArgument); Match(ref matchToken, TokenType.EOS); break; case TokenType.WHILE: Match(ref matchToken, TokenType.WHILE); Match(ref matchToken, TokenType.LPAREN); BooleanExpressionNode whileCondition = (BooleanExpressionNode)BooleanExpression(); Match(ref matchToken, TokenType.RPAREN); BlockNode whileBody = (BlockNode)Program(); programNode = new WhileNode(whileCondition, whileBody); break; case TokenType.EOF: programNode = new BlankNode(); break; default: Expect(TokenType.UNKNOWN, lookAheadToken); break; } return programNode; }