protected override void SetupFollowingTerminalsOfSelf(ScriptParserGenerator generator, string[] followings) { foreach (ElementsElement elems in _candidates) { elems.SetupFollowingTerminals(generator, followings); } }
public ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator, out bool oneClassType) { Debug.Assert(_candidates.Count >= 1); List <ParameterSignature> sigList = new List <ParameterSignature>(); HashSet <ParameterSignature> exists = new HashSet <ParameterSignature>(new ParameterSignatureComparer()); foreach (ElementsElement elems in _candidates) { ParameterSignature sig = elems.GetReturnParameterSignature(generator); if (!exists.Contains(sig)) { sigList.Add(sig); exists.Add(sig); } } Debug.Assert(sigList.Count >= 1); if (sigList.Count == 1) { oneClassType = true; return(sigList.First()); } oneClassType = false; ParameterSignature ret = new ParameterSignature("selection", SignatureType.Selection, sigList); return(ret); }
public override ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator) { ParameterSignature inner = _innerExpression.GetReturnParameterSignature(generator); string name = string.Format("{0}_opt", inner.ParamName); return(new ParameterSignature(name, SignatureType.Optional, inner)); }
public override string WriteParseCode(TextWriter writer, ScriptParserGenerator generator) { IList <string> firsts = _innerExpression.GetFirstTerminals(generator); IList <string> followings = this.GetFollowingTerminals(generator); HashSet <string> firstSet = new HashSet <string>(firsts); foreach (string following in followings) { if (firstSet.Contains(following)) { string context = string.Format("'{0}' の定義", this.RootDefinition.DefinitionName); string message = string.Format("省略可能な <{1}> の直後に <{0}> がありますが <{1}> の方が優先されます", following, this.ToString()); generator.Warn(context, message); } } ParameterSignature returnParam = this.GetReturnParameterSignature(generator); string returnType = returnParam.GetTypeName(); string returnVar; writer.WriteLine(generator.GetCodeOfDeclareDefault(returnType, out returnVar)); string peekVar; writer.WriteLine(generator.GetCodeOfPeek(out peekVar)); writer.WriteLine(generator.GetCodeOfIfOptionalLexisIn(peekVar, firsts)); string innerVar = _innerExpression.WriteParseCode(writer, generator); writer.WriteLine(generator.GetCodeOfSubstitution(returnVar, innerVar)); writer.WriteLine(generator.GetCodeOfCloseBlock()); return(returnVar); }
/// <summary> /// 後続終端記号の情報を設定します /// </summary> public void SetupFollowingTerminals(ScriptParserGenerator generator) { if (_followingTerminalsSetupDone) { return; } _followingTerminalsSetupDone = true; _expression.SetupFollowingTerminals(generator, new string[] { null }); }
public override ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator) { switch (_literal.Type) { case GeneratorLexType.Terminal: return(new ParameterSignature(generator.GetTerminalName(this.InnerWord), generator.Settings.InputClass)); case GeneratorLexType.Nonterminal: return(new ParameterSignature(ScriptParserGenerator.ConvertCase(this.InnerWord, generator.Settings.NonterminalCaseConversion), generator.GetReturnClassIdentifier(this.InnerWord))); default: throw new NotSupportedException(); } }
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; }
public IList <string> GetFirstTerminals(ScriptParserGenerator generator) { List <string> ret = new List <string>(); foreach (ElementElement elem in _restElements) { IList <string> res = elem.GetFirstTerminals(generator); ret.AddRange(res.Where(r => r != null)); if (!res.Contains(null)) { return(ret); } } //ret.Add(null); return(ret); }
/// <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)); }
public override string WriteParseCode(TextWriter writer, ScriptParserGenerator generator) { string var; switch (_literal.Type) { case GeneratorLexType.Terminal: writer.WriteLine(generator.GetCodeOfReadOrThrow(this.RootDefinition.DefinitionName, new string[] { this.InnerWord }, out var)); return(var); case GeneratorLexType.Nonterminal: writer.WriteLine(generator.GetCodeOfParseNonterminal(this.InnerWord, out var)); return(var); default: throw new NotSupportedException(); } }
public override ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator) { Debug.Assert(_elements.Count >= 1); if (_elements.Count == 1) { return(_elements.First().GetReturnParameterSignature(generator)); } else { List <ParameterSignature> list = new List <ParameterSignature>(); foreach (ElementElement elems in _elements) { list.Add(elems.GetReturnParameterSignature(generator)); } string name = list.Select(s => s.ParamName).Aggregate((a, b) => a + "_" + b); return(new ParameterSignature(name, SignatureType.FixedList, list)); } }
protected override void SetupFollowingTerminalsOfSelf(ScriptParserGenerator generator, string[] followings) { for (int i = _elements.Count - 1; i >= 0; i--) { // 後ろからfollowingsを設定 _elements[i].SetupFollowingTerminals(generator, followings); IList <string> tmp = _elements[i].GetFirstTerminals(generator); // 注目対象のElementがnullになりうるときは後続のfollowingsを加える if (tmp.Contains(null)) { // followingsにはnullが入っていることもあるけど除かない followings = tmp.Where(t => t != null).Union(followings).ToArray(); } else { followings = tmp.ToArray(); } } }
/// <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)); }
/// <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); // 循環対策に一時的入れていく _followingTerminals = ret.ToArray(); // 末尾にある要素の場合はこの要素を含む定義の後続を追加 if (this.CanBeTailOfDefinition) { ret.AddRange(this.RootDefinition.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(); } }
public override string WriteParseCode(TextWriter writer, ScriptParserGenerator generator) { Debug.Assert(_elements.Count >= 1); if (_elements.Count == 1) { return(_elements.First().WriteParseCode(writer, generator)); } else { List <string> innerVars = new List <string>(); foreach (ElementElement elem in _elements) { string var = elem.WriteParseCode(writer, generator); innerVars.Add(var); } ParameterSignature returnParam = this.GetReturnParameterSignature(generator); string returnType = returnParam.GetTypeName(); string returnVar; writer.WriteLine(generator.GetCodeOfDeclareNew(returnType, innerVars, out returnVar)); return(returnVar); } }
public override string WriteParseCode(TextWriter writer, ScriptParserGenerator generator) { IList <string> firsts = _innerExpression.GetFirstTerminals(generator); IList <string> followings = this.GetFollowingTerminals(generator); HashSet <string> firstSet = new HashSet <string>(firsts); foreach (string following in followings) { if (firstSet.Contains(following)) { string context = string.Format("'{0}' の定義", this.RootDefinition.DefinitionName); string message = string.Format("<{1}> の直後の <{0}> は <{1}> によって隠されます", following, this.ToString()); generator.Warn(context, message); } } ParameterSignature returnParam = this.GetReturnParameterSignature(generator); ParameterSignature innerParam = _innerExpression.GetReturnParameterSignature(generator); string innerType = innerParam.GetTypeName(); string innerListType = string.Format("List<{0}>", innerType); string innerListVar; writer.WriteLine(generator.GetCodeOfDeclareNew(innerListType, out innerListVar)); string peek; writer.WriteLine(generator.GetCodeOfForPeekLexisIn(firsts, out peek)); string innerVar = _innerExpression.WriteParseCode(writer, generator); writer.WriteLine(generator.GetCodeOfInvoke(innerListVar, "Add", innerVar)); writer.WriteLine(generator.GetCodeOfCloseBlock()); string returnType = returnParam.GetTypeName(); string returnVar; writer.WriteLine(generator.GetCodeOfDeclare(returnType, out returnVar)); writer.WriteLine(generator.GetCodeOfInvokeSubstitute(returnVar, innerListVar, "ToArray")); return(returnVar); }
internal void SetupFollowingTerminals(ScriptParserGenerator generator, string[] followings) { _followingTerminalsOfSelf.AddRange(followings.Where(f => f != null)); this.CanBeTailOfDefinition = followings.Any(f => f == null); this.SetupFollowingTerminalsOfSelf(generator, followings); }
/// <summary> /// 各ルールから生成される結果用メソッドのシグネチャを,ルールの要素から牽けるようにしてを返します /// </summary> /// <param name="generator"></param> /// <returns></returns> public IDictionary <ElementsElement, MethodSignature> GetReturnParameterSignaturesAndElements(ScriptParserGenerator generator) { Dictionary <ElementsElement, MethodSignature> methodList = new Dictionary <ElementsElement, MethodSignature>(); foreach (ElementsElement elems in this.Expression.Selection.Candidates) { // ひとつのルールに対してメソッドを一個生成する MethodSignature method = new MethodSignature(); foreach (ElementElement elem in elems.Elements) { ParameterSignature sig = elem.GetReturnParameterSignature(generator); sig.ParamName = sig.ParamName.TrimStart('_'); sig.ParamName = sig.ParamName.TrimEnd('_'); if (sig.ParamName.Length >= 1) { if (char.IsUpper(sig.ParamName[0])) { sig.ParamName = sig.ParamName[0].ToString().ToLower() + sig.ParamName.Substring(1); } } method.Parameters.Add(sig); method.AddEbnfString(elem.ToString()); } // おなじParamNameを持つものを探す HashSet <string> duplicativeNames = new HashSet <string>(from sig in method.Parameters group sig.ParamName by sig.ParamName into nameSet where nameSet.Count() >= 2 select nameSet.Key); Dictionary <string, int> countUpPerName = duplicativeNames.ToDictionary(n => n, n => 1); foreach (ParameterSignature sig in method.Parameters) { if (duplicativeNames.Contains(sig.ParamName)) { string name = sig.ParamName; sig.ParamName = string.Format("{0}_{1}", name, countUpPerName[name]); countUpPerName[name]++; } } method.MethodName = generator.GetReturnMethodIdentifier(this.DefinitionName); methodList[elems] = method; } // 引数の重複性を確認する var groupBy = methodList.Values.GroupBy(method => method, new MethodSignatureParametersComparer()); Dictionary <MethodSignature, List <MethodSignature> > duplicativeMethods = groupBy.ToDictionary(m => m.Key, m => m.ToList()); // 同じ引数のメソッドがある場合にはそれぞれにパラメータから作成される識別子を後置する. foreach (List <MethodSignature> dupMethods in duplicativeMethods.Values) { if (dupMethods.Count >= 2) { foreach (MethodSignature dupMethod in dupMethods) { dupMethod.MethodName += "_" + dupMethod.GetMangledName(); } } } // C#のキーワードが識別子になる場合には頭に@を付ける foreach (MethodSignature method in methodList.Values) { foreach (ParameterSignature sig in method.Parameters) { if (_keywords.Contains(sig.ParamName)) { sig.ParamName = "@" + sig.ParamName; } } } return(methodList); }
/// <summary> /// 各ルールから生成される結果用メソッドのシグネチャのリストを返します /// </summary> /// <param name="generator"></param> /// <returns></returns> public IList <MethodSignature> GetReturnParameterSignatures(ScriptParserGenerator generator) { IDictionary <ElementsElement, MethodSignature> tmp = this.GetReturnParameterSignaturesAndElements(generator); return(tmp.Values.ToArray()); }
protected override void SetupFollowingTerminalsOfSelf(ScriptParserGenerator generator, string[] followings) { _innerExpression.SetupFollowingTerminals(generator, followings); }
public override string WriteParseCode(TextWriter writer, ScriptParserGenerator generator) { return(_innerExpression.WriteParseCode(writer, generator)); }
public override ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator) { ParameterSignature inner = _innerExpression.GetReturnParameterSignature(generator); return(inner); }
public void WriteParseCode(TextWriter writer, ScriptParserGenerator generator) { writer.Write(ScriptParserGenerator.GetAccessibilityString(generator.Settings.ParseMethodAccessibility)); writer.Write(" "); writer.Write(generator.GetReturnClassIdentifier(this.DefinitionName)); writer.Write(" "); writer.Write(generator.GetParseMethodIdentifier(this.DefinitionName)); writer.WriteLine("() {"); generator.IndentCount = 1; generator.InitializeVariableIndex(1); IDictionary <ElementsElement, MethodSignature> methods = this.GetReturnParameterSignaturesAndElements(generator); if (false) { // 普通のコード if (this.Expression.Selection.Candidates.Count >= 2) { IList <string> firsts = this.Expression.Selection.GetFirstTerminals(generator); string peekVar; writer.WriteLine(generator.GetCodeOfPeekOrThrow(this.DefinitionName, firsts, out peekVar)); Dictionary <string, string> usedFirsts = new Dictionary <string, string>(); foreach (ElementsElement elems in this.Expression.Selection.Candidates) { IList <string> innerFirsts = elems.GetFirstTerminals(generator); foreach (string first in innerFirsts) { string usingPoint; if (usedFirsts.TryGetValue(first, out usingPoint)) { string context = string.Format("'{0}' の定義", this.DefinitionName); string message = string.Format("<{1}> 内の <{0}> は <{2}> によって隠されます", first, elems.ToString(), usingPoint); generator.Warn(context, message); } else { usedFirsts[first] = elems.ToString(); } } writer.WriteLine(generator.GetCodeOfIfLexisIn(peekVar, innerFirsts)); List <string> arguments = new List <string>(); foreach (ElementElement elem in elems.Elements) { string var = elem.WriteParseCode(writer, generator); arguments.Add(var); } writer.WriteLine(generator.GetCodeOfReturnMethod(methods[elems].MethodName, arguments)); writer.Write(generator.GetCodeOfCloseBlock()); writer.Write(generator.GetCodeOfSingleElse()); } writer.WriteLine(generator.GetCodeOfOpenBlock()); writer.WriteLine(generator.GetCodeOfThrowNew("System.NotImplementedException", ScriptParserGenerator.EscapeString(this.DefinitionName))); writer.WriteLine(generator.GetCodeOfCloseBlock()); } else { ElementsElement elems = this.Expression.Selection.Candidates.First(); IList <string> innerFirsts = elems.GetFirstTerminals(generator); List <string> arguments = new List <string>(); foreach (ElementElement elem in elems.Elements) { string var = elem.WriteParseCode(writer, generator); arguments.Add(var); } writer.WriteLine(generator.GetCodeOfReturnMethod(methods[elems].MethodName, arguments)); } } else { // 前半部分が同じSelectionをツリー状に探索するようにするために // SelectionSubCandidateを作る List <SelectionSubCandidate> subCandidates = new List <SelectionSubCandidate>(); foreach (ElementsElement candidate in this.Expression.Selection.Candidates) { subCandidates.Add(new SelectionSubCandidate(candidate)); } SelectionSubCandidate.writeParseCodeAux(writer, generator, subCandidates, (candidateAtEmpty, writer2, generator2) => { writer.WriteLine(generator.GetCodeOfReturnMethod(methods[candidateAtEmpty.OriginalElements].MethodName, candidateAtEmpty.TemporaryVariables)); }); } writer.Write("}"); }
public override ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator) { return(Selection.GetReturnParameterSignature(generator)); }
protected override void SetupFollowingTerminalsOfSelf(ScriptParserGenerator generator, string[] followings) { followings = followings.Union(this.GetFirstTerminals(generator).Where(f => f != null)).ToArray(); _innerExpression.SetupFollowingTerminals(generator, followings); }
public override ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator) { ParameterSignature inner = _innerExpression.GetReturnParameterSignature(generator); return(new ParameterSignature("repetition", SignatureType.Array, inner)); }
/// <summary> /// この定義の中で先頭にくる可能性のある終端記号を返します /// </summary> /// <param name="generator"></param> /// <returns></returns> public IList <String> GetFirstTerminals(ScriptParserGenerator generator) { return(this.Expression.GetFirstTerminals(generator)); }
public override ParameterSignature GetReturnParameterSignature(ScriptParserGenerator generator) { bool tmp; return(this.GetReturnParameterSignature(generator, out tmp)); }
public override string WriteParseCode(TextWriter writer, ScriptParserGenerator generator) { if (false) { // 普通のコード Debug.Assert(_candidates.Count >= 1); if (_candidates.Count == 1) { return(_candidates.First().WriteParseCode(writer, generator)); } else { IList <string> firsts = this.GetFirstTerminals(generator); string peekVar; writer.WriteLine(generator.GetCodeOfPeekOrThrow(this.RootDefinition.DefinitionName, firsts, out peekVar)); bool oneClassType; ParameterSignature returnParam = GetReturnParameterSignature(generator, out oneClassType); string returnType = returnParam.GetTypeName(); string returnVar; writer.WriteLine(generator.GetCodeOfDeclareDefault(returnType, out returnVar)); Dictionary <string, string> usedFirsts = new Dictionary <string, string>(); foreach (ElementsElement elems in _candidates) { IList <string> innerFirsts = elems.GetFirstTerminals(generator); foreach (string first in innerFirsts) { string usingPoint; if (usedFirsts.TryGetValue(first, out usingPoint)) { string context = string.Format("'{0}' の定義", this.RootDefinition.DefinitionName); string message = string.Format("<{1}> 内の <{0}> は <{2}> によって隠されます", first, this.ToString(), usingPoint); generator.Warn(context, message); } else { usedFirsts[first] = elems.ToString(); } } writer.WriteLine(generator.GetCodeOfIfLexisIn(peekVar, innerFirsts)); string candidateVar = elems.WriteParseCode(writer, generator); if (oneClassType) { writer.WriteLine(generator.GetCodeOfSubstitution(returnVar, candidateVar)); } else { string selectVar; writer.WriteLine(generator.GetCodeOfDeclareNew(returnType, new[] { candidateVar }, out selectVar)); writer.WriteLine(generator.GetCodeOfSubstitution(returnVar, selectVar)); } writer.Write(generator.GetCodeOfCloseBlock()); writer.Write(generator.GetCodeOfSingleElse()); } writer.Write(generator.GetCodeOfOpenBlock()); writer.WriteLine(generator.GetCodeOfCloseBlock()); return(returnVar); } } else { // 前半部分が同じSelectionをツリー状に探索するようにするために // SelectionSubCandidateを作る List <SelectionSubCandidate> subCandidates = new List <SelectionSubCandidate>(); foreach (ElementsElement candidate in _candidates) { subCandidates.Add(new SelectionSubCandidate(candidate)); } bool oneClassType; ParameterSignature returnParam = this.GetReturnParameterSignature(generator, out oneClassType); string returnVariableName; writer.WriteLine(generator.GetCodeOfDeclareDefault(returnParam.GetTypeName(), out returnVariableName)); SelectionSubCandidate.writeParseCodeAux(writer, generator, subCandidates, (candidateAtEmpty, writer2, generator2) => { // 候補の要素が単一要素の場合はFixedListをnewしなくてよいので分ける string resultVar; if (candidateAtEmpty.OriginalElements.Elements.Count == 1) { resultVar = candidateAtEmpty.TemporaryVariables.First(); } else { ParameterSignature returnParam2 = candidateAtEmpty.OriginalElements.GetReturnParameterSignature(generator2); string typename = returnParam2.GetTypeName(); writer2.WriteLine(generator2.GetCodeOfDeclareNew(typename, candidateAtEmpty.TemporaryVariables, out resultVar)); } bool oneClassReturn; ParameterSignature tmpReturnParam = this.GetReturnParameterSignature(generator2, out oneClassReturn); if (!oneClassReturn) { // 一回Selection<>を作成しないといけない string tmpTypename = tmpReturnParam.GetTypeName(); string tmpResultVar; writer.WriteLine(generator2.GetCodeOfDeclareNew(tmpTypename, new[] { resultVar }, out tmpResultVar)); resultVar = tmpResultVar; } writer2.WriteLine(generator.GetCodeOfSubstitution(returnVariableName, resultVar)); }); return(returnVariableName); } }