protected SourceElement ParseSource()
        {
            List <Selection <DefinitionElement, GeneratorLexElement> > var1 = new List <Selection <DefinitionElement, GeneratorLexElement> >();

            for (Optional <GeneratorLexElement> var2 = _Reader.Peek(); var2.HasValue && (var2.Value.Type == GeneratorLexType.Comment || var2.Value.Type == GeneratorLexType.Nonterminal); var2 = _Reader.Peek())
            {
                Selection <DefinitionElement, GeneratorLexElement> var3 = default(Selection <DefinitionElement, GeneratorLexElement>);
                GeneratorLexElement var4 = _Reader.PeekOrThrow("source", GeneratorLexType.Nonterminal, GeneratorLexType.Comment);
                if (var4.Type == GeneratorLexType.Nonterminal)
                {
                    DefinitionElement var5 = this.ParseDefinition();
                    Selection <DefinitionElement, GeneratorLexElement> var6 = new Selection <DefinitionElement, GeneratorLexElement>(var5);
                    var3 = var6;
                }
                else if (var4.Type == GeneratorLexType.Comment)
                {
                    GeneratorLexElement var7 = _Reader.ReadOrThrow("source", GeneratorLexType.Comment);
                    Selection <DefinitionElement, GeneratorLexElement> var8 = new Selection <DefinitionElement, GeneratorLexElement>(var7);
                    var3 = var8;
                }
                else
                {
                    throw _Reader.Error("source", GeneratorLexType.Nonterminal, GeneratorLexType.Comment);
                }
                var1.Add(var3);
            }
            Selection <DefinitionElement, GeneratorLexElement>[] var9;
            var9 = var1.ToArray();
            return(this.ReturnSource(var9));
        }
Пример #2
0
        /// <summary>
        /// definition = 'nonterminal', "=", expressions, ";" ;
        /// </summary>
        /// <param name="nonterminal">'nonterminal'</param>
        /// <param name="equal">"="</param>
        /// <param name="expressions">expressions</param>
        /// <param name="semicolon">";"</param>
        protected override DefinitionElement ReturnDefinition(GeneratorLexElement nonterminal, GeneratorLexElement equal, ExpressionsElement expressions, GeneratorLexElement semicolon)
        {
            DefinitionElement ret = new DefinitionElement(nonterminal, expressions);

            ret.Expression.setRootDefinition(ret);
            return(ret);
        }
 internal void setRootDefinition(DefinitionElement definition)
 {
     _rootDefinition = definition;
     foreach (DefinitionContent child in this.EnumerateChildren())
     {
         child.setRootDefinition(definition);
     }
 }
        void firstFollowing(ScriptParserGenerator gen, DefinitionElement root, TextWriter writer, DefinitionContent content)
        {
            writer.WriteLine(string.Format("   {0}: first:<{1}> following:<{2}>", content, joinStr(content.GetFirstTerminals(gen)), joinStr(content.GetFollowingTerminals(gen))));
            SelectionElement s = content as SelectionElement;

            if (s != null)
            {
                foreach (ElementsElement elems in s.Candidates)
                {
                    firstFollowing(gen, root, writer, elems);
                }
            }
            ExpressionsElement ex = content as ExpressionsElement;

            if (ex != null)
            {
                foreach (ElementsElement elems in ex.Selection.Candidates)
                {
                    firstFollowing(gen, root, writer, elems);
                }
            }
            ElementsElement es = content as ElementsElement;

            if (es != null)
            {
                foreach (ElementElement elem in es.Elements)
                {
                    firstFollowing(gen, root, writer, elem);
                }
            }
            RepeatElement r = content as RepeatElement;

            if (r != null)
            {
                firstFollowing(gen, root, writer, r.InnerExpression);
            }
            OptionElement o = content as OptionElement;

            if (o != null)
            {
                firstFollowing(gen, root, writer, o.InnerExpression);
            }
            GroupElement g = content as GroupElement;

            if (g != null)
            {
                firstFollowing(gen, root, writer, g.InnerExpression);
            }
            LiteralElement l = content as LiteralElement;
        }
        /// <summary>
        /// この要素の先頭にくる可能性のある終端記号群を返します.
        /// </summary>
        /// <param name="generator"></param>
        /// <returns></returns>
        public IList <string> GetFirstTerminals(ScriptParserGenerator generator)
        {
            if (_firstTerminals != null)
            {
                return(new ReadOnlyCollection <string>(_firstTerminals));
            }
            HashSet <string> ret                  = new HashSet <string>();
            HashSet <string> dependencies         = new HashSet <string>();
            Queue <string>   dependencyCandidates = new Queue <string>();

            string[] subDeps;
            foreach (string first in this.GetFirstTerminalsOfSelf(out subDeps))
            {
                ret.Add(first);
            }
            foreach (string dep in subDeps)
            {
                dependencyCandidates.Enqueue(dep);
            }
            while (dependencyCandidates.Count > 0)
            {
                string dep = dependencyCandidates.Dequeue();
                if (dependencies.Contains(dep))
                {
                    continue;
                }
                dependencies.Add(dep);
                DefinitionElement depDef = generator.LookUpDefinition(dep);
                IList <string>    firsts = depDef.GetFirstTerminalsOfSelf(out subDeps);
                foreach (string subDep in subDeps)
                {
                    dependencyCandidates.Enqueue(subDep);
                }
                foreach (string first in firsts)
                {
                    ret.Add(first);
                }
            }
            if (ret.Contains(null))
            {
                ret.RemoveWhere(r => r == null);
                ret.Add(null);
            }
            _firstTerminals = ret.ToArray();
            return(new ReadOnlyCollection <string>(_firstTerminals));
        }
Пример #6
0
        /// <summary>
        /// この定義に後続する終端記号を返します.
        /// </summary>
        /// <param name="generator"></param>
        /// <returns></returns>
        public IList <string> GetFollowingTerminals(ScriptParserGenerator generator)
        {
            generator.InitializeFollowingTerminals();
            if (_followingTerminals != null)
            {
                return(new ReadOnlyCollection <string>(_followingTerminals));
            }
            List <string> ret = new List <string>(_followingTerminalsOfSelf.Where(f => f != null));

            // 循環対策のために一時的に入れておく
            _followingTerminals = ret.ToArray();
            foreach (string dependency in _followingDependencies)
            {
                DefinitionElement def = generator.LookUpDefinition(dependency);
                ret.AddRange(def.GetFollowingTerminals(generator));
            }
            _followingTerminals = ret.Distinct().ToArray();
            return(new ReadOnlyCollection <string>(_followingTerminals));
        }
Пример #7
0
        protected override void SetupFollowingTerminalsOfSelf(ScriptParserGenerator generator, string[] followings)
        {
            switch (_literal.Type)
            {
            case GeneratorLexType.Terminal:
                break;

            case GeneratorLexType.Nonterminal:
                DefinitionElement def = generator.LookUpDefinition(this.InnerWord);
                def.AddFollowingTerminals(followings);
                if (followings.Contains(null))
                {
                    def.AddNonterminalContainingThisAtTail(this.RootDefinition.DefinitionName);
                }
                break;

            default:
                throw new NotSupportedException();
            }
        }
        public static void writeParseCodeAux(TextWriter writer, ScriptParserGenerator generator, IList <SelectionSubCandidate> subCandidates, Action <SelectionSubCandidate, TextWriter, ScriptParserGenerator> returnCodeGenerate)
        {
            Debug.Assert(subCandidates.Count >= 1);
            DefinitionElement rootDefinition = subCandidates.First().RootElement;

            // 先頭のDefinitionContentが同じである選択候補の集合
            Dictionary <DefinitionContent, List <SelectionSubCandidate> > sameHeadCandidates = new Dictionary <DefinitionContent, List <SelectionSubCandidate> >(new DefinitionContentComparer());
            // 優先順位を保つために順番を覚えておく
            List <DefinitionContent> headOrder = new List <DefinitionContent>();
            // 後続の要素がない選択候補の集合
            List <SelectionSubCandidate> noElementCandidates = new List <SelectionSubCandidate>();

            // 選択候補を先頭の要素ごとに振り分け
            foreach (SelectionSubCandidate sub in subCandidates)
            {
                List <SelectionSubCandidate> list;
                if (sub.IsEmpty)
                {
                    noElementCandidates.Add(sub);
                }
                else
                {
                    if (!sameHeadCandidates.TryGetValue(sub.Head, out list))
                    {
                        sameHeadCandidates[sub.Head] = list = new List <SelectionSubCandidate>();
                        headOrder.Add(sub.Head);
                    }
                    list.Add(sub);
                }
            }
            Dictionary <string, string> usedFirsts = new Dictionary <string, string>();
            Dictionary <DefinitionContent, string[]> firstTerminals = new Dictionary <DefinitionContent, string[]>();

            foreach (DefinitionContent head in headOrder)
            {
                // 先頭が同じ候補の集合
                List <SelectionSubCandidate> list;
                bool getListFromHeadSucceeded = sameHeadCandidates.TryGetValue(head, out list);
                Debug.Assert(getListFromHeadSucceeded);
                // 現在の先頭要素の中での頭にくる可能性のある終端記号
                HashSet <string> firstsAtThisHead = new HashSet <string>();
                foreach (SelectionSubCandidate sub in list)
                {
                    IList <string> firsts = sub.GetFirstTerminals(generator);
                    foreach (string first in firsts)
                    {
                        // もう追加した場合はスルー
                        if (firstsAtThisHead.Contains(first))
                        {
                            continue;
                        }
                        firstsAtThisHead.Add(first);
                        // 他の先頭のときに使っている終端記号が頭にくる可能性がある場合は警告
                        string usingPoint;
                        if (usedFirsts.TryGetValue(first, out usingPoint))
                        {
                            string context = string.Format("'{0}' の定義", rootDefinition.DefinitionName);
                            string message = string.Format("<{1}> 内の <{0}> は <{2}> によって隠されます", first, sub.OriginalElements.ToString(), usingPoint);
                            generator.Warn(context, message);
                        }
                        else
                        {
                            usedFirsts[first] = sub.OriginalElements.ToString();
                        }
                    }
                }
                firstTerminals[head] = firstsAtThisHead.ToArray();
            }
            bool isSingleCandidate = sameHeadCandidates.Count == 1 && noElementCandidates.Count == 0;

            if (isSingleCandidate)
            {
                List <SelectionSubCandidate> list             = sameHeadCandidates.Values.First();
                string[]                     firstsAtThisHead = firstTerminals.Values.First();
                DefinitionContent            head             = list.First().Head;
                string                       headVar          = head.WriteParseCode(writer, generator);
                List <SelectionSubCandidate> next             = new List <SelectionSubCandidate>();
                foreach (SelectionSubCandidate sub in list)
                {
                    next.Add(sub.NextElement(headVar));
                }
                writeParseCodeAux(writer, generator, next, returnCodeGenerate);
                return;
            }
            bool needsBlockAtEmpty = headOrder.Count >= 1;
            bool usePeekOrThrow    = noElementCandidates.Count == 0;

            // 後続の要素があるものは再帰的に処理
            if (headOrder.Count >= 1)
            {
                string peek;
                if (usePeekOrThrow)
                {
                    IList <string> validTerminals = firstTerminals.Values.SelectMany(terminals => terminals).Distinct().ToList();
                    writer.WriteLine(generator.GetCodeOfPeekOrThrow(rootDefinition.DefinitionName, validTerminals, out peek));
                }
                else
                {
                    // 後続の要素がない場合もあるのでPeekOrThrowではなくPeek
                    writer.WriteLine(generator.GetCodeOfPeek(out peek));
                }
                // 順番通りに
                foreach (DefinitionContent head in headOrder)
                {
                    // 先頭が同じ候補の集合
                    List <SelectionSubCandidate> list;
                    bool getListFromHeadSucceeded = sameHeadCandidates.TryGetValue(head, out list);
                    Debug.Assert(getListFromHeadSucceeded);
                    // 現在の先頭要素の中での頭にくる可能性のある終端記号
                    string[] firstsAtThisHead;
                    bool     getFirstsFromHeadSucceeded = firstTerminals.TryGetValue(head, out firstsAtThisHead);
                    Debug.Assert(getFirstsFromHeadSucceeded);
                    // 頭の終端記号が対象のであるか
                    if (usePeekOrThrow)
                    {
                        writer.WriteLine(generator.GetCodeOfIfLexisIn(peek, firstsAtThisHead));
                    }
                    else
                    {
                        writer.WriteLine(generator.GetCodeOfIfOptionalLexisIn(peek, firstsAtThisHead));
                    }
                    // 先頭の要素をパース
                    string headVar = head.WriteParseCode(writer, generator);
                    // 後続を再帰的に処理
                    List <SelectionSubCandidate> next = new List <SelectionSubCandidate>();
                    foreach (SelectionSubCandidate sub in list)
                    {
                        next.Add(sub.NextElement(headVar));
                    }
                    writeParseCodeAux(writer, generator, next, returnCodeGenerate);
                    writer.Write(generator.GetCodeOfCloseBlock());
                    writer.Write(generator.GetCodeOfSingleElse());
                }
            }
            // 同じ内容なのが二つあった時は警告を出す
            if (noElementCandidates.Count >= 2)
            {
                SelectionSubCandidate oneOfCandidate = noElementCandidates.First();
                foreach (SelectionSubCandidate emptyElse in noElementCandidates.Skip(1))
                {
                    string context = string.Format("'{0}' の定義", rootDefinition.DefinitionName);
                    string message = string.Format("<{0}> は <{1}> によって隠されます", emptyElse.OriginalElements.ToString(), oneOfCandidate.OriginalElements.ToString());
                    generator.Warn(context, message);
                }
            }
            if (needsBlockAtEmpty)
            {
                writer.WriteLine(generator.GetCodeOfOpenBlock());
            }
            if (noElementCandidates.Count >= 1)
            {
                SelectionSubCandidate elements = noElementCandidates.First();
                returnCodeGenerate(elements, writer, generator);
            }
            else
            {
                IList <string> availableTerminals = new List <string>(usedFirsts.Keys);
                writer.WriteLine(generator.GetCodeOfThrowError(rootDefinition.DefinitionName, availableTerminals));
            }
            if (needsBlockAtEmpty)
            {
                writer.WriteLine(generator.GetCodeOfCloseBlock());
            }
        }