Example #1
0
        public Precedence(SymbolCoordinates coords, AssociativityEnum associativity, IEnumerable <PrecedenceWord> usedTokens)
        {
            this.Coords        = coords;
            this.Associativity = associativity;
            this.usedTokens    = usedTokens.ToArray();

            // each entry is its own micro group
            this.PriorityGroupStart = true;
            this.PriorityGroupEnd   = true;
        }
Example #2
0
        protected IEnumerable <ITokenMatch <SYMBOL_ENUM> > initParse(IEnumerable <ITokenMatch <SYMBOL_ENUM> > tokens, ParserOptions options)
        {
            messages = null;

            if (actionTable == null)
            {
                throw new Exception("The grammar is not correct.");
            }

            this.options = options;

            if (options.Trace)
            {
                parseLog = new LinkedList <ParseHistory>();
            }
            else
            {
                parseLog = null;
            }

            consecutiveCorrectActionsCount = 0;

            if (tokens.Any(it => SyntaxErrorSymbol.Equals(it.Token)))
            {
                throw new ArgumentException("All tokens have to be recognized.");
            }

            // nothing wrong if the last token is already an EOF, so skipping it
            if (tokens.SkipTail(1).Any(it => EofSymbol.Equals(it.Token)))
            {
                throw new ArgumentException("EOF token in the middle of the tokens.");
            }


            // if there are more tokens than just EOF, we strip EOF
            // because we would like to add new EOF with its position set just right after last token
            // this is solely for purpose of more precise line numbering
            if (tokens.Count() > 1 && EofSymbol.Equals(tokens.Last().Token))
            {
                tokens = tokens.SkipTail(1).ToArray();
            }

            tokens = tokens.Concat(Enumerable.Range(1, lookaheadWidth).Select(_ => new TokenMatch <SYMBOL_ENUM>(symbolsRep)
            {
                Token       = EofSymbol,
                Coordinates = tokens.Last().Coordinates
            })).ToArray();

            Coordinates = new SymbolCoordinates(false,
                                                new SymbolPosition(tokens.First().Coordinates.FirstPosition.Filename, LineNumberInit, ColumnNumberInit),
                                                new SymbolPosition(tokens.First().Coordinates.FirstPosition.Filename, LineNumberInit, ColumnNumberInit));

            return(tokens);
        }
Example #3
0
 public Playback(SymbolCoordinates initCoordinates,
                 Action <SymbolCoordinates> positionUpdate,
                 Action <string, IEnumerable <string> > addWarningMessages,
                 Action <string> addErrorMessage,
                 Func <bool> isSuccessfulParse)
 {
     this.initCoordinates    = initCoordinates;
     this.positionUpdate     = positionUpdate;
     this.addWarningMessages = addWarningMessages;
     this.addErrorMessage    = addErrorMessage;
     this.isSuccessfulParse  = isSuccessfulParse;
 }
Example #4
0
        public static Precedence Create(SymbolCoordinates coords, string mode, string associativity, IEnumerable <string> inputSymbols,
                                        IEnumerable <PrecedenceWord> conflictProds)
        {
            precedenceMode prec = getPrec(mode);

            AssociativityEnum assoc = getAssoc(associativity);

            switch (prec)
            {
            case precedenceMode.Operator: return(new OperatorPrecedence(coords, assoc, inputSymbols.Select(it => new PrecedenceWord(it)), conflictProds));

            case precedenceMode.ReduceShift: return(new ReduceShiftPrecedence(coords, assoc, inputSymbols.Select(it => new PrecedenceWord(it)), conflictProds));

            case precedenceMode.ReduceReduce: return(new ReduceReducePrecedence(coords, assoc, inputSymbols.Select(it => new PrecedenceWord(it)), conflictProds));
            }

            throw ParseControlException.NewAndRun("Not recognized precedence");
        }
Example #5
0
        public ReduceReducePrecedence(SymbolCoordinates coords, AssociativityEnum associativity,
                                      IEnumerable <PrecedenceWord> inputTokens,
                                      IEnumerable <PrecedenceWord> conflictTokens)
            : base(coords, associativity, inputTokens.Concat(conflictTokens))
        {
            try
            {
                InputSet      = inputTokens.ToArray();
                ReduceSymbols = conflictTokens.ToArray();

                if (ReduceSymbols.Count() < 2)
                {
                    throw new Exception();
                }
            }
            catch
            {
                throw ParseControlException.NewAndRun("Incorrect reduce/reduce precedence rule");
            }
        }
Example #6
0
 // in case of operator precedence -- it is just a list of tokens, not conflict resolution really
 // so we don't have do anything special
 public OperatorPrecedence(SymbolCoordinates coords, AssociativityEnum associativity,
                           IEnumerable <PrecedenceWord> inputTokens,
                           IEnumerable <PrecedenceWord> conflictTokens)
     : base(coords, associativity, inputTokens.Concat(conflictTokens))
 {
 }
Example #7
0
        internal static IEnumerable <Precedence> CreateOperators(SymbolCoordinates coords, string mode, IEnumerable <Tuple <string, string> > __opPairs,
                                                                 // it can be single and then serves as both reduce production and shift production
                                                                 // or it can be many, but then remember to put reduce production as first one (exactly as in RS rule)
                                                                 IEnumerable <string> __conflictProds)
        {
            if (!__conflictProds.Any())
            {
                throw ParseControlException.NewAndRun("There has to be at least one production given for operator precedence.");
            }

            string reduce_prod = __conflictProds.First();
            IEnumerable <string> shift_prod = __conflictProds.Count() == 1 ? new [] { __conflictProds.Single() }: __conflictProds.Skip(1).ToArray();

            precedenceMode prec = getPrec(mode);

            if (prec != precedenceMode.ReduceShift)
            {
                throw ParseControlException.NewAndRun("Only shift-reduce mode is supported with this syntax.");
            }

            Tuple <string, string>[] op_pairs = __opPairs.ToArray();
            var result = new List <Precedence>();

            for (int i = 0; i < op_pairs.Length; ++i)
            {
                string input_sym = op_pairs[i].Item2;

                var group = new List <Precedence>();

                {
                    // same vs same
                    // here we go as given associativity, because priority is the same (of course)
                    AssociativityEnum assoc = getAssoc(op_pairs[i].Item1);
                    group.Add(new ReduceShiftPrecedence(coords, assoc,
                                                        new[] { new PrecedenceWord(input_sym) },
                                                        PrecedenceWord.Create(reduce_prod, input_sym).Concat(shift_prod.Select(it => new PrecedenceWord(it))))
                    {
                        PriorityGroupEnd = false, PriorityGroupStart = false
                    });
                }

                if (i > 0)
                {
                    // higher priority means that if master is in input we shift, and when it is on stack we reduce
                    group.Add(new ReduceShiftPrecedence(coords, AssociativityEnum.Reduce,
                                                        op_pairs.Take(i).Select(it => new PrecedenceWord(it.Item2)),
                                                        PrecedenceWord.Create(reduce_prod, input_sym).Concat(shift_prod.Select(it => new PrecedenceWord(it))))
                    {
                        PriorityGroupEnd = false, PriorityGroupStart = false
                    });
                    group.Add(new ReduceShiftPrecedence(coords, AssociativityEnum.Shift,
                                                        new[] { new PrecedenceWord(input_sym) },
                                                        new PrecedenceWord(reduce_prod, op_pairs.Take(i).Select(it => it.Item2)).Concat(shift_prod.Select(it => new PrecedenceWord(it))))
                    {
                        PriorityGroupEnd = false, PriorityGroupStart = false
                    });
                }

                group.First().PriorityGroupStart = true;
                group.Last().PriorityGroupEnd    = true;

                result.AddRange(group);
            }

            return(result);
        }
Example #8
0
        private bool process()
        {
            Command <SYMBOL_ENUM, TREE_NODE> command = commands.First.Value;

            NfaCell <SYMBOL_ENUM, TREE_NODE> reduce_item = command.ReduceItem;

            commands.RemoveFirst();

            if (reduce_item == null) // shift
            {
                ITokenMatch <SYMBOL_ENUM> input_head = tokens.Head;

                addToStack(advanceInput: true,
                           symbol: input_head.Token,
                           userObject: new Option <object>(input_head.Value),
                           coordinates: input_head.Coordinates);
            }
            else
            {
                // here we have to use RhsSeenCount from state, not from production to use the same code as in parsers
                List <StackElement <SYMBOL_ENUM, TREE_NODE> > stack_tail = stack.RemoveLast(reduce_item.RhsSeenCount).ToList();

                bool           is_exact = true;
                SymbolPosition first_position;
                SymbolPosition last_position;
                {
                    SymbolCoordinates first_coords = stack_tail.Select(it => it.Coordinates).FirstOrDefault(it => it.IsExact);
                    if (first_coords != null)
                    {
                        first_position = first_coords.FirstPosition;
                    }
                    else
                    {
                        is_exact = false;

                        first_coords = stack.Select(it => it.Coordinates).LastOrDefault(it => it.IsExact);
                        if (first_coords != null)
                        {
                            first_position = first_coords.LastPosition;
                        }
                        else
                        {
                            first_position = initCoordinates.FirstPosition;
                        }
                    }
                }
                {
                    SymbolCoordinates last_coords = stack_tail.Select(it => it.Coordinates).LastOrDefault(it => it.IsExact);
                    if (last_coords != null)
                    {
                        last_position = last_coords.LastPosition;
                    }
                    else
                    {
                        last_position = tokens.Head.Coordinates.FirstPosition;
                    }
                }

                var coordinates = new SymbolCoordinates(is_exact, first_position, last_position);
                positionUpdate(coordinates);

                // no value for user object -- for 2 reasons:
                // * in case of exception we have to pass no value further
                // * if stack already contains no value we have to pass no value again
                var user_object = new Option <object>();

                // [@PARSER_USER_ACTION]
                // this is shortcut -- instead of passing function that returns nulls (when bulding parser)
                // we set user actions to null and here we can handle it
                if (reduce_item.ProductionUserAction == null)
                {
                    // return null as user object (it is a valid value)
                    user_object = new Option <object>(null);
                }
                else if (stack_tail.All(it => it.UserObject.HasValue))
                {
                    try
                    {
                        object value = reduce_item.ProductionUserAction.Code(stack_tail.Select(it => it.UserObject.Value).ToArray());
                        if (value is RichParseControl)
                        {
                            addWarningMessages(coordinates.FirstPosition.ToString(), (value as RichParseControl).Warnings);
                            user_object = new Option <object>((value as RichParseControl).Value);
                        }
                        else
                        {
                            user_object = new Option <object>(value);
                        }
                    }
                    catch (ParseControlException ex)
                    {
                        addErrorMessage(coordinates.FirstPosition.ToString() + ": " + ex.Message);
                        if (!ex.ContinueOnError)
                        {
                            return(false);
                        }
                    }
                    catch (Exception ex)
                    {
                        addErrorMessage("User action error in production : " + reduce_item.ProductionCoordinates + Environment.NewLine + ex.Message
                                        + Environment.NewLine + ex.ToString());
                        addErrorMessage(ex.StackTrace);
                        return(false);
                    }
                }

                addToStack(advanceInput: false,
                           symbol: reduce_item.LhsSymbol,
                           userObject: user_object,
                           coordinates: coordinates);
            }

            return(true);
        }
Example #9
0
        private void addToStack(bool advanceInput, SYMBOL_ENUM symbol, Option <object> userObject, SymbolCoordinates coordinates)
        {
            stack.Add(new StackElement <SYMBOL_ENUM, TREE_NODE>()
            {
                Symbol      = symbol,
                UserObject  = userObject,
                Coordinates = coordinates,
            });

            if (advanceInput)
            {
                ++tokens.Offset;
            }
        }