private void SubstituteTreeTerminalByActualValue(Terminal treeTerminal, ConcreteTerminal actualTerminal) { // ToDo: Replace this ugly and AWFUL PERFORMANCE code! var node = _syntaxTree.FindFirst( n => n.Value is Terminal && (n.Value as Terminal).Type != TokenType.Epsilon && !_replacedTerminalNodes.Contains(n)); _replacedTerminalNodes.Add(node); node.Value = actualTerminal; //if (treeTerminal is GeneralizedTerminal) //{ // // replace first non epsilon generalized terminal // var node = _syntaxTree.FindFirst(n => n.Value is GeneralizedTerminal && !n.Value.Equals(GeneralizedTerminal.Epsilon)); // node.Value = actualTerminal; //} //else //{ // // if Token.Position == null, then come from production // var node = _syntaxTree.FindFirst(n => n.Value is ConcreteTerminal && (n.Value as ConcreteTerminal).Token.Position == null); // node.Value = actualTerminal; //} }
private void BubblingProcessNode(SyntaxTreeNode node) { if (node.Value is Nonterminal) { Nonterminal nonterminal = node.Value as Nonterminal; if (nonterminal.Equals(MyNonterminals.ASSIGN_STATEMENT) && node.ChildrenCount == 4) { var idToken = (node[1].Value as ConcreteTerminal).Token; string defVariableName = idToken.Value; if (!_defindedVariables.Contains(defVariableName)) { _defindedVariables.Add(defVariableName); } else { _errors.Add(new Error(idToken, ErrorKind.Semantic, "Variable redefinition")); } } } else { ConcreteTerminal terminal = node.Value as ConcreteTerminal; if (terminal.Token.HasType(TokenType.Identifier) && !_defindedVariables.Contains(terminal.Token.Value)) { if (((Nonterminal)node.Parent.Value).Equals(MyNonterminals.FACTOR)) { _errors.Add(new Error(terminal.Token, ErrorKind.Semantic, "Undefined variable")); } } } }
private string GenerateErrorMessage(Nonterminal disclosingNonterminal, ConcreteTerminal inputTerminal) { var expected = GetExpectedTerminalsFor(disclosingNonterminal) .Except(new[] { GeneralizedTerminal.Epsilon, GeneralizedTerminal.EndOfText }); //return string.Format("{0} expected, but received {1} (disclosing: {2})", string.Join(" or ", expected), inputTerminal, disclosingNonterminal); return(string.Format("{0} expected, but received {1} (start with one of {{{2}}})", disclosingNonterminal, inputTerminal, string.Join(", ", expected))); }
private void TunnelingProcessNode(SyntaxTreeNode node) { if (node.Value is Nonterminal) { Nonterminal nonterminal = node.Value as Nonterminal; } else { ConcreteTerminal terminal = node.Value as ConcreteTerminal; } }
private void BubblingProcessNode(SyntaxTreeNode node) { if (node.Value is Nonterminal && !node.IsEpsilon) { var nonterminal = (Nonterminal)node.Value; if (nonterminal.Equals(FormalNonterminals.FACTOR)) { // F -> const | ( E ) | func-call | id if (node[TokenType.IntegerConstant] != null) { nonterminal[VALUE_KEY] = ((ConcreteTerminal)node[TokenType.IntegerConstant].Value).Token; } else if (node[TokenType.FloatConstant] != null) { nonterminal[VALUE_KEY] = ((ConcreteTerminal)node[TokenType.FloatConstant].Value).Token; } else if (node[TokenType.Identifier] != null) { nonterminal[VALUE_KEY] = ((ConcreteTerminal)node[TokenType.Identifier].Value).Token; } else if (node[FormalNonterminals.EXPRESSION] != null) { nonterminal[VALUE_KEY] = GetValue(node[FormalNonterminals.EXPRESSION]); } else { nonterminal[VALUE_KEY] = GetValue(node[FormalNonterminals.FUNCTION_CALL]); } } if (nonterminal.Equals(FormalNonterminals.TERM) || nonterminal.Equals(FormalNonterminals.EXPRESSION)) { // T -> F T', E -> T E' nonterminal[VALUE_KEY] = GetValue(node[1]) ?? GetValue(node[0]); } if (nonterminal.Equals(FormalNonterminals.EXPRESSION_DASH) || nonterminal.Equals(FormalNonterminals.TERM_DASH)) { // E' -> + T E' | - T E', T' -> * F T' | / F T' Operand resultVar = _code.Helper.GetTempVariable(); Operand arg1 = GetOperand(node.Parent[FormalNonterminals.TERM]) ?? GetOperand(node.Parent[FormalNonterminals.FACTOR]); // T for E', F for T' Operand arg2 = GetOperand(node[2]) ?? GetOperand(node[1]); nonterminal[VALUE_KEY] = resultVar; OpCode opCode = OpCode.Undefinded; ConcreteTerminal arithmeticOp = node[TokenType.Operator].Value as ConcreteTerminal; if (arithmeticOp.Token.Value == "+") { opCode = OpCode.ADD; } else if (arithmeticOp.Token.Value == "-") { opCode = OpCode.SUB; } else if (arithmeticOp.Token.Value == "*") { opCode = OpCode.MULT; } else if (arithmeticOp.Token.Value == "/") { opCode = OpCode.DIV; } _code.Emit(new Instruction(opCode, arg1, arg2, resultVar)); } if (nonterminal.Equals(FormalNonterminals.PARAM)) { // param -> E Operand param = GetOperand(node[FormalNonterminals.EXPRESSION]); _code.Emit(new Instruction(OpCode.PARAM, param, null, null)); } if (nonterminal.Equals(FormalNonterminals.FUNCTION_CALL)) { // func-call -> function ( param-list ) Operand resultVar = _code.Helper.GetTempVariable(); Operand funcName = new Operand(((ConcreteTerminal)node[TokenType.Function].Value).Token.Value); nonterminal[VALUE_KEY] = resultVar; _code.Emit(new Instruction(OpCode.CALL, funcName, null, resultVar)); } #region ASSIGN-STATEMENT if (nonterminal.Equals(FormalNonterminals.ASSIGN_STATEMENT)) { // assign -> id-decl = E | id = E var idSymbol = node[FormalNonterminals.ID_DECLARATION] != null ? node[FormalNonterminals.ID_DECLARATION][TokenType.Identifier] : node[TokenType.Identifier]; Operand resultVar = new Operand(((ConcreteTerminal)idSymbol.Value).Token.Value); Operand value = GetOperand(node[FormalNonterminals.EXPRESSION]); _code.Emit(new Instruction(OpCode.ASGN, value, null, resultVar)); } #endregion #region IF-STATEMENT if (nonterminal.Equals(FormalNonterminals.IF_BLOCK)) { // bool-E -> E op E // condition will be inverted, and when it equals to false goto else block (or end of if block) var boolExp = node[FormalNonterminals.BOOL_EXPRESSION]; var boolOp = boolExp[FormalNonterminals.BOOL_OPERATOR][TokenType.Operator].Value; Operand falseDestination; if (!node.Parent[FormalNonterminals.ELSE_BLOCK].IsEpsilon) { falseDestination = (Operand)node.Parent[FormalNonterminals.ELSE_BLOCK].Value[BEGIN_BLOCK_LABEL_KEY]; } else { falseDestination = (Operand)node.Parent.Value[END_BLOCK_LABEL_KEY]; } _code.Emit(new Instruction(GetCondJumpInvertOpCode(boolOp), GetOperand(boolExp[0]), GetOperand(boolExp[2]), falseDestination)); } if (nonterminal.Equals(FormalNonterminals.IF_STATEMENT)) { _code.Emit(new Instruction(OpCode.LTRGT, (Operand)node.Value[END_BLOCK_LABEL_KEY], null, null)); } if (nonterminal.Equals(FormalNonterminals.THEN_BLOCK)) { _code.Emit(new Instruction(OpCode.JMP, (Operand)node.Parent.Value[END_BLOCK_LABEL_KEY], null, null)); } #endregion #region FOR-STATEMENT if (nonterminal.Equals(FormalNonterminals.FOR_STATEMENT)) { _code.Emit(new Instruction(OpCode.LTRGT, (Operand)node.Value[END_BLOCK_LABEL_KEY], null, null)); } if (nonterminal.Equals(FormalNonterminals.FOR_TEST_BLOCK)) { var boolExp = node[FormalNonterminals.BOOL_EXPRESSION]; var boolOp = boolExp[FormalNonterminals.BOOL_OPERATOR][TokenType.Operator].Value; var bodyBeginLabel = node.Parent[FormalNonterminals.FOR_BODY_BLOCK].Value[BEGIN_BLOCK_LABEL_KEY]; var endForLabel = node.Parent.Value[END_BLOCK_LABEL_KEY]; _code.Emit(new Instruction(GetCondJumpInvertOpCode(boolOp), GetOperand(boolExp[0]), GetOperand(boolExp[2]), (Operand)endForLabel)); _code.Emit(new Instruction(OpCode.JMP, (Operand)bodyBeginLabel, null, null)); } if (nonterminal.Equals(FormalNonterminals.FOR_BODY_BLOCK)) { var stepBeginLabel = node.Parent[FormalNonterminals.FOR_STEP_BLOCK].Value[BEGIN_BLOCK_LABEL_KEY]; _code.Emit(new Instruction(OpCode.JMP, (Operand)stepBeginLabel, null, null)); } if (nonterminal.Equals(FormalNonterminals.FOR_STEP_BLOCK)) { var testBeginLabel = node.Parent[FormalNonterminals.FOR_TEST_BLOCK].Value[BEGIN_BLOCK_LABEL_KEY]; _code.Emit(new Instruction(OpCode.JMP, (Operand)testBeginLabel, null, null)); } #endregion } }
private StepResults Step(out Error error) { if (_stack.Count == 0) #region When stack is empty { if (_tokenStream.Current.Type == TokenType.EndOfText) #region ACCEPT { error = null; return(StepResults.AcceptInput); } #endregion else #region REJECT: EOF EXPECTED { error = new Error(_tokenStream.Current, ErrorKind.Syntax, "End of input expected"); return(StepResults.RejectInput); } #endregion } #endregion else #region When stack is not empty { Symbol magazineSymbol = _stack.Peek(); ConcreteTerminal inputTerminal = new ConcreteTerminal(_tokenStream.Current); if (magazineSymbol is Nonterminal) { var magazineNonterminal = (Nonterminal)magazineSymbol; AutomateAction action = _controlTable[magazineNonterminal, inputTerminal]; if (action == null && CanBeEpsilon(magazineNonterminal)) { _stack.Pop(); error = null; return(StepResults.InProgress); } if (action == null) // common error handling { error = new Error(_tokenStream.Current, ErrorKind.Syntax, GenerateErrorMessage(magazineNonterminal, inputTerminal)); return(StepResults.RejectInput); } switch (action.Kind) { case AutomateActionKind.UseProduction: _stack.Pop(); // delete disclosing nonterminal Production production = action.GetProduction(); if (!production.RightPart.IsEpsilonChain) { production.RightPart.ReverseForEach(s => _stack.Push(s)); // and push right parts of productions } ConstructSyntaxTree(production); break; case AutomateActionKind.HandleError: // custom error handling break; default: break; } error = null; return(StepResults.InProgress); } else // magazineSymbol is Terminal { var magazineTerminal = (Terminal)magazineSymbol; if (magazineTerminal.IsAppropriateTerminal(inputTerminal)) { _stack.Pop(); _tokenStream.MoveNext(); SubstituteTreeTerminalByActualValue(magazineTerminal, inputTerminal); error = null; return(StepResults.InProgress); } else { error = new Error(_tokenStream.Current, ErrorKind.Syntax, GenerateErrorMessage(magazineTerminal, inputTerminal)); return(StepResults.RejectInput); } } } #endregion }
private string GenerateErrorMessage(Terminal expectedTerminal, ConcreteTerminal inputTerminal) { return(string.Format("{0} expected, but received {1}", expectedTerminal, inputTerminal)); }