public EmptyString <TTokenTypeName, TNonTerminalName, TActionResult> EmptyString( SemanticAction <TActionResult, TTokenTypeName> semanticAction = null) { var matchAction = semanticAction ?? _defaultSemanticActions.EmptyStringAction; return(new EmptyString <TTokenTypeName, TNonTerminalName, TActionResult>(matchAction)); }
public void SemanticActionInitsWithNoArgs() { var semanticAction = new SemanticAction(); Assert.NotNull(semanticAction); Assert.IsType <SemanticAction>(semanticAction); }
public Terminal <TTokenTypeName, TNonTerminalName, TActionResult> Terminal( TTokenTypeName expectedToken, SemanticAction <TActionResult, TTokenTypeName> semanticAction = null) { var matchAction = semanticAction ?? _defaultSemanticActions.GetTerminalAction(expectedToken); return(new Terminal <TTokenTypeName, TNonTerminalName, TActionResult>(expectedToken, matchAction)); }
/// <summary> /// Executes the given LR reduction /// </summary> /// <param name="production">A LR reduction</param> private void Reduce(LRProduction production) { Symbol variable = symVariables[production.Head]; builder.ReductionPrepare(production.Head, production.ReductionLength, production.HeadAction); for (int i = 0; i != production.BytecodeLength; i++) { LROpCode op = production[i]; switch (op.Base) { case LROpCodeBase.SemanticAction: { SemanticAction action = symActions[production[i + 1].DataValue]; i++; action.Invoke(variable, builder); break; } case LROpCodeBase.AddVirtual: { int index = production[i + 1].DataValue; builder.ReductionAddVirtual(index, op.TreeAction); i++; break; } default: builder.ReductionPop(op.TreeAction); break; } } builder.Reduce(); }
public Optional <TTokenTypeName, TNonTerminalName, TActionResult> Optional( IParsingOperator <TTokenTypeName, TNonTerminalName, TActionResult> subExpression, SemanticAction <TActionResult, TTokenTypeName> semanticAction = null) { var matchAction = semanticAction ?? _defaultSemanticActions.OptionalAction; return(new Optional <TTokenTypeName, TNonTerminalName, TActionResult>(subExpression, matchAction)); }
public OrderedChoice <TTokenTypeName, TNonTerminalName, TActionResult> OrderedChoice( IEnumerable <IParsingOperator <TTokenTypeName, TNonTerminalName, TActionResult> > orderedChoices, SemanticAction <TActionResult, TTokenTypeName> semanticAction = null) { var matchAction = semanticAction ?? _defaultSemanticActions.OrderedChoiceAction; return(new OrderedChoice <TTokenTypeName, TNonTerminalName, TActionResult>(orderedChoices, matchAction)); }
public Sequence(IEnumerable <IParsingOperator <TTokenTypeName, TNonTerminalName, TActionResult> > sequenceDefinitions, SemanticAction <TActionResult, TTokenTypeName> matchAction) { if (sequenceDefinitions.Count() < 2) { throw new ArgumentException("Sequence (concatenation) must contain at least 2 elements.", nameof(sequenceDefinitions)); } _sequenceDefinition = sequenceDefinitions; _matchAction = matchAction; }
public OrderedChoice(IEnumerable <IParsingOperator <TTokenTypeName, TNonTerminalName, TActionResult> > choiceSubExpressions, SemanticAction <TActionResult, TTokenTypeName> matchAction) { if (choiceSubExpressions.Count() < 2) { throw new ArgumentException("Must have at least 2 sub-expressions for Ordered Choice."); } _choiceSubExpressions = choiceSubExpressions; _matchAction = matchAction; }
public void SemanticActionInits() { var id = "id"; var entities = new Dictionary <string, Entity>() { { "entityKey", new Entity() } }; var state = "done"; var semanticAction = new SemanticAction(id, entities) { State = state }; Assert.NotNull(semanticAction); Assert.IsType <SemanticAction>(semanticAction); Assert.Equal(id, semanticAction.Id); Assert.Equal(entities, semanticAction.Entities); Assert.Equal(state, semanticAction.State); }
/// <summary> /// Builds the SPPF /// </summary> /// <param name="generation">The current GSS generation</param> /// <param name="production">The LR production</param> /// <param name="first">The first label of the path</param> /// <param name="path">The reduction path</param> /// <returns>The identifier of the corresponding SPPF node</returns> private int BuildSPPF(int generation, LRProduction production, int first, GSSPath path) { Symbol variable = symVariables[production.Head]; sppf.ReductionPrepare(first, path, production.ReductionLength); for (int i = 0; i != production.BytecodeLength; i++) { LROpCode op = production[i]; switch (op.Base) { case LROpCodeBase.SemanticAction: { SemanticAction action = symActions[production[i + 1].DataValue]; i++; action.Invoke(variable, sppf); break; } case LROpCodeBase.AddVirtual: { int index = production[i + 1].DataValue; sppf.ReductionAddVirtual(index, op.TreeAction); i++; break; } case LROpCodeBase.AddNullVariable: { int index = production[i + 1].DataValue; sppf.ReductionAddNullable(nullables[index], op.TreeAction); i++; break; } default: sppf.ReductionPop(op.TreeAction); break; } } return(sppf.Reduce(generation, production.Head, production.HeadAction)); }
public OneOrMore(IParsingOperator <TTokenTypeName, TNonTerminalName, TActionResult> subExpression, SemanticAction <TActionResult, TTokenTypeName> matchAction) => (_subExpression, _matchAction) = (subExpression, matchAction);
public EmptyString(SemanticAction <TActionResult, TTokenTypeName> matchAction) => _matchAction = matchAction;
// The analyze method for the syntactic analyzer takes in a list // of tokens from the lexical analyzer, derives the grammar and handles errors public SyntaxResult analyzeSyntax(List <IToken> lexical) { SymbolTable global = new SymbolTable("Global", null); SyntaxResult results = new SyntaxResult(global); // Remove all errors and comments from the lexical analyzer lexical.RemoveAll(x => x.isError() || x.getToken() == TokenList.BlockComment || x.getToken() == TokenList.LineComment); // Add an end of program token lexical.Add(new SimpleToken(TokenList.EndOfProgram, false)); // The stack for the table parser Stack <IProduceable> parseStack = new Stack <IProduceable>(); parseStack.Push(TokenList.EndOfProgram); parseStack.Push(startProduct); var tokenEnumerator = lexical.GetEnumerator(); // Start enumerating over the list tokenEnumerator.MoveNext(); IToken lastTerminal = null; Stack <SemanticRecord> semanticStack = new Stack <SemanticRecord>(); Stack <SymbolTable> symbolTableStack = new Stack <SymbolTable>(); symbolTableStack.Push(global); // The table driven algorithm as seen in class slides while (parseStack.Peek() != TokenList.EndOfProgram) { var top = parseStack.Peek(); if (top.isTerminal()) { if (top == tokenEnumerator.Current.getToken()) { lastTerminal = tokenEnumerator.Current; parseStack.Pop(); tokenEnumerator.MoveNext(); } else { string resumeMessage = skipErrors(ref tokenEnumerator, parseStack); results.Errors.Add(string.Format("Error Parsing terminal: Expecting {0}, got {1} at token {2}. {3}", top.getProductName(), tokenEnumerator.Current.getToken().getProductName(), tokenEnumerator.Current.getName(), resumeMessage)); } } else if (top is SemanticAction) { // Pop then execute the semantic action parseStack.Pop(); SemanticAction action = (SemanticAction)top; results.SemanticErrors.AddRange(action.ExecuteSemanticAction(semanticStack, symbolTableStack, lastTerminal)); } else { Rule rule; Token token = tokenEnumerator.Current.getToken(); var row = table[top]; // consider removing if (table[top].TryGetValue(token, out rule)) { parseStack.Pop(); for (int i = rule.getSymbols().Count - 1; i >= 0; i--) { if (rule.getSymbols()[i] != TokenList.Epsilon) { parseStack.Push(rule.getSymbols()[i]); } } } else // if no entry exists for a symbol token pair, then it is an error { string resumeMessage = skipErrors(ref tokenEnumerator, parseStack); results.Errors.Add(string.Format("Could not find rule for produce {0} to produce {1} at token {2}. {3}", top.getProductName(), token.getProductName(), tokenEnumerator.Current.getName(), resumeMessage)); } } // Add the current state of the stack to the derivation list results.Derivation.Add(new List <IProduceable>(parseStack)); } return(results); }
/// <summary> /// When a SkillDialog is started, a skillBegin event is sent which firstly indicates the Skill is being invoked in Skill mode, also slots are also provided where the information exists in the parent Bot. /// </summary> /// <param name="innerDc">inner dialog context.</param> /// <param name="options">options.</param> /// <param name="cancellationToken">cancellation token.</param> /// <returns>dialog turn result.</returns> protected override async Task <DialogTurnResult> OnBeginDialogAsync(DialogContext innerDc, object options = null, CancellationToken cancellationToken = default(CancellationToken)) { var slots = new Dictionary <string, JObject>(); // Retrieve the SkillContext state object to identify slots (parameters) that can be used to slot-fill when invoking the skill var accessor = _userState.CreateProperty <SkillContext>(nameof(SkillContext)); var skillContext = await accessor.GetAsync(innerDc.Context, () => new SkillContext()); /* In instances where the caller is able to identify/specify the action we process the Action specific slots * In other scenarios (aggregated skill dispatch) we evaluate all possible slots against context and pass across * enabling the Skill to perform it's own action identification. */ var actionName = options != null ? options as string : null; if (actionName != null) { // Find the specified within the selected Skill for slot filling evaluation var action = _skillManifest.Actions.SingleOrDefault(a => a.Id == actionName); if (action != null) { // If the action doesn't define any Slots or SkillContext is empty then we skip slot evaluation if (action.Definition.Slots != null && skillContext.Count > 0) { // Match Slots to Skill Context slots = await MatchSkillContextToSlots(innerDc, action.Definition.Slots, skillContext); } } else { throw new ArgumentException($"Passed Action ({actionName}) could not be found within the {_skillManifest.Id} skill manifest action definition."); } } else { // The caller hasn't got the capability of identifying the action as well as the Skill so we enumerate // actions and slot data to pass what we have // Retrieve a distinct list of all slots, some actions may use the same slot so we use distinct to ensure we only get 1 instance. var skillSlots = _skillManifest.Actions.SelectMany(s => s.Definition.Slots).Distinct(new SlotEqualityComparer()); if (skillSlots != null) { // Match Slots to Skill Context slots = await MatchSkillContextToSlots(innerDc, skillSlots.ToList(), skillContext); } } await innerDc.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"-->Handing off to the {_skillManifest.Name} skill.")); var activity = innerDc.Context.Activity; var entities = new Dictionary <string, Entity>(); foreach (var value in slots) { entities.Add(value.Key, new Entity { Properties = JObject.FromObject(value.Value) }); } var semanticAction = new SemanticAction { Entities = new Dictionary <string, Entity>() }; foreach (var slot in slots) { semanticAction.Entities.Add(slot.Key, new Entity { Properties = slot.Value }); } activity.SemanticAction = semanticAction; // Send skillBegin event to Skill/Bot var dialogResult = await ForwardToSkillAsync(innerDc, activity); // return APIResponse if any if (_apiResponses != null && _apiResponses.Count > 0) { dialogResult.Result = _apiResponses; _skillTransport.Disconnect(); return(await innerDc.EndDialogAsync(_apiResponses)); } // if there's any response we need to send to the skill queued // forward to skill and start a new turn while (_queuedResponses.Count > 0) { await ForwardToSkillAsync(innerDc, _queuedResponses.Dequeue()); } _skillTransport.Disconnect(); return(dialogResult); }
public NonTerminal(TNonTerminalName nonTerminalName, SemanticAction <TActionResult, TTokenTypeName> matchAction) => (_nonTerminalName, _matchAction, _previousStartIndices) = (nonTerminalName, matchAction, new HashSet <int>());
public Sequence <TTokenTypeName, TNonTerminalName, TActionResult> Sequence( IEnumerable <IParsingOperator <TTokenTypeName, TNonTerminalName, TActionResult> > sequenceDefinitions, SemanticAction <TActionResult, TTokenTypeName> matchAction = null) => new Sequence <TTokenTypeName, TNonTerminalName, TActionResult>(sequenceDefinitions, matchAction ?? _defaultSemanticActions.SequenceAction);
public NonTerminal <TTokenTypeName, TNonTerminalName, TActionResult> NonTerminal(TNonTerminalName head, SemanticAction <TActionResult, TTokenTypeName> semanticAction = null) { var action = semanticAction ?? _defaultSemanticActions.GetNonTerminalAction(head); return(new NonTerminal <TTokenTypeName, TNonTerminalName, TActionResult>(head, action)); }
public ZeroOrMore <TTokenTypeName, TNonTerminalName, TActionResult> ZeroOrMore( IParsingOperator <TTokenTypeName, TNonTerminalName, TActionResult> subExpression, SemanticAction <TActionResult, TTokenTypeName> semanticAction = null) { var matchAction = semanticAction ?? _defaultSemanticActions.ZeroOrMoreAction; return(new ZeroOrMore <TTokenTypeName, TNonTerminalName, TActionResult>(subExpression, matchAction)); }
/// <summary> /// Gets the set of semantic actions in the form a table consistent with the automaton /// </summary> /// <param name="input">A set of semantic actions</param> /// <returns>A table of semantic actions</returns> private static SemanticAction[] GetUserActions(Dictionary <string, SemanticAction> input) { SemanticAction[] result = new SemanticAction[1]; result[0] = input["OnLopla"]; return(result); }
/// <summary> /// Gets the set of semantic actions in the form a table consistent with the automaton /// </summary> /// <param name="input">A set of semantic actions</param> /// <returns>A table of semantic actions</returns> private static SemanticAction[] GetUserActions(Actions input) { SemanticAction[] result = new SemanticAction[1]; result[0] = new SemanticAction(input.OnLopla); return(result); }
public Terminal(TTokenTypeName expectedToken, SemanticAction <TActionResult, TTokenTypeName> matchAction) => (_expectedToken, _matchAction) = (expectedToken, matchAction);
/// <summary> /// When a SkillDialog is started, a skillBegin event is sent which firstly indicates the Skill is being invoked in Skill mode, also slots are also provided where the information exists in the parent Bot. /// </summary> /// <param name="innerDc">inner dialog context.</param> /// <param name="options">options.</param> /// <param name="cancellationToken">cancellation token.</param> /// <returns>dialog turn result.</returns> protected override async Task <DialogTurnResult> OnBeginDialogAsync(DialogContext innerDc, object options = null, CancellationToken cancellationToken = default(CancellationToken)) { var slots = new Dictionary <string, JObject>(); // Retrieve the SkillContext state object to identify slots (parameters) that can be used to slot-fill when invoking the skill var accessor = _userState.CreateProperty <SkillContext>(nameof(SkillContext)); var skillContext = await accessor.GetAsync(innerDc.Context, () => new SkillContext()).ConfigureAwait(false); var dialogOptions = options != null ? options as SkillDialogOption : null; var actionName = dialogOptions?.Action; var activity = innerDc.Context.Activity; // only set SemanticAction if it's not populated if (activity.SemanticAction == null) { var semanticAction = new SemanticAction { Id = actionName, Entities = new Dictionary <string, Entity>(), }; if (!string.IsNullOrWhiteSpace(actionName)) { // only set the semantic state if action is not empty semanticAction.State = SkillConstants.SkillStart; // Find the specified action within the selected Skill for slot filling evaluation var action = _skillManifest.Actions.SingleOrDefault(a => a.Id == actionName); if (action != null) { // If the action doesn't define any Slots or SkillContext is empty then we skip slot evaluation if (action.Definition.Slots != null && skillContext.Count > 0) { // Match Slots to Skill Context slots = await MatchSkillContextToSlotsAsync(innerDc, action.Definition.Slots, skillContext).ConfigureAwait(false); } } else { throw new ArgumentException($"Passed Action ({actionName}) could not be found within the {_skillManifest.Id} skill manifest action definition."); } } else { // The caller hasn't got the capability of identifying the action as well as the Skill so we enumerate // actions and slot data to pass what we have // Retrieve a distinct list of all slots, some actions may use the same slot so we use distinct to ensure we only get 1 instance. var skillSlots = _skillManifest.Actions.SelectMany(s => s.Definition.Slots).Distinct(new SlotEqualityComparer()); if (skillSlots != null) { // Match Slots to Skill Context slots = await MatchSkillContextToSlotsAsync(innerDc, skillSlots.ToList(), skillContext).ConfigureAwait(false); } } foreach (var slot in slots) { semanticAction.Entities.Add(slot.Key, new Entity { Properties = slot.Value }); } activity.SemanticAction = semanticAction; } await innerDc.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"-->Handing off to the {_skillManifest.Name} skill.")).ConfigureAwait(false); var dialogResult = await ForwardToSkillAsync(innerDc, activity).ConfigureAwait(false); _skillTransport.Disconnect(); return(dialogResult); }