问题描述
我想解析/存储以下序列:Ann {* some arbitrary long sequence *}
我的缓冲区长度(YYLMAX)设置为8K。鉴于序列可以是任意长,我尝试通过这种方式做到这一点:
- 搜索
Ann
令牌,后跟{*
。看到后进入ANN
状态。 - 处于
ANN
状态时,一次读取一个字符,直到YYLMAX-1。将此令牌返回给YACC,YACC将其复制/追加到C ++字符串缓冲区(动态增加)。 - 重复步骤(2),直到看到
*}
。此时将状态设置为INITIAL(0)。
对于小序列(小于8K),我的代码可以正常工作。但是,如果序列超过8K,则第一个 grab 可以正常工作,但是由于它与annotation_text
规则匹配,因此词法分析器似乎将状态重置为INITIAL。因此,当我继续阅读序列中的下一个字符时,由于词法分析器规则ANN[^*]
不再匹配,最终导致解析错误。我想避免这种情况,并保持在ANN
状态,直到读取完整的序列,直到看到*}
。实施此行为的正确方法是什么?一个示例示例会有所帮助。
我不想增加YYLMAX的长度,因为我事先不知道Ann {* ... *}
块中序列的最大长度。
谢谢您的任何想法。
我的YACC语法的相关代码段如下所示:
string curr_annotation = "{*";
annotation : _STIL_ANN _STIL_ANN_LCURLY annotation_text _STIL_ANN_RCURLY
{
curr_annotation += "*}";
std::cout << "Going to add annotation '" << curr_annotation << "'" << std::endl;
p_block->addAnn(curr_annotation,stil_yylineno);
curr_annotation = "{*";
}
;
annotation_text : _STIL_ANN_TEXT
{
std::cout << "appending to annotation" << std::endl;
curr_annotation += $1;
}
| annotation_text _STIL_ANN_TEXT
;
我的LEXER的相关代码段如下所示:
WHITESPACE [ \t\n\r]
START_BLK_ANN {WHITESPACE}*"{*"
END_BLK_ANN "*}"
...
<ANN>{START_BLK_ANN} { printf("match1\n");
TRACE(("<ANN>START_BLK_ANN <%s> \n",yytext));
return(token(_STIL_ANN_LCURLY));
}
<ANN>{END_BLK_ANN} { printf("match2\n"); TRACE(("<ANN>END_BLK_ANN <%s> \n",yytext));
BEGIN 0;
return(token(_STIL_ANN_RCURLY));
}
<ANN>[^*] { printf("match3\n"); yylval.string = stiltok_grab_annotation();
TRACE(("ANN_TEXT <%s> \n",yylval.string));
return(token(_STIL_ANN_TEXT));
}
{IDENTIFIER} {
printf("got here\n");
temp_sym_name = yytext;
tokVal = stiltoktbl.locatetoken(temp_sym_name);
yylval.string = yytext;
if (tokVal != UNDEFINED_TOKEN) {
if (tokVal == _STIL_USER_KEYWORD) {
BEGIN USERKW;
TRACE(("USER_KEYWORD <%s> \n",yytext));
}
else if (tokVal == _STIL_Include) {
TRACE(("INCLUDE \n"));
BEGIN INCLUDE;
return(token(_STIL_INCLUDE));
}
else if (tokVal == _STIL_Ann) {
TRACE(("ANN \n"));
BEGIN ANN; <== Ann Token seen switch state.
return(token(_STIL_ANN));
}
else {
TRACE(("KEYWORD <%s> \n",yytext));
}
return(tokVal);
}
else {
TRACE(("IDENTIFIER <%s> \n",yytext));
return(token(_STIL_IDENTIFIER));
}
stiltok_grab_annotation
看起来像这样:
char * stiltok_grab_annotation() {
TRACEID("stiltok_grab_annotation",SEV_4);
char * p_ann_begin = yytext; // point past "{*" prefix
char * p_ann_end = p_ann_begin + 1;
char c1 = yyinput();
char c2 = yyinput();
*(p_ann_end++) = c1;
*(p_ann_end++) = c2;
while ( c1 != '*' || c2 != '}') {
c1 = c2;
c2 = yyinput();
*(p_ann_end++) = c2;
if ((p_ann_end - yytext) == (MAX_TOKEN_LENGTH-1)) {
break;
}
}
*(p_ann_end) = '\0'; // place the string terminator at end after "*}" suffix
// Return '*}' token to the lexer
if ( c1 == '*' && c2 == '}' ) {
*(p_ann_end-2) = '\0';
yyunput(c2,yytext);
yyunput(c1,yytext);
}
return p_ann_begin;
}
样品运行(只是相关的部分):
match1 <-- in ANN state,matched '{*'
Line:[58] {*
match3 <-- in ANN state,matched single character. run stiltok_grab_annotation()...
Line:[58] ...... <-- received 8K-1 characters.
appending to annotation <-- successfully copied by yacc to string buffer
got here <-- lexer has gone back to IDENTIFIER state instead of remaining in ANN state
Line:[58]D_REG55_0_18_0 <-- trouble begins
-S- Parsing error detected in file: x [stilcomyacc_perror]
-T- Syntax Error [Line: 58]
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)