Beispiel #1
0
        /// <summary>
        /// 返回指定状态的唯一可行归约。
        /// </summary>
        /// <param name="actions">要寻找唯一归约的状态动作。</param>
        /// <returns>如果指定状态中只有一个归约是可行的,则返回唯一的可行归约;
        /// 否则返回错误动作。</returns>
        private static ParseAction FindUniqueReduction(ParseAction[] actions)
        {
            ParseAction action = ParseAction.Error;

            for (int i = 1; i < actions.Length; i++)
            {
                switch (actions[i].ActionType)
                {
                case ParseActionType.Accept:
                case ParseActionType.Shift:
                    return(ParseAction.Error);

                case ParseActionType.Reduce:
                    if (action.ActionType == ParseActionType.Error)
                    {
                        action = actions[i];
                    }
                    else if (action.Index != actions[i].Index)
                    {
                        return(ParseAction.Error);
                    }
                    break;
                }
            }
            return(action);
        }
Beispiel #2
0
        /// <summary>
        /// 分析当前的符号。
        /// </summary>
        /// <param name="token">要分析的符号。</param>
        public override void Parse(Token <T> token)
        {
            if (token.IsEndOfFile)
            {
                if (stateStack.Count == 1)
                {
                    return;
                }
            }
            while (true)
            {
                int         state  = stateStack.Peek();
                ParseAction action = GetAction(state, token.Id);
                switch (action.ActionType)
                {
                case ParseActionType.Shift:
                    Shift(token, action.Index);
                    goto ReduceByUnique;

                case ParseActionType.Reduce:
                    Reduce(action.Index);
                    break;

                case ParseActionType.Accept:
                    stateStack.Pop();
                    result = tokenStack.Pop();
                    return;

                case ParseActionType.Error:
                    ReportError(state, token);
                    // ErrorRecovery(state, token.Id);
                    return;
                }
            }
ReduceByUnique:
            // 尝试根据唯一归约进行归约。
            while (true)
            {
                int         state  = stateStack.Peek();
                ParseAction action = rule.States[state].Actions[Constants.UniqueIdx];
                switch (action.ActionType)
                {
                case ParseActionType.Reduce:
                    Reduce(action.Index);
                    break;

                case ParseActionType.Error:
                    return;
                }
            }
        }
Beispiel #3
0
 /// <summary>
 /// 分析并尝试解决动作中的冲突。
 /// </summary>
 /// <param name="grammar">语法分析器使用的语法。</param>
 /// <param name="index">当前状态的索引。</param>
 /// <param name="actionList">动作列表。</param>
 /// <returns>解决冲突后的动作列表。</returns>
 private ParseAction[] ResolveActions(Grammar <T> grammar, int index,
                                      List <Tuple <LRItem <T>, ParseAction> >[] actionList)
 {
     ParseAction[] actions = new ParseAction[actionCount];
     for (int i = 1; i < actionCount; i++)
     {
         List <Tuple <LRItem <T>, ParseAction> > list = actionList[i];
         int cnt = list.Count;
         if (cnt == 0)
         {
             continue;
         }
         if (cnt == 1)
         {
             actions[i] = list[0].Item2;
             continue;
         }
         // 当前的终结符。
         T sym = (T)Enum.ToObject(typeof(T), i - Constants.TokenOffset);
         List <ParserConflictItem> conflictItems = new List <ParserConflictItem>();
         conflictItems.Add(new ParserConflictItem(list[0].Item1.ToString(), list[0].Item2));
         ParseAction action    = list[0].Item2;
         int         actionIdx = 0;
         for (int j = 1; j < list.Count; j++)
         {
             if (action.ActionType == ParseActionType.Reduce)
             {
                 if (list[j].Item2.ActionType == ParseActionType.Shift)
                 {
                     int assocCmp = grammar.CompareAssociativity(productions[action.Index], sym);
                     // 冲突时采用移入。
                     if (assocCmp == 0)
                     {
                         action = list[j].Item2;
                         conflictItems.Add(new ParserConflictItem(list[j].Item1.ToString(), list[j].Item2));
                     }
                     else if (assocCmp == -1)
                     {
                         action = list[j].Item2;
                         conflictItems.RemoveAt(actionIdx);
                         actionIdx = conflictItems.Count;
                         conflictItems.Add(new ParserConflictItem(list[j].Item1.ToString(), list[j].Item2));
                     }
                 }
                 else
                 {
                     int assocCmp = grammar.CompareAssociativity(productions[action.Index],
                                                                 list[j].Item1.Production);
                     if (assocCmp == -1)
                     {
                         action = list[j].Item2;
                         conflictItems.RemoveAt(actionIdx);
                         actionIdx = conflictItems.Count;
                         conflictItems.Add(new ParserConflictItem(list[j].Item1.ToString(), list[j].Item2));
                     }
                     else if (assocCmp == 0)
                     {
                         // 冲突时采用标号较小的规则。
                         if (list[j].Item2.Index < action.Index)
                         {
                             action = list[j].Item2;
                         }
                         conflictItems.Add(new ParserConflictItem(list[j].Item1.ToString(), list[j].Item2));
                     }
                 }
             }
             else if (list[j].Item2.ActionType == ParseActionType.Reduce)
             {
                 int assocCmp = grammar.CompareAssociativity(productions[action.Index], sym);
                 // 冲突时采用移入。
                 if (assocCmp == 1)
                 {
                     action = list[j].Item2;
                     conflictItems.RemoveAt(actionIdx);
                     actionIdx = conflictItems.Count;
                     conflictItems.Add(new ParserConflictItem(list[j].Item1.ToString(), list[j].Item2));
                 }
                 else if (assocCmp == 0)
                 {
                     conflictItems.Add(new ParserConflictItem(list[j].Item1.ToString(), list[j].Item2));
                 }
             }
         }
         if (conflictItems.Count > 1)
         {
             conflicts.Add(new ParserConflict(index, sym.ToString(), actionIdx, conflictItems.ToArray()));
         }
         actions[i] = action;
     }
     actions[Constants.UniqueIdx] = FindUniqueReduction(actions);
     return(actions);
 }
Beispiel #4
0
        /// <summary>
        /// 构造 LALR 语法分析表。
        /// </summary>
        /// <param name="grammar">语法分析器使用的语法。</param>
        /// <param name="itemsets">LR 项集族。</param>
        private void BuildLRTable(Grammar <T> grammar, List <LRItemset <T> > itemsets)
        {
            int stateCnt = itemsets.Count;

            this.states = new StateData[stateCnt];
            int gotoCnt = grammar.NonTerminals.Count;

            for (int i = 0; i < stateCnt; i++)
            {
                List <Tuple <LRItem <T>, ParseAction> >[] actions = new List <Tuple <LRItem <T>, ParseAction> > [actionCount];
                for (int j = 0; j < actionCount; j++)
                {
                    actions[j] = new List <Tuple <LRItem <T>, ParseAction> >();
                }
                LRItemset <T> itemset = itemsets[i];
                foreach (LRItem <T> item in itemset.Items)
                {
                    if (item.Index < item.Production.Body.Count)
                    {
                        // 移入动作。
                        Symbol <T>   sym  = item.Production.Body[item.Index];
                        Terminal <T> tSym = sym as Terminal <T>;
                        if (tSym != null)
                        {
                            int targetIndex = itemset.Goto[tSym];
                            actions[tSym.Index + Constants.TokenOffset].Add(
                                new Tuple <LRItem <T>, ParseAction>(item, ParseAction.Shift(targetIndex)));
                        }
                    }
                    else if (item.Production.Head != grammar.AugmentedStart)
                    {
                        // 归约动作。
                        int targetIndex = item.Production.Index;
                        foreach (Terminal <T> sym in item.Forwards)
                        {
                            actions[sym.Index + Constants.TokenOffset].Add(
                                new Tuple <LRItem <T>, ParseAction>(item, ParseAction.Reduce(targetIndex)));
                        }
                    }
                    else if (item.Forwards.Contains(EndOfFile) && actions[Constants.EOFIdx].Count == 0)
                    {
                        // 接受动作。
                        actions[Constants.EOFIdx].Add(new Tuple <LRItem <T>, ParseAction>(item, ParseAction.Accept));
                    }
                }
                // 生成 GOTO 转换。
                int[] gotos = new int[gotoCnt];
                foreach (NonTerminal <T> sym in grammar.NonTerminals)
                {
                    int state;
                    if (!itemset.Goto.TryGetValue(sym, out state))
                    {
                        state = Constants.DeadState;
                    }
                    gotos[sym.Index] = state;
                }
                string[] originRules = new string[itemset.Items.Count];
                for (int j = 0; j < originRules.Length; j++)
                {
                    originRules[j] = itemset.Items[j].ToString();
                }
                this.states[i] = new StateData(ResolveActions(grammar, i, actions), gotos, originRules);
            }
        }
Beispiel #5
0
 /// <summary>
 /// 使用指定的产生式和动作初始化 <see cref="ParserConflictItem"/> 结构的新实例。
 /// </summary>
 /// <param name="production">产生冲突的产生式。</param>
 /// <param name="action">冲突的动作。</param>
 public ParserConflictItem(string production, ParseAction action)
 {
     this.production = production;
     this.action     = action;
 }