/// <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));
        }
예제 #2
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));
        }
예제 #3
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();
            }
        }