Example #1
0
        private static precedenceMode getPrec(string mode)
        {
            mode = mode.ToLower();

            precedenceMode prec;

            if (mode == "rs")
            {
                prec = Precedence.precedenceMode.ReduceShift;
            }
            else if (mode == "rr")
            {
                prec = Precedence.precedenceMode.ReduceReduce;
            }
            else if (mode == "op")
            {
                prec = Precedence.precedenceMode.Operator;
            }
            else
            {
                throw ParseControlException.NewAndRun("Not recognized precedence mode " + mode);
            }

            return(prec);
        }
Example #2
0
        private static AssociativityEnum getAssoc(string associativity)
        {
            associativity = associativity.ToLower();
            AssociativityEnum assoc;

            if (associativity == "none")
            {
                assoc = AssociativityEnum.None;
            }
            else if (associativity == "left")
            {
                assoc = AssociativityEnum.Left;
            }
            else if (associativity == "right")
            {
                assoc = AssociativityEnum.Right;
            }
            else if (associativity == "try")
            {
                assoc = AssociativityEnum.Try;
            }
            else if (associativity == "shift")
            {
                assoc = AssociativityEnum.Shift;
            }
            else if (associativity == "reduce")
            {
                assoc = AssociativityEnum.Reduce;
            }
            else
            {
                throw ParseControlException.NewAndRun("Not recognized precedence associativity " + associativity);
            }
            return(assoc);
        }
Example #3
0
        public AltRule(SymbolPosition pos, string markWith, IEnumerable <RhsGroup> groups, CodeMix gen)
        {
            this.Position = pos;
            this.MarkWith = markWith;

            // [@PARSER_USER_ACTION]
            // here we swap the notion of user action
            // if in grammar user didn't pass ANY code -- it means identity function
            // if the grammar user pass empty code -- it means passing null value, so as shorcut set null as entire user action
            if (gen == null) // if there was no code at all, we infer the end object
            {
                CodeMix mix = null;
                if (inferEndObject(groups, ref mix))
                {
                    this.Code = mix;
                }
                else
                {
                    throw ParseControlException.NewAndRun("Couldn't infer which object to pass at " + pos.XYString());
                }
            }
            // if there was an empty code, such code does not produce anything (i.e. null)
            // thus we set entire action as null -- it is a shortcut
            else if (gen.IsEmpty)
            {
                this.Code = null;
            }
            else
            {
                this.Code = gen;
            }

            SetGroups(groups);
        }
Example #4
0
        private RhsGroup(SymbolPosition position, string name, IEnumerable <IRhsEntity> chunks, RepetitionEnum repetition, ModeEnum mode)
        {
            this.Position = position;
            this.ObjName  = name;

            if (chunks.Count() == 1 && chunks.Single().IsGroup() && chunks.Single().AsGroup().Repetition == RepetitionEnum.Once)
            {
                // there is only one chunk, so each symbol is really a chunk -- recreate the list
                this.elements = chunks.Single().AsGroup().Elements.ToArray();
            }
            else
            {
                this.elements = chunks.ToArray();
            }

            this.Repetition = repetition;
            this.Mode       = mode;


            string err = findError(this.ObjName, this.Elements, this.Repetition, this.Mode);

            if (err != null)
            {
                throw ParseControlException.NewAndRun(err);
            }
        }
        private void createPrecedences()
        {
            var errors = new List <string>();

            foreach (Precedence prec in grammar.ParserPrecedences)
            {
                if (prec.PriorityGroupStart)
                {
                    precedenceTable.StartPriorityGroup();
                }

                try
                {
                    if (prec is OperatorPrecedence)
                    {
                        precedenceTable.AddOperator(prec.Associativity, (prec as OperatorPrecedence).UsedTokens.Select(it => it.GetSymbolId(grammar)).ToArray());
                    }
                    else if (prec is ReduceShiftPrecedence)
                    {
                        ReduceShiftPrecedence rs_prec = prec as ReduceShiftPrecedence;
                        foreach (PrecedenceWord input in rs_prec.InputSet)
                        {
                            precedenceTable.AddReduceShiftPattern(prec.Associativity,
                                                                  input.GetSymbolId(grammar),
                                                                  rs_prec.ReduceSymbol.GetSymbolId(grammar),
                                                                  rs_prec.ReduceSymbol.StackSymbols.Select(it => grammar.GetSymbolId(it)),       // reduce stack operators
                                                                  rs_prec.ShiftSymbols.First().GetSymbolId(grammar),
                                                                  rs_prec.ShiftSymbols.Skip(1).Select(it => it.GetSymbolId(grammar)).ToArray()); // rest of shift symbols
                        }
                    }
                    else if (prec is ReduceReducePrecedence)
                    {
                        ReduceReducePrecedence rr_prec = prec as ReduceReducePrecedence;
                        foreach (PrecedenceWord input in rr_prec.InputSet)
                        {
                            precedenceTable.AddReduceReducePattern(prec.Associativity,
                                                                   input.GetSymbolId(grammar),
                                                                   rr_prec.ReduceSymbols.First().GetSymbolId(grammar),
                                                                   rr_prec.ReduceSymbols.Skip(1).Select(it => it.GetSymbolId(grammar)).ToArray());
                        }
                    }
                    else
                    {
                        throw new Exception("Unrecognized precedence");
                    }
                }
                catch (Exception ex)
                {
                    errors.Add(ex.Message + " " + prec.Coords.FirstPosition.XYString() + ".");
                }

                if (prec.PriorityGroupEnd)
                {
                    precedenceTable.EndPriorityGroup();
                }
            }

            ParseControlException.ThrowAndRun(errors);
        }
Example #6
0
        private void createImplicitNames()
        {
            if (Code == null)
            {
                return;
            }

            // we have to check the source of the symbol
            // named group cannot have named symbols inside
            HashSet <RhsSymbol> symbols_named_groups = new HashSet <RhsSymbol>(
                rhsGroups
                .Where(it => it.ObjName != null)
                .Select(it => it.GetSymbols()).Flatten()
                );

            // symbols which can have implicit obj name
            Dictionary <string, RhsSymbol> implicit_symbols
                = rhsGroups.Select(it => it.GetSymbols()).Flatten()
                  .GroupBy(it => it.SymbolName)
                  .Where(it => it.Count() == 1 && it.Single().ObjName == null && !symbols_named_groups.Contains(it.Single()))
                  .ToDictionary(it => it.Key, it => it.Single());

            var errors = new List <string>();


            foreach (string placeholder in Code.GetPlaceholders().ToHashSet())
            {
                RhsSymbol symbol;
                CodeBody  code;
                if (standardMacros.TryGetValue(placeholder, out code))
                {
                    Code.ConvertPlaceholderToCode(placeholder, code);
                }

                if (!implicit_symbols.TryGetValue(placeholder, out symbol))
                {
                    if (code == null)
                    {
                        errors.Add("Cannot bind placeholder \"" + placeholder + "\" to any symbol" + " in: " + groupsToString() + ".");
                    }
                }
                else if (code != null)
                {
                    errors.Add("Ambiguous placeholder \"" + placeholder + "\" in: " + groupsToString() + ".");
                }
                else
                {
                    string var_name = Code.RegisterNewIdentifier(symbol.SymbolName);
                    Code.ConvertPlaceholderToCode(placeholder, new CodeBody().AddIdentifier(var_name));
                    symbol.SetImplicitUserObjName(var_name);
                }
            }


            if (errors.Any())
            {
                throw ParseControlException.NewAndRun(errors.Join(Environment.NewLine));
            }
        }
Example #7
0
        public LabeledSymbol(string userLabel, string symbolName)
        {
            this.ObjName      = userLabel;
            this.__symbolName = symbolName;

            if (ObjName != null && new Regex("^_+\\d+$").IsMatch(ObjName))
            {
                throw ParseControlException.NewAndRun("\"" + ObjName + "\" is reserved name");
            }
        }
Example #8
0
        private static void validate(IEnumerable <Tuple <int, int> > ranges)
        {
            IEnumerable <Tuple <int, int> > invalid = ranges.Where(it => it.Item1 > it.Item2).ToList();

            if (invalid.Any())
            {
                throw ParseControlException.NewAndRun("Min limit of character range cannot be bigger than max limit: "
                                                      + invalid.Select(it => (char)it.Item1 + "-" + (char)it.Item2).Join(","));
            }
        }
Example #9
0
        private LexPattern mergeLexPatterns(IEnumerable <ILexPattern> rawPatterns)
        {
            if (!rawPatterns.Any())
            {
                throw new ArgumentException("Internal error");
            }

            if (rawPatterns.WhereType <LexPattern>().Any(it => it.Type == LexPattern.TypeEnum.EofAction))
            {
                if (rawPatterns.Count() != 1)
                {
                    throw new ArgumentException("Internal error");
                }
                else
                {
                    return(rawPatterns.WhereType <LexPattern>().Single());
                }
            }

            IEnumerable <string> unknowns = rawPatterns
                                            .WhereType <LexPatternName>()
                                            .Select(it => it.Name)
                                            .Where(it => !lexerPatternNames.ContainsKey(it))
                                            .ToArray();

            if (unknowns.Any())
            {
                ParseControlException.ThrowAndRun(new[] { "Unknown pattern name(s): " + unknowns.Join(", ") + "." });
            }

            IEnumerable <LexPattern> patterns = rawPatterns.Select(it =>
            {
                var name = it as LexPatternName;
                if (name == null)
                {
                    return(it as LexPattern);
                }
                else
                {
                    return(lexerPatternNames[name.Name]);
                }
            }).ToArray();

            LexPattern head = patterns.First();

            if (patterns.Any(it => head.Type != it.Type || head.StringComparison != it.StringComparison))
            {
                ParseControlException.ThrowAndRun(new[] { "Cannot mix pattern modes." });
            }

            return(LexPattern.Merge(head.Type, head.StringComparison, patterns));
        }
Example #10
0
        private Repetition(int min, int?max)
        {
            this.Min = min;
            this.Max = max;

            if (Max.HasValue && Max == 0)
            {
                throw ParseControlException.NewAndRun("Max repetition cannot be zero.");
            }
            if (Max.HasValue && Max < Min)
            {
                throw ParseControlException.NewAndRun("Max repetition less than min repetition.");
            }
        }
Example #11
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 #12
0
        public string Make(Dictionary<string, string> placeholderMapping, bool encloseStatements = true)
        {
            foreach (string s in placeholders)
                if (!placeholderMapping.ContainsKey(s))
                    throw ParseControlException.NewAndRun("Placeholder \"" + s + "\" not mapped.");

            var builder = new StringBuilder();
            foreach (CodePiece piece in pieces)
                if (piece.Type == CodePiece.TypeEnum.Placeholder)
                    builder.Append(placeholderMapping[piece.Content]);
                else
                    builder.Append(piece.Content);

            string result = builder.ToString().Trim();

            if (HasStatement && encloseStatements)
                return "{" + result + "}";
            else
                return result;
        }
Example #13
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 #14
0
        public AltRegex GetRegex(string strRegex)
        {
            IEnumerable <ITokenMatch <SymbolEnum> > tokens = lexer.ScanText(strRegex);
            ITokenMatch <SymbolEnum> err_token             = tokens.FirstOrDefault(it => it.Token == SymbolEnum.Error);

            if (err_token != null)
            {
                throw ParseControlException.NewAndRun("Invalid regex input " + (err_token.ErrorMessage != null?"(" + err_token.ErrorMessage + ")":"")
                                                      + ": " + strRegex.EscapedString());
            }

            var regex = parser.Parse(tokens, new ParserOptions()).FirstOrDefault() as AltRegex;

            if (regex == null)
            {
                throw ParseControlException.NewAndRun("Invalid regex syntax: " + strRegex.EscapedString());
            }

            return(regex);
        }
Example #15
0
        private void validate()
        {
            Dictionary <string, int> name_counts = RhsGroups.Select(gr => gr.ObjName)
                                                   .Concat(RhsGroups.Select(gr => gr.GetSymbols().Select(sym => sym.ObjName)).Flatten())
                                                   .Where(it => it != null)
                                                   .GroupBy(it => it)
                                                   .ToDictionary(it => it.Key, it => it.Count());

            if (name_counts.Any(it => it.Value > 1))
            {
                throw ParseControlException.NewAndRun("Duplicated name");
            }

            if (Code != null)
            {
                HashSet <string> named_symbols = new HashSet <string>(objNameCollector(RhsGroups)
                                                                      .Where(it => it != null)
                                                                      );

                foreach (string control_var in Code.GetMacroControlVariables())
                {
                    if (!named_symbols.Contains(control_var))
                    {
                        var symbols = new HashSet <string>(rhsGroups
                                                           .Select(it => it.GetSymbols()).Flatten()
                                                           .Select(it => it.SymbolName));

                        var message = "Control name \"" + control_var + "\" is not defined";
                        if (symbols.Contains(control_var))
                        {
                            throw ParseControlException.NewAndRun(message + " -- did you mean \"" + CodePiece.PlaceholderSigil + control_var + "\"?");
                        }
                        else
                        {
                            throw ParseControlException.NewAndRun(message + " (currently: " + named_symbols.Join(",") + ")");
                        }
                    }
                }
            }
        }
Example #16
0
        public void ConvertPlaceholderToCode(string placeholder, CodeBody varName)
        {
            if (getControlPlaceholder() == placeholder)
            {
                if (varName.Pieces.Count() == 1)
                {
                    ControlName = varName.Pieces.Single();
                }
                else
                {
                    // the reason for this is we don't handle compound variable/expressions like "foo.field.bar"
                    // and the reason for the reason is, such compound expression can come only from standard placeholders
                    // like $pos or $coords, and it does not make sense to check them if they exist or if they are null or not
                    throw ParseControlException.NewAndRun("Placeholder \"" + placeholder + "\" cannot be used as control variable in macro.");
                }
            }

            varBody.ConvertPlaceholderToCode(placeholder, varName);
            foreach (CodeMix mix in altCodes)
            {
                mix.ConvertPlaceholderToCode(placeholder, varName);
            }
        }
Example #17
0
        internal LexPattern SetStringComparison(StringCaseComparison stringComparison)
        {
            if (this.stringComparison.HasValue)
            {
                throw new ArgumentException();
            }

            this.stringComparison = stringComparison;

            if (Type == TypeEnum.Regex)
            {
                try
                {
                    Rule.FormatAsRegex(pattern.AsInternalRegex(), stringComparison);
                }
                catch (ArgumentException ex)
                {
                    throw ParseControlException.NewAndRun(ex.Message);
                }
            }

            return(this);
        }
Example #18
0
        internal GrammarOptions(params Tuple <string, bool>[] options)
        {
            UseMRE = true;

            var unknown = new List <string>();

            foreach (Tuple <string, bool> opt in options)
            {
                if (opt.Item1 == "mre")
                {
                    UseMRE = opt.Item2;
                }
                else
                {
                    unknown.Add(opt.Item1);
                }
            }

            if (unknown.Any())
            {
                throw ParseControlException.NewAndRun("Unknown option(s): " + unknown.Join(","));
            }
        }
Example #19
0
        internal Grammar(IEnumerable <Tuple <GrammarElementEnum, object> > elements,
                         IEnumerable <LexItem> implicitLexerRules,
                         List <string> warnings)
        {
            var throw_errors = new List <string>();

            {
                Dictionary <GrammarElementEnum, int> elem_counts = EnumExtensions.GetValues <GrammarElementEnum>().ToDictionary(it => it, it => 0);
                foreach (Tuple <GrammarElementEnum, object> elem in elements)
                {
                    if (elem.Item2 != null)
                    {
                        ++elem_counts[elem.Item1];
                    }
                }

                var optionals = new HashSet <GrammarElementEnum>(new GrammarElementEnum[] {
                    GrammarElementEnum.Types,
                    GrammarElementEnum.Terminals,
                    GrammarElementEnum.Options,
                    GrammarElementEnum.Prededence,
                    GrammarElementEnum.LexerTypeInfo,
                    GrammarElementEnum.ExplicitLexerRules,
                    GrammarElementEnum.LexerStates,
                    GrammarElementEnum.ParserTypeInfo,
                    GrammarElementEnum.ParserRules,
                    GrammarElementEnum.PatternsInfo,
                    GrammarElementEnum.Using
                });

                foreach (KeyValuePair <GrammarElementEnum, int> count in elem_counts.Where(it => it.Value != 1))
                {
                    if (count.Value > 1)
                    {
                        throw ParseControlException.NewAndRun(count.Key.ToString() + " section is duplicated");
                    }
                    // if not optional section
                    else if (!optionals.Contains(count.Key))
                    {
                        throw ParseControlException.NewAndRun(count.Key.ToString() + " section is missing");
                    }
                }


                {
                    // if we have lexer name section, then we have to have lexer rules as well
                    // in reverse -- if we don't have the first, we cannot have the latter one and lexer states section
                    // so it is not symmetric!
                    var lexer_count = elem_counts[GrammarElementEnum.LexerTypeInfo];
                    if (elem_counts[GrammarElementEnum.LexerStates] > lexer_count ||
                        elem_counts[GrammarElementEnum.ExplicitLexerRules] != lexer_count)
                    {
                        throw ParseControlException.NewAndRun("Lexer definition is given only partially: lexer name section "
                                                              + (lexer_count > 0 ? "exists" : "does not exist") + " while lexer states section "
                                                              + (elem_counts[GrammarElementEnum.LexerStates] > 0 ? "exists" : "does not exist") + " and lexer rules section "
                                                              + (elem_counts[GrammarElementEnum.ExplicitLexerRules] > 0 ? "exists" : "does not exist") + ".");
                    }
                }

                if (elem_counts[GrammarElementEnum.ParserRules] != elem_counts[GrammarElementEnum.ParserTypeInfo])
                {
                    throw ParseControlException.NewAndRun("Parser definition is given only partially");
                }
            }

            Dictionary <GrammarElementEnum, object> dict_elements = EnumExtensions.GetValues <GrammarElementEnum>()
                                                                    .ToDictionary(it => it, it => (object)null);

            foreach (Tuple <GrammarElementEnum, object> elem in elements)
            {
                dict_elements[elem.Item1] = elem.Item2;
            }

            this.usingList        = (((IEnumerable <string>)dict_elements[GrammarElementEnum.Using]) ?? new string[] { }).ToList();
            this.types            = (((IEnumerable <SymbolInfo>)dict_elements[GrammarElementEnum.Types]) ?? new SymbolInfo[] { }).ToDictionary(it => it.SymbolName, it => it.TypeName);
            this.guessed_types    = new Dictionary <string, string>();
            this.NamespaceName    = ((string)dict_elements[GrammarElementEnum.Namespace]);
            this.TokenTypeInfo    = ((TokenInfo)dict_elements[GrammarElementEnum.TokenName]);
            this.PatternsTypeInfo = ((PatternsInfo)dict_elements[GrammarElementEnum.PatternsInfo]) ?? new PatternsInfo(null, null);

            this.LexerTypeInfo = ((FactoryTypeInfo)dict_elements[GrammarElementEnum.LexerTypeInfo]);
            this.Options       = ((GrammarOptions)dict_elements[GrammarElementEnum.Options]) ?? new GrammarOptions();
            this.LexerStates   = ((StatesInfo)dict_elements[GrammarElementEnum.LexerStates]) ?? StatesInfo.CreateDefault();
            // implicit rules first, because lexer matches text in longest-first fashion
            // when user explicitly adds something like <anything> rule with reversed concat order
            // implicit rules will never be matched
            this.lexerRules = implicitLexerRules.Concat((((IEnumerable <IScanningRule>)dict_elements[GrammarElementEnum.ExplicitLexerRules]) ?? new LexItem[] { })
                                                        .Select(it => it as LexItem).Where(it => it != null)).ToList();
            {
                IEnumerable <LexPatternVariable> pattern_vars = (((IEnumerable <IScanningRule>)dict_elements[GrammarElementEnum.ExplicitLexerRules]) ?? new LexPatternVariable[] { })
                                                                .Select(it => it as LexPatternVariable).Where(it => it != null).ToArray();
                this.LexerPatternFields = pattern_vars.Where(it => it.WithField).ToArray();
                this.lexerPatternNames  = pattern_vars.ToDictionary(it => it.Name, it => it.Pattern);
            }

            this.lexerRules.ForEach(it => it.OutputPattern = mergeLexPatterns(it.InputPatterns));

            this.ParserTypeInfo    = ((FactoryTypeInfo)dict_elements[GrammarElementEnum.ParserTypeInfo]);
            this.parserPrecedences = (((IEnumerable <Precedence>)dict_elements[GrammarElementEnum.Prededence]) ?? Enumerable.Empty <Precedence>()).ToList();

            this.terminalRegistry = new OrderedSet <string>(
                (new[] { EOFSymbol })
                .Concat((((IEnumerable <string>)dict_elements[GrammarElementEnum.Terminals]) ?? new string[] { }))
                .Concat(
                    lexerRules.Select(lex_it => lex_it.Context.Concat(lex_it.TerminalName)).Flatten()
                    // error symbol can appear in lexer productions, it is not a terminal though
                    .Where(s => s != null && s != Grammar.ErrorSymbol)));

            this.parserProductions = new List <Production>();
            AddProductions(((IEnumerable <Production>)dict_elements[GrammarElementEnum.ParserRules]) ?? new Production[] { });

            this.symbolRegistry = new OrderedSet <string>(
                (new[] { ErrorSymbol })
                .Concat(terminalRegistry) // EOF starts that set
                .Concat(nonTerminalRegistry)
                .Concat(ParserProductions
                        .Select(prod => prod.RhsAlternatives
                                .Select(alt => alt.RhsGroups
                                        .Select(grp => grp.GetSymbols().Select(s => s.SymbolName))
                                        .Flatten())
                                .Flatten())
                        .Flatten()));

            // here we get partial mapping (useful for lexer, which sees only part of all symbols)
            InitSymbolMapping();

            if (!IsParserBuilt)
            {
                var errors = new List <string>();
                if (dict_elements[GrammarElementEnum.Types] != null)
                {
                    errors.Add("types");
                }

                if (dict_elements[GrammarElementEnum.Prededence] != null)
                {
                    errors.Add("precedence");
                }

                if (dict_elements[GrammarElementEnum.ParserRules] != null)
                {
                    errors.Add("parser productions");
                }

                if (errors.Any())
                {
                    throw ParseControlException.NewAndRun("Parser is not built (no parser name is given); " + errors.Join(", ") + " section(s) are meaningless.");
                }
            }

            {
                IEnumerable <string> undef_symbols = new HashSet <string>(types.Select(it => it.Key).Where(it => !symbolRegistry.Contains(it)));

                if (undef_symbols.Any())
                {
                    warnings.Add("Undefined symbol(s) in types section: " + String.Join(", ", undef_symbols));
                }
            }

            if (IsParserBuilt)
            {
                var rhs_symbol_names = new HashSet <string>(ParserProductions.Select(it => it.RhsAlternatives).Flatten()
                                                            .Select(it => it.RhsGroups).Flatten()
                                                            .Select(it => it.GetSymbols()).Flatten()
                                                            .Select(it => it.SymbolName));

                IEnumerable <string> unused_terminals = terminalRegistry.Where(it => it != Grammar.EOFSymbol && !rhs_symbol_names.Contains(it)).ToList();

                if (unused_terminals.Any())
                {
                    warnings.Add("Unused terminal(s) in parsing section: " + String.Join(", ", unused_terminals));
                }
            }

            ParseControlException.ThrowAndRun(throw_errors);
        }
Example #20
0
        internal void AddProductions(IEnumerable <Production> productions)
        {
            foreach (SymbolInfo sym_info in productions.Select(it => it.LhsSymbol).Where(it => it.TypeName != null))
            {
                {
                    string typename;
                    if (!this.types.TryGetValue(sym_info.SymbolName, out typename))
                    {
                        setTypeNameOfSymbol(sym_info.SymbolName, sym_info.TypeName);
                    }
                    else if (typename != sym_info.TypeName)
                    {
                        throw ParseControlException.NewAndRun(sym_info.SymbolName + " defined as " + sym_info.TypeName + " has already type " + typename);
                    }
                }
            }

            foreach (Production prod in productions)
            {
                foreach (AltRule alt in prod.RhsAlternatives.Where(it => it.Code != null))
                {
                    string guess = alt.Code.BuildBody(presentVariables: null).GuessTypeName();

                    string typename;
                    if (!this.guessed_types.TryGetValue(prod.LhsSymbol.SymbolName, out typename))
                    {
                        // it can be null, meaning it was not recognized
                        this.guessed_types.Add(prod.LhsSymbol.SymbolName, guess);
                    }
                    // if there is a conflict with guessing set it is as not recognized
                    else if (typename != guess)
                    {
                        this.guessed_types[prod.LhsSymbol.SymbolName] = null;
                    }
                }
            }

            parserProductions.AddRange(productions);

            this.nonTerminalRegistry = new HashSet <string>(ParserProductions.Select(prod => prod.LhsSymbol.SymbolName));

            var unknown       = new HashSet <string>();
            var lhs_terminals = new List <string>();

            foreach (Production prod in productions)
            {
                foreach (AltRule alt in prod.RhsAlternatives)
                {
                    foreach (IEnumerable <RhsSymbol> symbols in alt.RhsGroups.Select(it => it.GetSymbols()))
                    {
                        unknown.AddRange(symbols
                                         .Where(sym => !terminalRegistry.Contains(sym.SymbolName) &&
                                                !nonTerminalRegistry.Contains(sym.SymbolName) &&
                                                !types.ContainsKey(sym.SymbolName) &&
                                                sym.SymbolName != ErrorSymbol)
                                         .Select(it => it.Coords.XYString() + " " + it.SymbolName));
                    }
                }

                if (terminalRegistry.Contains(prod.LhsSymbol.SymbolName))
                {
                    lhs_terminals.Add(prod.LhsSymbol.SymbolName);
                }
            }

            var errors = new List <string>();

            if (lhs_terminals.Any())
            {
                errors.Add("Terminal(s) " + lhs_terminals.Join(",") + " cannot be used at LHS of the production");
            }
            if (unknown.Any())
            {
                errors.Add("Undefined symbol(s): " + String.Join(",", unknown));
            }

            ParseControlException.ThrowAndRun(errors);
        }
Example #21
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);
        }