コード例 #1
0
        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;
            //}
        }
コード例 #2
0
        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"));
                    }
                }
            }
        }
コード例 #3
0
        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)));
        }
コード例 #4
0
 private void TunnelingProcessNode(SyntaxTreeNode node)
 {
     if (node.Value is Nonterminal)
     {
         Nonterminal nonterminal = node.Value as Nonterminal;
     }
     else
     {
         ConcreteTerminal terminal = node.Value as ConcreteTerminal;
     }
 }
コード例 #5
0
        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
            }
        }
コード例 #6
0
        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
        }
コード例 #7
0
 private string GenerateErrorMessage(Terminal expectedTerminal, ConcreteTerminal inputTerminal)
 {
     return(string.Format("{0} expected, but received {1}", expectedTerminal, inputTerminal));
 }