[英]flex and bison: parse string without quotes
我正在使用flex + bison c ++開發mgf文件解析器(語法: http : //www.matrixscience.com/help/data_file_help.html )。
我已經意識到詞法分析器(lex)和解析器(yacc)。 但是我有一個我無法解決的問題:當我嘗試解析字符串時。
重要提示:字符串周圍沒有'或'。
這是輸入示例:
CHARGE=1+, 2+ and 3+
#some comments
BEGIN IONS
TITLE= Cmpd 1, +MSn(417.2108), 10.0 min //line 20
PEPMASS=417.21083 35173
CHARGE=3+
123.79550 20
285.16455 56
302.14335 146 1+
[other datas ...]
END IONS
BEGIN IONS
[an other one ... ]
這里(最小)詞法分析器:MGF_TOKEN_DEBUG是用於打印行的宏
#define MGF_TOKEN_DEBUG(val) std::cout<<"token: "<<val<<std::endl
\n {
MGF_TOKEN_DEBUG("T_EOL");
return token::T_EOL;
}
^[#;!/][^\n]* {
MGF_TOKEN_DEBUG("T_COMMENT");
return token::T_COMMENT;
}
[[:space:]] {}
/** values **/
[0-9]+ {
MGF_TOKEN_DEBUG("V_INTEGER"<<" (="<<yytext<<")");
return token::V_INTEGER;
}
[0-9]+"."[0-9]* {
MGF_TOKEN_DEBUG("V_DOUBLE"<<" (="<<yytext<<")");
return token::V_DOUBLE;
}
[0-9]+("."[0-9]+)?[eE][+-][0-9]+ {
MGF_TOKEN_DEBUG("V_DOUBLE"<<" (="<<yytext<<")");
return token::V_DOUBLE;
}
"+" {
MGF_TOKEN_DEBUG("T_PLUS");
return token::T_PLUS;
}
"=" {
MGF_TOKEN_DEBUG("T_EQUALS");
return token::T_EQUALS;
}
"," {
MGF_TOKEN_DEBUG("T_COMA");
return token::T_COMA;
}
"and" {
MGF_TOKEN_DEBUG("T_AND");
return token::T_AND;
}
/*** keywords */
^"CHARGE" {
MGF_TOKEN_DEBUG("K_CHARGE");
return token::K_CHARGE;
}
^"TITLE" {
MGF_TOKEN_DEBUG("K_TITLE");
return token::K_TITLE;
}
[ others keywords ...]
/**** string : problem here **/
[A-Za-z]([:;,()A-Za-z0-9_.-]|[[:space]])* {
MGF_TOKEN_DEBUG("V_STRING"<<" (="<<yytext<<")");
return token::V_STRING;
}
還有(最小化的)解析器。
start : headerparams blocks T_END;
headerparams : /* empty */| headerparams headerparam;
headerparam : K_CHARGE T_EQUALS charge_list T_EOL | [others ...];
blocks : /* empty */ | blocks block;
block : T_BEGIN_IONS T_EOL blockparams ions T_END_IONS T_EOL| T_BEGIN_IONS T_EOL blockparams T_END_IONS T_EOL;
blockparam : K_CHARGE T_EQUALS charge T_EOL | K_TITLE T_EQUALS V_STRING T_EOL | [others...];
ion : number number T_EOL| number number charge T_EOL;
ions : ions ion| ion;
number : V_INTEGER | V_DOUBLE;
charge : V_INTEGER T_PLUS | V_INTEGER T_MINUS;
charge_list : charge| charge_list T_COMA charge | charge_list T_AND charge;
我的問題是我得到了下一個令牌:
[...]
[line 20]
token: K_TITLE
token: T_EQUALS
token: v_STRING (= Cmpd)
token: V_INTEGER (= 1)
Error line 20: syntax error, unexpected integer, expecting end of line
我想擁有:
[...]
[line 20]
token: K_TITLE
token: T_EQUALS
token: v_STRING (Cmpd 1, +MSn (417.2108), 10.0 min)
token: T_EOL
如果有人可以幫助我...
編輯#1我已經使用令牌串聯來“解決”問題:
法:
[A-Za-z][^\n[:space:]+-=,]* {
MGF_TOKEN_DEBUG("V_STRING"<<" (="<<yytext<<")"))
return token::V_STRING;t
}
YACC:
string_st : V_STRING
| string_st V_STRING
| string_st number
| string_st T_COMA
| string_st T_PLUS
| string_st T_MINUS
;
blockparam : K_CHARGE T_EQUALS charge T_EOL | K_TITLE T_EQUALS string_st T_EOL | [others...];
如果您的字符串始終以TITLE
開頭,以\\n
結尾(換行符)
我建議您使用開始條件 ,
%x IN_TITLE
"TITLE" { /* return V_STRING of TITILE in c++ code */ BEGIN(IN_TITLE); }
<IN_TITLE>= { /* return T_EQUALS in c++ code */; }
<IN_TITLE>"\n" { BEGIN(INITIAL); }
<IN_TITLE>.* { MGF_TOKEN_DEBUG("V_STRING"<<" (="<<yytext<<")");return token::V_STRING; }
%x IN_TITLE
定義了IN_TITLE
狀態,模式文本TITLE
將使其開始。 一旦啟動, \\n
將使其返回初始狀態(已預定義了INITIAL),並且所有其他字符將被消耗到V_STRING
而無需任何特殊操作。
您的基本問題是一個簡單的錯字:
[A-Za-z]([:;,()A-Za-z0-9_.-]|[[:space]])*
應該:
[A-Za-z]([:;,()A-Za-z0-9_.-]|[[:space:]])*
^
您實際上不需要|
運營商。 以下內容完全合法(但也可能不是您想要的;請參閱下文):
[A-Za-z][[:space:]:;,()A-Za-z0-9_.-]*
解決此問題后,您會發現還有另一個問題:由於STRING
模式更長,因此您的關鍵字(例如TITLE
)將被歸類為STRING
。 (實際上,由於[:space:]
包含\\n
,因此STRING
模式可能會擴展到輸入的末尾。您可能想要[:blank:]
。)
我快速瀏覽了您要解析的格式的描述,但這不是一個非常精確的描述。 但似乎參數行具有以下格式:
^[[:alpha:]]+=.*$
也許:alpha:
應該是:alnum:
甚至是更寬容的東西; 如我所說,描述不是很精確。 清楚的是:
TITLE
和title
都可以相同地工作,並且 =
號是強制性的,並且在其兩側都不能有空格。 (因此,您的TITLE=
行不正確,但可能沒關系)。 為了不干擾數據的解析,您可能希望使上面的單個“令牌”成為其值,該令牌是=
后面的部分,並且其類型對應於(區分大小寫)關鍵字。 當然,每個參數類型可能都需要特異值解析器,這只能通過使用開始條件在flex
實現。 無論如何,您都應該考慮TITLE
中不屬於STRING
模式的流浪字符的后果,以及如何建議解決由此產生的詞法錯誤。
您的代碼不清楚,您如何將文本值從詞法分析器傳遞到解析器。 您需要注意, yytext
的值僅在詞法分析器操作內部對其對應的標記是安全的。 下次對詞法分析器的調用將使它無效,並且野牛解析器幾乎總是具有前瞻標記,因此將在處理該標記之前再次調用詞法分析器。 因此,您必須復制yytext
才能將其傳遞給解析器,並且解析器需要獲得副本的所有權,以免最終導致內存泄漏。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.