You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决Bison解析器中HTTP头语法的移进/归约冲突

处理HTTP头字段Bison语法的移进/归约冲突

在为HTTP定义Bison语法时,处理头字段值末尾的可选空白时遇到多处移进/归约冲突,以下是仅处理头字段部分的简化语法:

%{
  #define YYDEBUG 1
  int yylex(void);
  void yyerror(char *s);
%}
%token X00
%%
/* Reference - RFC 7230 */

headerField : fieldName ':' OWS fieldValue OWS CRLF | fieldName ':' OWS CRLF ;

fieldValue : fieldValueSS | fieldValue fieldValueSS ;

fieldValueSS : fieldContent | obsFold ; 

fieldContent : fieldVChar optFieldContent ;

optFieldContent : /* empty */ | RWS fieldVChar ;

fieldVChar : obsText | VCHAR ;

/* Even though this line fold is obsolete still account for it for consistency with the RFC */
obsFold : CRLF RWS ;

fieldName : token ;

token : tChar | token tChar ;

tChar : '!' | '#' | '$' | '%' | '&' | '\\x27' | '*' | '+' | '-' | '.' | '^' | '_' | '`' | '|' | '~' | DIGIT | ALPHA ;

obsText :     r__1 ;

/* Tokens */
ALPHA : LOALPHA | UPALPHA ;

LOALPHA :     r__2 ;

UPALPHA :     r__3 ;

DIGIT :     r__4 ;

SP : '\\x20' ;

HTAB : '\\x09' ;

WS : SP | HTAB ;

OWS : /* empty */ | OWS WS ;

RWS : WS | RWS WS ;

VCHAR :     r__5 ;

LF : '\\x0a' ;

CR : '\\x0d' ;

CRLF : CR LF ;

/* Range Expansions */
r__1 : 
  '\\x80' | '\\x81' | '\\x82' | '\\x83' | '\\x84' | '\\x85' | '\\x86' | '\\x87' | 
  '\\x88' | '\\x89' | '\\x8a' | '\\x8b' | '\\x8c' | '\\x8d' | '\\x8e' | '\\x8f' | 
  '\\x90' | '\\x91' | '\\x92' | '\\x93' | '\\x94' | '\\x95' | '\\x96' | '\\x97' | 
  '\\x98' | '\\x99' | '\\x9a' | '\\x9b' | '\\x9c' | '\\x9d' | '\\x9e' | '\\x9f' | 
  '\\xa0' | '\\xa1' | '\\xa2' | '\\xa3' | '\\xa4' | '\\xa5' | '\\xa6' | '\\xa7' | 
  '\\xa8' | '\\xa9' | '\\xaa' | '\\xab' | '\\xac' | '\\xad' | '\\xae' | '\\xaf' | 
  '\\xb0' | '\\xb1' | '\\xb2' | '\\xb3' | '\\xb4' | '\\xb5' | '\\xb6' | '\\xb7' | 
  '\\xb8' | '\\xb9' | '\\xba' | '\\xbb' | '\\xbc' | '\\xbd' | '\\xbe' | '\\xbf' | 
  '\\xc0' | '\\xc1' | '\\xc2' | '\\xc3' | '\\xc4' | '\\xc5' | '\\xc6' | '\\xc7' | 
  '\\xc8' | '\\xc9' | '\\xca' | '\\xcb' | '\\xcc' | '\\xcd' | '\\xce' | '\\xcf' | 
  '\\xd0' | '\\xd1' | '\\xd2' | '\\xd3' | '\\xd4' | '\\xd5' | '\\xd6' | '\\xd7' | 
  '\\xd8' | '\\xd9' | '\\xda' | '\\xdb' | '\\xdc' | '\\xdd' | '\\xde' | '\\xdf' | 
  '\\xe0' | '\\xe1' | '\\xe2' | '\\xe3' | '\\xe4' | '\\xe5' | '\\xe6' | '\\xe7' | 
  '\\xe8' | '\\xe9' | '\\xea' | '\\xeb' | '\\xec' | '\\xed' | '\\xee' | '\\xef' | 
  '\\xf0' | '\\xf1' | '\\xf2' | '\\xf3' | '\\xf4' | '\\xf5' | '\\xf6' | '\\xf7' | 
  '\\xf8' | '\\xf9' | '\\xfa' | '\\xfb' | '\\xfc' | '\\xfd' | '\\xfe' | '\\xff' ;
r__2 : 
  '\\x61' | '\\x62' | '\\x63' | '\\x64' | '\\x65' | '\\x66' | '\\x67' | '\\x68' | 
  '\\x69' | '\\x6a' | '\\x6b' | '\\x6c' | '\\x6d' | '\\x6e' | '\\x6f' | '\\x70' | 
  '\\x71' | '\\x72' | '\\x73' | '\\x74' | '\\x75' | '\\x76' | '\\x77' | '\\x78' | 
  '\\x79' | '\\x7a' ;
r__3 : 
  '\\x41' | '\\x42' | '\\x43' | '\\x44' | '\\x45' | '\\x46' | '\\x47' | '\\x48' | 
  '\\x49' | '\\x4a' | '\\x4b' | '\\x4c' | '\\x4d' | '\\x4e' | '\\x4f' | '\\x50' | 
  '\\x51' | '\\x52' | '\\x53' | '\\x54' | '\\x55' | '\\x56' | '\\x57' | '\\x58' | 
  '\\x59' | '\\x5a' ;
r__4 : 
  '\\x30' | '\\x31' | '\\x32' | '\\x33' | '\\x34' | '\\x35' | '\\x36' | '\\x37' | 
  '\\x38' | '\\x39' ;
r__5 : 
  '\\x21' | '\\x22' | '\\x23' | '\\x24' | '\\x25' | '\\x26' | '\\x27' | '\\x28' | 
  '\\x29' | '\\x2a' | '\\x2b' | '\\x2c' | '\\x2d' | '\\x2e' | '\\x2f' | '\\x30' | 
  '\\x31' | '\\x32' | '\\x33' | '\\x34' | '\\x35' | '\\x36' | '\\x37' | '\\x38' | 
  '\\x39' | '\\x3a' | '\\x3b' | '\\x3c' | '\\x3d' | '\\x3e' | '\\x3f' | '\\x40' | 
  '\\x41' | '\\x42' | '\\x43' | '\\x44' | '\\x45' | '\\x46' | '\\x47' | '\\x48' | 
  '\\x49' | '\\x4a' | '\\x4b' | '\\x4c' | '\\x4d' | '\\x4e' | '\\x4f' | '\\x50' | 
  '\\x51' | '\\x52' | '\\x53' | '\\x54' | '\\x55' | '\\x56' | '\\x57' | '\\x58' | 
  '\\x59' | '\\x5a' | '\\x5b' | '\\x5c' | '\\x5d' | '\\x5e' | '\\x5f' | '\\x60' | 
  '\\x61' | '\\x62' | '\\x63' | '\\x64' | '\\x65' | '\\x66' | '\\x67' | '\\x68' | 
  '\\x69' | '\\x6a' | '\\x6b' | '\\x6c' | '\\x6d' | '\\x6e' | '\\x6f' | '\\x70' | 
  '\\x71' | '\\x72' | '\\x73' | '\\x74' | '\\x75' | '\\x76' | '\\x77' | '\\x78' | 
  '\\x79' | '\\x7a' | '\\x7b' | '\\x7c' | '\\x7d' | '\\x7e' ;

查看生成的.output文件,状态321存在2处移进/归约冲突:

State 321

    7 fieldContent: fieldVChar • optFieldContent

    ' '   shift, and go to state 109
    '\\t'  shift, and go to state 110

    ' '       [reduce using rule 8 (optFieldContent)]
    '\\t'      [reduce using rule 8 (optFieldContent)]
    $default  reduce using rule 8 (optFieldContent)

    optFieldContent  go to state 335
    SP               go to state 324
    HTAB             go to state 325
    WS               go to state 336
    RWS              go to state 337

冲突原因:读取若干可见字符后遇到空白时,解析器无法判断是继续累积fieldVChar字符还是归约空的optFieldContent。

状态340同样存在2处移进/归约冲突:

State 340

   12 obsFold: CRLF RWS •
   46 RWS: RWS • WS

    ' '   shift, and go to state 109
    '\\t'  shift, and go to state 110

    ' '       [reduce using rule 12 (obsFold)]
    '\\t'      [reduce using rule 12 (obsFold)]
    $default  reduce using rule 12 (obsFold)

    SP    go to state 324
    HTAB  go to state 325
    WS    go to state 343 

冲突原因:接收CRLF和至少一个空白令牌后,当收到另一个空白令牌时,解析器无法判断是继续累积空白还是归约已完成的obsFold规则。

尝试过的修复方法

方法1:整合optFieldContent到fieldContent

尝试禁用空optFieldContent并将其整合到fieldContent规则中:

fieldContent : fieldVChar | fieldVChar fieldContentSS ;

fieldContentSS : RWS fieldVChar ;

结果:未解决冲突。

方法2:拆分带obsFold和不带obsFold的字段值规则

为包含obsFold和不包含obsFold的字段值分别定义规则:

headerField : fieldName ':' OWS fieldValueWS CRLF | fieldName ':' OWS CRLF | fieldName ':' OWS fieldValue OWS CRLF ;

fieldValue : fieldValueSS | fieldValue fieldValueSS ;

fieldValueSS : fieldContent ; 

fieldValueWS : fieldValueSSWS | fieldValueWS fieldValueSSWS ;

fieldValueSSWS : fieldContent | obsFold ; 

结果:解决了移进/归约冲突,但引发大量归约/归约冲突,解析器无法判断归约fieldValueSSWS还是fieldValueSS。


内容的提问来源于stack exchange,提问作者Josh Meise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 18:55:54