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));
        }
Exemple #4
0
        /// <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);
        }
Exemple #10
0
        /// <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);
Exemple #12
0
 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);
        }
Exemple #15
0
 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));
        }
Exemple #19
0
 /// <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);
 }
Exemple #20
0
 /// <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);
        }