Exemplo n.º 1
0
 public void SetPrecedence(IPrecedenceGroup precedenceGroup)
 {
     _production.SetPrecedence(precedenceGroup);
 }
Exemplo n.º 2
0
        private void SetActionTable(short[,] table, int state, int tokenNumber, short value)
        {
            // This is an error condition, find out what sort of exception it is
            short oldValue = table[state, tokenNumber];

            if ((oldValue != value) && (oldValue != short.MinValue))
            {
                try
                {
                    if (oldValue < 0 && value < 0) // Both values are reduce. Throw a reduce reduce conflict. This is not solveable. NOTE: Bison takes the first rule (here 'oldValue')
                    {
                        throw new ReduceReduceConflictException <T>("Grammar contains a reduce reduce conflict");
                    }

                    int   shiftTokenNumber = tokenNumber;
                    int   reduceRuleNumber;
                    short shiftValue;
                    short reduceValue;

                    if (oldValue < 0)
                    {
                        // The old value was a reduce, the new must be a shift
                        shiftValue       = value;
                        reduceValue      = oldValue;
                        reduceRuleNumber = -(oldValue + 1);
                    }
                    else
                    {
                        // TODO: Unsure if this is a real case. The only testcases that end up here are retarded tests which are cyclic in nature.
                        // TODO: These cases always fail later on anyway due to conflicts.
                        // The old value was a shift, the new value must be a reduce
                        shiftValue       = oldValue;
                        reduceValue      = value;
                        reduceRuleNumber = -(value + 1);
                    }

                    // Check if these tokens have declared precedences and associativity
                    // If they do, we might be able to act on this.
                    Terminal <T>        shiftingTerminal = grammar.AllSymbols.OfType <Terminal <T> >().First(f => f.TokenNumber == shiftTokenNumber);
                    IPrecedenceGroup    shiftPrecedence  = grammar.GetPrecedence(shiftingTerminal);
                    IProductionRule <T> productionRule   = reductionRules[reduceRuleNumber].Item1;

                    // If the rule has a context dependent precedence, use that. Otherwise use the reduce precedence of the last terminal symbol in the production rules precedence
                    IPrecedenceGroup reducePrecedence = productionRule.ContextPrecedence ?? grammar.GetPrecedence(productionRule.Symbols.Reverse().OfType <ITerminal <T> >().FirstOrDefault());

                    // If either rule has no precedence this is not a legal course of action.
                    // TODO: In bison this is apparently cool, it prefers to shift in this case. I don't know why, but this seems like a dangerous course of action to me.
                    if (shiftPrecedence == null || reducePrecedence == null)
                    {
                        throw new ShiftReduceConflictException <T>("Grammar contains a shift reduce conflict")
                              {
                                  ShiftSymbol  = shiftingTerminal,
                                  ReduceSymbol = productionRule.ResultSymbol,
                              }
                    }
                    ;

                    if (shiftPrecedence.Precedence < reducePrecedence.Precedence)
                    {
                        table[state, tokenNumber] = reduceValue; // Precedence of reduce is higher, choose to reduce
                    }
                    else if (shiftPrecedence.Precedence > reducePrecedence.Precedence)
                    {
                        table[state, tokenNumber] = shiftValue; // Shift precedence is higher. Shift
                    }
                    // Both tokens are in the same precedence group! It's now up to the associativity
                    // The two tokens CANNOT have different associativity, due to how the configuration works which throws up if you try to multiple-define the precedence
                    else if (shiftPrecedence.Associativity == AssociativityDirection.Left)
                    {
                        table[state, tokenNumber] = reduceValue; // Prefer reducing
                    }
                    else if (shiftPrecedence.Associativity == AssociativityDirection.Right)
                    {
                        table[state, tokenNumber] = shiftValue; // Prefer shifting
                    }
                    else // if (shiftPrecedence.Associativity  == AssociativityDirection.NonAssociative) <- this is implied
                    {
                        throw new ShiftReduceConflictException <T>("Grammar contains a shift reduce conflict (Nonassociative)")
                              {
                                  ShiftSymbol  = shiftingTerminal,
                                  ReduceSymbol = productionRule.ResultSymbol,
                              }
                    };     // Unresolveable
                }
                catch (AmbiguousGrammarException ex)
                {
                    // Fill in more information on the error and rethrow the error
                    ex.StateNumber   = state;
                    ex.TokenNumber   = tokenNumber;
                    ex.PreviousValue = oldValue;
                    ex.NewValue      = value;

                    throw;
                }
            }
            else
            {
                table[state, tokenNumber] = value;
            }
        }
Exemplo n.º 3
0
 public void SetPrecedence(IPrecedenceGroup precedenceGroup) => ContextPrecedence = precedenceGroup;