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