簡體   English   中英

如何在我自己的解析器中使用flex?

[英]How to use flex with my own parser?

我想將詞法分析留給詞法分析,但自己開發解析器。

我制作了一個token.h標頭,其中包含令牌類型的枚舉和簡單的類層次結構,

對於lex規則:

[0-9]+ {yylval = new NumToken(std::stoi(yytext));return NUM;}

如何從解析器代碼中獲取NumToken指針? 假設我只想打印出令牌。

while(true)
{
    auto t = yylex();
    //std::cout <<yylval.data<<std::endl; // What goes here ?
}

我可以使用yacc / bison進行此操作,但是找不到有關如何手動執行此操作的任何文檔或示例。

在傳統的bison / flex解析器中, yylval是在bison生成的解析器中定義的全局變量,並在bison生成的頭文件中聲明(應在包含在生成的掃描器中#include)。 因此,一個簡單的解決方案就是復制它:在token.h聲明yylval (作為全局token.h並在解析器中的某個位置定義它。

但是現代編程風格已經從使用全局變量轉變了(有充分的理由),實際上,如果需要,甚至flex也會生成不依賴於全局狀態的掃描程序。 要請求這樣的掃描儀,請指定

%option reentrant

在您的掃描儀定義中。 默認情況下,這會將yylex的原型更改為:

int yylex(yyscan_t yyscanner);

其中yyscan_t是不透明的指針。 (這是C,所以意味着它是一個void* 。)您可以在Flex手冊中閱讀有關細節; 最重要的要點是,您可以要求flex還生成一個頭文件(帶有%option header-file ),以便其他翻譯單元可以引用各種函數來創建,銷毀和操作yyscan_t ,並且您需要最少創建一個,以便yylex在某處存儲其狀態。 (理想情況下,您也將其銷毀。)[注1]。

使用掃描儀折返從預期的方式bison是啟用%option bison-bridge (和%option bison-location ,如果你的詞法分析器每個令牌生成源位置信息)。 這將為yylex原型添加一個附加參數:

int yylex(YYSTYPE *yylval_param, yyscan_t scanner);

使用`%option bison-locations',添加了兩個參數:

int yylex(YYSTYPE *yylval_param,
          YYLTYPE *yylloc_param,
          yyscan_t scanner);

flex生成的代碼聲明語義類型YYSTYPE和位置類型YYLTYPE 它們必須出現在您#include到掃描儀中的token.h標頭中。

野牛橋參數的目的是提供一種將語義值yylval返回給調用方(即解析器)的機制。 由於yylval實際上與參數yylval_param [注2]相同,因此它將是指向實際語義值的指針 ,因此您需要在flex動作中編寫(例如) yylval->data = ...

所以這是做到這一點的一種方法。

替代bison-bridge一種可能更簡單的選擇是僅提供您自己的yylex原型,您可以使用宏YY_DECL 例如,您可以執行以下操作(如果YYSTYPE很簡單):

#define YY_DECL std::pair<int, YYSTYPE> yylex(yyscan_t yyscanner)

然后一條規則可以返回該對:

[0-9]+ {return std::make_pair(NUM, new NumToken(std::stoi(yytext));}

顯然,此主題有很多變體。


筆記

  1. 不幸的是,生成的標頭包含很多不必要的包,,包括一堆用於標准“全局變量”的宏定義,這些宏定義將不起作用,因為在可重入的掃描器中,這些變量只能在flex動作中使用。

  2. bison-bridge生成的掃描器將yylval定義為一個宏,該宏引用不透明狀態結構中的一個字段,並將yylval_param存儲到該字段中。 yyget_lvalyyset_lval函數是為了從yylex外部獲取或設置此字段。 我不知道為什么; 似乎介於不必要和危險之間,因為狀態將包含指向 yylex調用中提供的值的指針,一旦調用返回,它很可能是懸空的指針。

暫無
暫無

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

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