Datetime 使用YACC shift的日期时间分析器减少冲突

Datetime 使用YACC shift的日期时间分析器减少冲突,datetime,yacc,shift-reduce-conflict,Datetime,Yacc,Shift Reduce Conflict,我有下面的YACC解析器 %start Start %token _DTP_LONG // Any number; Max upto 4 Digits. %token _DTP_SDF // 17 Digit number indicating SDF format of Date Time %token _DTP_EOS // end of input %token

我有下面的YACC解析器

%start          Start

%token          _DTP_LONG         // Any number; Max upto 4 Digits.  
%token          _DTP_SDF          // 17 Digit number indicating SDF format of Date Time
%token          _DTP_EOS          // end of input
%token          _DTP_MONTH        //Month names e.g Jan,Feb

%token          _DTP_AM            //Is A.M
%token          _DTP_PM            //Is P.M
%%


Start           :   DateTimeShortExpr
                |   DateTimeLongExpr

                |   SDFDateTimeExpr EOS
                |   DateShortExpr EOS
                |   DateLongExpr EOS
                |   MonthExpr EOS
                ;

DateTimeShortExpr   :  DateShortExpr TimeExpr   EOS         {;}
                    |  DateShortExpr AMPMTimeExpr   EOS     {;}
                    ;


DateTimeLongExpr    :  DateLongExpr TimeExpr EOS           {;}
                    |  DateLongExpr AMPMTimeExpr EOS       {;}
                    ;

DateShortExpr   :  Number                                                          {                                       rc = vDateTime.SetDate ((Word) $1,  0,  0);
                                                                    }   


                |  Number Number                                {     rc = vDateTime.SetDate ((Word) $1, (Word) $2,  0); }


                |  Number Number Number                    {     rc = vDateTime.SetDate ((Word) $1, (Word) $2, (Word) $3); }

                ;

DateLongExpr        :   Number AbsMonth                    {     // case : number greater than 31, consider as year
                                                                     if ($1 > 31) {
                                                                        rc = vDateTime.SetDateFunc (1, (Word) $2, (Word) $1);

                                                            }
                                                            // Number is considered as days
                                                            else {
                                                                   rc = vDateTime.SetDateFunc ((Word) $1, (Word) $2,  0);
                                                                 }
                                                            }

                |   Number AbsMonth Number              {rc = vDateTime.SetDateFunc((Word) $1, (Word) $2, (Word) $3);}


                ;                                 

TimeExpr        :   Number                                      {     rc = vDateTime.SetTime ((Word) $1,  0,  0);}

                |   Number Number                               {     rc = vDateTime.SetTime ((Word) $1, (Word) $2,  0); }

                |   Number Number Number                    {     rc = vDateTime.SetTime ((Word) $1, (Word) $2, (Word) $3); }
                ;                                                                                    


AMPMTimeExpr    : TimeExpr _DTP_AM                     {     rc = vDateTime.SetTo24hr(TP_AM)     ; }

                | TimeExpr _DTP_PM                     {     rc = vDateTime.SetTo24hr(TP_PM)     ; }

                | _DTP_AM TimeExpr                     {     rc = vDateTime.SetTo24hr(TP_AM)     ; }

                | _DTP_PM TimeExpr                     {     rc = vDateTime.SetTo24hr(TP_PM)     ; }
                ;


SDFDateTimeExpr   : SDFNumber                          { rc = vDateTime.SetSDF ($1);}

               ;

MonthExpr           : AbsMonth                         {     rc = vDateTime.SetNrmMth ($1);}

                   | AbsMonth Number                   {     rc = vDateTime.Set ($1,$2);}
                ;           

Number              : _DTP_LONG                               {     $$ = $1; }
                ;               

SDFNumber           : _DTP_SDF                              {     $$ = $1; }
                ;               

EOS                 : _DTP_EOS                              {     $$ = $1; }
                ;

AbsMonth            : _DTP_MONTH                            {      $$ = $1;  }
                ;               
%%


它给出了三个移位-减少冲突。我如何删除它们???

移位-减少冲突是语法描述的“小语言”所固有的。考虑输入令牌流< /P>
_DTP_LONG _DTP_LONG _DTP_LONG EOS
每个
\u DTP\u LONG
可以减少为一个
数字
。但是应该

Number Number Number
是否减少为1号
DateShortExpr
后接2号
TimeExpr
或2号
DateShortExpr
后接1号
TimeShortExpr
?这种模糊性是内在的

如果可能的话,可以通过添加其他符号来重新设计您的语言,以区分日期和时间——例如,冒号表示时间的各个部分,斜杠表示日期的各个部分

更新

我不认为您可以在这里使用yacc/bison的特性,因为标记是无法区分的

当yacc/bison遇到一个问题时,您必须依赖它的默认行为,也就是说,改变而不是减少。在输出中考虑这个例子:

+-------------------------     STATE 9     -------------------------+

+ CONFLICTS:

? sft/red (shift & new state 12, rule 11) on _DTP_LONG

+ RULES:

  DateShortExpr :  Number^    (rule 11)
  DateShortExpr :  Number^Number
  DateShortExpr :  Number^Number Number
   DateLongExpr :  Number^AbsMonth
   DateLongExpr :  Number^AbsMonth Number

+ ACTIONS AND GOTOS:

      _DTP_LONG : shift & new state 12
     _DTP_MONTH : shift & new state 13
                : reduce by rule 11

         Number : goto state 26
       AbsMonth : goto state 27
解析器将要做的是移位并应用规则12,而不是按规则11减少(
DateShortExpr:Number
)。这意味着解析器永远不会将单个
数字
解释为
DateShortExpr
;它总是会改变的


依赖默认行为的一个困难是,当您修改语法时,默认行为可能会发生变化。

您能指出在哪里会发生这种情况吗?另外,请花一些时间格式化您的代码。@leppie:这是lrt文件,我不想让用户放置指定的分隔符……我知道它是内置的,但我们可以通过应用某种优先级来抑制它们吗