Esempio n. 1
0
 protected void OnActionSelected(Token input, ActionRecord action)
 {
     Data.Grammar.OnActionSelected(this, _currentToken, action);
     if (ActionSelected != null)
     {
         ParserActionEventArgs args = new ParserActionEventArgs(this.CurrentState, input, action);
         ActionSelected(this, args);
     }
 }
Esempio n. 2
0
        //TODO: need to rewrite, looks ugly
        private bool Recover()
        {
            if (_currentToken.Category != TokenCategory.Error)
            {
                _currentToken = Grammar.CreateSyntaxErrorToken(_context, _currentToken.Location, "Syntax error.");
            }
            //Check the current state and states in stack for error shift action - this would be recovery state.
            ActionRecord action = GetCurrentAction();

            if (action == null || action.ActionType == ParserActionType.Reduce)
            {
                while (Stack.Count > 0)
                {
                    _currentState = Stack.Top.State;
                    Stack.Pop(1);
                    action = GetCurrentAction();
                    if (action != null && action.ActionType != ParserActionType.Reduce)
                    {
                        break; //we found shift action for error token
                    }
                }//while
            }//if
            if (action == null || action.ActionType == ParserActionType.Reduce)
            {
                return(false); //could not find shift action, cannot recover
            }
            //We found recovery state, and action contains ActionRecord for "error shift". Lets shift it.
            ExecuteShiftAction(action);//push the error token
            // Now shift all tokens from input that can be shifted.
            // These are the ones that are found in error production after the error. We ignore all other tokens
            // We stop when we find a state with reduce-only action.
            while (_currentToken.Terminal != Grammar.Eof)
            {
                //with current token, see if we can shift it.
                action = GetCurrentAction();
                if (action == null)
                {
                    NextToken(); //skip this token and continue reading input
                    continue;
                }
                if (action.ActionType == ParserActionType.Reduce || action.ActionType == ParserActionType.Operator)
                {
                    //we can reduce - let's reduce and return success - we recovered.
                    ExecuteReduceAction(action);
                    return(true);
                }
                //it is shift action, let's shift
                ExecuteShiftAction(action);
            }//while
            return(false); //
        }
Esempio n. 3
0
        private void ExecuteReduceAction(ActionRecord action)
        {
            ParserState oldState = _currentState;
            int         popCnt   = action.PopCount;

            //Get new node's child nodes - these are nodes being popped from the stack
            AstNodeList childNodes = new AstNodeList();

            for (int i = 0; i < action.PopCount; i++)
            {
                AstNode child = Stack[Stack.Count - popCnt + i].Node;
                if (!child.Term.IsSet(TermOptions.IsPunctuation))
                {
                    childNodes.Add(child);
                }
            }
            //recover state, location and pop the stack
            SourceSpan newNodeSpan;

            if (popCnt == 0)
            {
                newNodeSpan = new SourceSpan(_currentToken.Location, 0);
            }
            else
            {
                SourceLocation firstPopLoc   = Stack[Stack.Count - popCnt].Node.Location;
                int            lastPopEndPos = Stack[Stack.Count - 1].Node.Span.EndPos;
                newNodeSpan   = new SourceSpan(firstPopLoc, lastPopEndPos - firstPopLoc.Position);
                _currentState = Stack[Stack.Count - popCnt].State;
                Stack.Pop(popCnt);
            }
            //Create new node
            AstNode node = CreateNode(action, newNodeSpan, childNodes);

            // Push node/current state into the stack
            Stack.Push(node, _currentState);
            //switch to new state
            ActionRecord gotoAction;

            if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction))
            {
                _currentState = gotoAction.NewState;
            }
            else
            {
                //should never happen
                throw new CompilerException(string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}",
                                                          action.NonTerminal, oldState, _currentState));
            }
        }//method
Esempio n. 4
0
        private ActionRecord GetCurrentAction()
        {
            ActionRecord action = null;

            if (_currentToken.MatchByValue)
            {
                string key = CurrentToken.Text;
                if (!_caseSensitive)
                {
                    key = key.ToLower();
                }
                if (_currentState.Actions.TryGetValue(key, out action))
                {
                    return(action);
                }
            }
            if (_currentToken.MatchByType && _currentState.Actions.TryGetValue(_currentToken.Terminal.Key, out action))
            {
                return(action);
            }
            return(null); //action not found
        }
Esempio n. 5
0
 public ParserActionEventArgs(ParserState state, Token input, ActionRecord action)
 {
     State  = state;
     Input  = input;
     Action = action;
 }
Esempio n. 6
0
 public virtual ActionRecord OnActionConflict(Parser parser, Token input, ActionRecord action)
 {
     return(action);
 }
Esempio n. 7
0
 public virtual void OnActionSelected(Parser parser, Token input, ActionRecord action)
 {
 }
Esempio n. 8
0
 // Override this method in language grammar if you want a custom node creation mechanism.
 public virtual AstNode CreateNode(CompilerContext context, ActionRecord reduceAction,
                                   SourceSpan sourceSpan, AstNodeList childNodes)
 {
     return(null);
 }
Esempio n. 9
0
        }//method

        private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes)
        {
            NonTerminal nt = reduceAction.NonTerminal;
            AstNode     result;

            AstNodeArgs args = new AstNodeArgs(nt, _context, sourceSpan, childNodes);

            result = nt.InvokeNodeCreator(args);
            if (result != null)
            {
                return(result);
            }

            Type defaultNodeType = _context.Compiler.Grammar.DefaultNodeType;
            Type ntNodeType      = nt.NodeType ?? defaultNodeType ?? typeof(AstNode);

            // Check if NonTerminal is a list
            // List nodes are produced by .Plus() or .Star() methods of BnfElement
            // In this case, we have a left-recursive list formation production:
            //     ntList -> ntList + delim? + ntElem
            //  We check if we have already created the list node for ntList (in the first child);
            //  if yes, we use this child as a result directly, without creating new list node.
            //  The other incoming child - the last one - is a new list member;
            // we simply add it to child list of the result ntList node. Optional "delim" node is simply thrown away.
            bool isList = nt.IsSet(TermOptions.IsList);

            if (isList && childNodes.Count > 1 && childNodes[0].Term == nt)
            {
                result = childNodes[0];
                AstNode newChild = childNodes[childNodes.Count - 1];
                newChild.Parent = result;
                result.ChildNodes.Add(newChild);
                return(result);
            }
            //Check for StarList produced by MakeStarList; in this case the production is:  ntList -> Empty | Elem+
            // where Elem+ is non-empty list of elements. The child list we are actually interested in is one-level lower
            if (nt.IsSet(TermOptions.IsStarList) && childNodes.Count == 1)
            {
                childNodes = childNodes[0].ChildNodes;
            }
            // Check for "node-bubbling" case. For identity productions like
            //   A -> B
            // the child node B is usually a subclass of node A,
            // so child node B can be used directly in place of the A. So we simply return child node as a result.
            // TODO: probably need a grammar option to enable/disable this behavior explicitly
            if (!isList && !nt.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1)
            {
                Type childNodeType = childNodes[0].Term.NodeType ?? defaultNodeType ?? typeof(AstNode);
                if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType))
                {
                    return(childNodes[0]);
                }
            }
            // Try using Grammar's CreateNode method
            result = Data.Grammar.CreateNode(_context, reduceAction, sourceSpan, childNodes);
            if (result == null)
            {
                //Finally create node directly. For perf reasons we try using "new" for AstNode type (faster), and
                // activator for all custom types (slower)
                if (ntNodeType == typeof(AstNode))
                {
                    result = new AstNode(args);
                }
                else
#if PocketPC || SILVERLIGHT
                {
                    ConstructorInfo ctor = ntNodeType.GetConstructor(new Type[] { typeof(AstNodeArgs) });
                    if (ctor == null)
                    {
                        throw new Exception("Failed to located constructor: " + ntNodeType.ToString() + "(AstNodeArgs args)");
                    }
                    result = (AstNode)ctor.Invoke(new object[] { args });
                }
#else
                {
                    result = (AstNode)Activator.CreateInstance(ntNodeType, args);
                }
#endif
            }
            if (result != null)
            {
                nt.OnNodeCreated(result);
            }
            return(result);
        }
Esempio n. 10
0
 private void ExecuteShiftAction(ActionRecord action)
 {
     Stack.Push(_currentToken, _currentState);
     _currentState = action.NewState;
     NextToken();
 }
Esempio n. 11
0
        }//method

        public AstNode Parse(CompilerContext context, IEnumerable <Token> tokenStream)
        {
            _context       = context;
            _caseSensitive = _context.Compiler.Grammar.CaseSensitive;
            Reset();
            _input = tokenStream.GetEnumerator();
            NextToken();
            while (true)
            {
                if (_currentState == Data.FinalState)
                {
                    AstNode result = Stack[0].Node;
                    Stack.Reset();
                    return(result);
                }
                //check for scammer error
                if (_currentToken.Terminal.Category == TokenCategory.Error)
                {
                    ReportScannerError();
                    if (!Recover())
                    {
                        return(null);
                    }
                    continue;
                }
                //Get action
                ActionRecord action = GetCurrentAction();
                if (action == null)
                {
                    ReportParserError();
                    if (!Recover())
                    {
                        return(null); //did not recover
                    }
                    continue;
                }//action==null

                if (action.HasConflict())
                {
                    action = Data.Grammar.OnActionConflict(this, _currentToken, action);
                }
                this.OnActionSelected(_currentToken, action);
                switch (action.ActionType)
                {
                case ParserActionType.Operator:
                    if (GetActionTypeForOperation(_currentToken) == ParserActionType.Shift)
                    {
                        goto case ParserActionType.Shift;
                    }
                    else
                    {
                        goto case ParserActionType.Reduce;
                    }

                case ParserActionType.Shift:
                    ExecuteShiftAction(action);
                    break;

                case ParserActionType.Reduce:
                    ExecuteReduceAction(action);
                    break;
                } //switch
            }     //while
        }         //Parse