簡體   English   中英

flex和bison:解析不帶引號的字符串

[英]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:甚至是更寬容的東西; 如我所說,描述不是很精確。 清楚的是:

  • 關鍵字不區分大小寫,因此TITLEtitle都可以相同地工作,並且
  • =號是強制性的,並且在其兩側都不能有空格。 (因此,您的TITLE=行不正確,但可能沒關系)。

為了不干擾數據的解析,您可能希望使上面的單個“令牌”成為其值,該令牌是=后面的部分,並且其類型對應於(區分大小寫)關鍵字。 當然,每個參數類型可能都需要特異值解析器,這只能通過使用開始條件在flex實現。 無論如何,您都應該考慮TITLE中不屬於STRING模式的流浪字符的后果,以及如何建議解決由此產生的詞法錯誤。


您的代碼不清楚,您如何將文本值從詞法分析器傳遞到解析器。 您需要注意, yytext的值僅在詞法分析器操作內部對其對應的標記是安全的。 下次對詞法分析器的調用將使它無效,並且野牛解析器幾乎總是具有前瞻標記,因此將在處理該標記之前再次調用詞法分析器。 因此,您必須復制yytext才能將其傳遞給解析器,並且解析器需要獲得副本的所有權,以免最終導致內存泄漏。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM