/// <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)); }
/// <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)); }
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(); } }