protected Symbol MatchGerundSignature(string gerund, ParseForest forest, ParseTreeVisitor visitor, SemanticContext context, bool isSubject) { string root = gerund.FormOf(Inflections.plural); " Found gerund for".Log(root); var context2 = new SemanticContext { InvocationBeingDefined = new Invocation(root), SignatureBeingDefined = new Signature(root), }; CreateSymbol(forest, visitor.Right(), context2); context2.InvocationBeingDefined.SuppliedArguments = context2.SignatureBeingDefined.parms; Scope.Current.ResolveMultimethodSymbolByArguments(context2.InvocationBeingDefined); if (context2.InvocationBeingDefined.FunctionSymbol == null) { throw new Backtrack("Signature of parameter-function \"" + context2.SignatureBeingDefined + "\" doesn't match any existing functions."); } var newSymbol = new Symbol { Name = context2.SignatureBeingDefined.verb, // todo: might the name & type be backward? It's usually the other way but the logging looks better this way: it's more precise Type = context2.SignatureBeingDefined.ToString(), Category = Categories.Variable, // local variable PartOfSpeech = NonTerminalSymbol.GP, }; context.SignatureBeingDefined[context.prepFound] = newSymbol; context.SignatureBeingDefined.HasSubject |= isSubject; " Higher-order function".Log("\"" + context.SignatureBeingDefined + "\" has a parameter \"" + context2.SignatureBeingDefined + "\" which could accept any \"" + context2.InvocationBeingDefined.FunctionSymbol.Signature + "\""); return(context2.InvocationBeingDefined.FunctionSymbol); }
protected string WithAlternates(ParseForest forest, ParseTreeVisitor resetVisitor, SemanticContext context, string retryScope = null) { string errors = ""; ParseTreeNodeMatch c = resetVisitor.currentNode; for (; errors != null && c != null; c = c.next) { try { var visitor = new ParseTreeVisitor(resetVisitor) { currentNode = c }; visitor.Right(); // does this need be here? what if we want Left? Should i pass in these two lines as delegate? CreateSymbol(forest, visitor, context); errors = null; } catch (Backtrack b) { "--BACKTRACK".Log(); errors += b.Message + Environment.NewLine; if (retryScope == null) { continue; } Scope.Abandon(); Scope.EnterNew(retryScope); } } if (errors != null && c == null) { if (retryScope != null) { Scope.Abandon(); } return(errors); } return(null); }
protected void DefineTemporalConstraint(ParseForest forest, SemanticContext context) { var DCvisitor = new ParseTreeVisitor(forest); var MCvisitor = new ParseTreeVisitor(DCvisitor); if (DCvisitor.currentNode.B == NonTerminalSymbol.DC) { DCvisitor.Left(); MCvisitor.Right(); } else { DCvisitor.Right(); MCvisitor.Left(); } context.SignatureBeingDefined.verb = "??constraint"; context.InvocationBeingDefined = new Invocation(""); context.FunctionBeingDefined = new Symbol { Category = Categories.Constraint, PartOfSpeech = NonTerminalSymbol.TR, }; Scope.EnterNew(context.SignatureBeingDefined.verb); DefineImpInvSymbol(forest, context, MCvisitor); " MAIN CLAUSE:".Log(context.SignatureBeingDefined.verb); DefineImpInvSymbol(forest, context, DCvisitor); " DEPENDENT CLAUSE:".Log(context.SignatureBeingDefined.verb); "DEFINED constraint:".Log(context.SignatureBeingDefined); context.FunctionBeingDefined.Name = context.SignatureBeingDefined.ToString(); context.FunctionBeingDefined.Type = context.SignatureBeingDefined.verb; context.FunctionBeingDefined.Signature = context.SignatureBeingDefined; Scope.Current.Define(context.FunctionBeingDefined); EndPreviousFunctionBody(context); }
protected void CreateSymbol(ParseForest forest, ParseTreeVisitor visitor, SemanticContext context) { if (visitor == null) { return; } ParseTreeVisitor visitor2; switch (visitor.currentType) { case NonTerminalSymbol.G: // the problem with lone gerunds like "giving" is that you don't know if its GP or aGP so look to see what the container is if (visitor.parentNode.B == NonTerminalSymbol.IV) { // aGP MatchGerundSignature(forest.a[visitor.i], forest, visitor, context, false); } else if (visitor.parentNode.B == NonTerminalSymbol.VO || visitor.parentNode.B == NonTerminalSymbol.SVO) { // GP //if (visitor.currentNode != null && visitor.currentNode.B == NonTerminalSymbol.G) MatchGerundSignature(forest.a[visitor.i], forest, visitor, context, false); //else // FillParameterWith_NP(forest, visitor, context); // the G -- G is an argument } else { throw new Exception("Unknown context for lone gerund."); } break; case NonTerminalSymbol.NPPP: case NonTerminalSymbol.SV: case NonTerminalSymbol.SVO: case NonTerminalSymbol.VO: case NonTerminalSymbol.IsHas: case NonTerminalSymbol.NPs: case NonTerminalSymbol.ConjNP: case NonTerminalSymbol.aSVO: case NonTerminalSymbol.aNPPP: visitor2 = new ParseTreeVisitor(visitor); CreateSymbol(forest, visitor.Left(), context); CreateSymbol(forest, visitor2.Right(), context); break; case NonTerminalSymbol.XYZ: CreateSymbol(forest, visitor.Right(), context); break; case NonTerminalSymbol.Conj: case NonTerminalSymbol.comma: case NonTerminalSymbol.colon: break; case NonTerminalSymbol.aSV: if (visitor.currentNode != null && visitor.currentNode.B == NonTerminalSymbol.G) { MatchGerundSignature(forest.a[visitor.i], forest, visitor.Left(), context, true); } else { CreateParameterFrom_aNP(forest, visitor.Left(), context, true); } break; case NonTerminalSymbol.aVO: if (visitor.currentNode != null && visitor.currentNode.B == NonTerminalSymbol.G) { MatchGerundSignature(forest.a[visitor.i], forest, visitor.Right(), context, false); } else { CreateParameterFrom_aNP(forest, visitor.Right(), context, true); } break; case NonTerminalSymbol.aGP: case NonTerminalSymbol.aNP: if (visitor.currentNode != null && visitor.currentNode.B == NonTerminalSymbol.G) { MatchGerundSignature(forest.a[visitor.i], forest, visitor, context, false); } else { CreateParameterFrom_aNP(forest, visitor, context); } break; case NonTerminalSymbol.aPP: case NonTerminalSymbol.PP: context.prepFound = ""; visitor2 = new ParseTreeVisitor(visitor); CreateSymbol(forest, visitor.Left(), context); CreateSymbol(forest, visitor2.Right(), context); break; case NonTerminalSymbol.P: context.prepFound = forest.a[visitor.i]; break; case NonTerminalSymbol.GP: MatchGerundSignature(forest.a[visitor.i], forest, visitor, context, false); break; case NonTerminalSymbol.NP: // is this NP actually a gerund phrase? if (visitor.currentNode != null && visitor.currentNode.B == NonTerminalSymbol.G) { MatchGerundSignature(forest.a[visitor.i], forest, visitor, context, false); } else { FillParameterWith_NP(forest, visitor, context); } break; case NonTerminalSymbol.V: case NonTerminalSymbol.VP: if (context.InvocationBeingDefined == null) { context.InvocationBeingDefined = new Invocation(forest.a[visitor.i]); } else { context.InvocationBeingDefined.verb = forest.a[visitor.i]; } break; case NonTerminalSymbol.Ops: //AppendToFunctionBody(context); visitor2 = new ParseTreeVisitor(visitor); CreateSymbol(forest, visitor.Left(), context); CreateSymbol(forest, visitor2.Right(), context); break; case NonTerminalSymbol.ConjOp: AppendToFunctionBody(context); visitor2 = new ParseTreeVisitor(visitor); CreateSymbol(forest, visitor.Left(), context); CreateSymbol(forest, visitor2.Right(), context); break; case NonTerminalSymbol.body: CreateSymbol(forest, visitor.Right(), context); AppendToFunctionBody(context); break; case NonTerminalSymbol.DeObj: case NonTerminalSymbol.DeVar: var whichCase = visitor.currentType; visitor2 = new ParseTreeVisitor(visitor); if (visitor.currentNode.B == NonTerminalSymbol.G) { throw new Exception("Can't use a gerund phrase yet"); } Symbol ident = CreateSymbolFromNP(forest, visitor.Left(), context); using (Scope.EnterNew("of " + ident.Name)) { CreateSymbol(forest, visitor2.Right(), context); if (whichCase == NonTerminalSymbol.DeVar && context.SignatureBeingDefined.parms.Count == 1) { ident.Type = context.SignatureBeingDefined.parms[0].aNP.Type; } } break; default: visitor.currentType.ToString().Log("isn't known by the big switch statement in CreateSymbol"); return; } }