[英]Grammar to Lex/Yacc
我的任務是讓我參加一個語法(BNF形式)並創建一個詞法掃描器(使用lex)和一個解析器(使用bison)的項目。 我從來沒有使用過這些程序,我認為一個很好的參考將是看如何從語法中創建這些項目。 我正在尋找一種語法,並且它與.l和.ypp文件相關聯,最好在C ++中。 我已經能夠找到示例文件或示例語法,但不能同時找到它們。 我花了一些時間搜索,但找不到任何東西。 我想在此發布信息,希望有人對我有所幫助,但在此期間我將繼續搜索。
我目前正在閱讀湯姆·尼曼(Tom Niemann)的http://epaperpress.com/lexandyacc/download/LexAndYaccTutorial.pdf ,該書寫得不錯,可以理解。
謝謝
編輯:我還在搜索,我開始認為我在尋找什么不存在。 Google通常不會讓我失望!
編輯2:也許,如果我提供一些語法,您可能會告訴我適當的.l和.ypp文件是什么樣子。 這只是語法的一小段,我只需要對它的工作原理有一點“品味”,我想我可以從那里學到它。
語法:
Program ::= Compound
Statements ::= Compound | Assignment | ...
Assignment ::= Var ASSIGN Expression
Expression ::= Var | Operator Expression Expression | Number
Compound := START Statements END
Number ::= NUMBER
說明:
Assignment is the equal sign ":="
Var is an identifier that begins with a lower case letter and is followed by lower case letters or digits
START is the "start" keyword
END is the "end keyword
Operator is "+", "-", "*", "/"
Number is decimal digits which could potentially be negative (minus sign in front)
其中大多數是相當簡單的。 但是,其中一部分無疑是有問題的。 您已經定義了一個數字(可能)包括前導-
,這是一個問題。
問題很簡單。 給定類似321-123
的輸入,詞法分析器(通常不會跟蹤當前狀態)基本上不可能猜測這應該是兩個標記( 321
和-123
還是三個321
, -
, 123
)。 在這種情況下, -
幾乎可以肯定要與123
分開,但是如果輸入為321 + -123
,則顯然希望將-123
替換為單個標記。
為了解決這個問題,您可能需要更改語法,以使開頭-
不在數字中。 相反,您始終希望將-
視為運算符,並且數字本身僅由數字組成。 然后由解析器來整理表達式,其中-
是一元還是二進制。
考慮到這一點,lexer文件將如下所示:
%{
#include "y.tab.h"
%}
%option noyywrap case-insensitive
%%
:= { return ASSIGN; }
start { return START; }
end { return END; }
[+/*] { return OPERATOR; }
- { return MINUS; }
[0-9]+ { return NUMBER; }
[a-z][a-z0-9]* { return VAR; }
[ \r\n] { ; }
%%
void yyerror(char const *s) { fputs(s, stderr); }
匹配的yacc文件如下所示:
%token ASSIGN START END OPERATOR MINUS NUMBER VAR
%left '-' '+' '*' '/'
%%
program : compound
statement : compound
| assignment
;
assignment : VAR ASSIGN expression
;
statements :
| statements statement
;
expression : VAR
| expression OPERATOR expression
| expression MINUS expression
| value
;
value: NUMBER
| MINUS NUMBER
;
compound : START statements END
%%
int main() {
yyparse();
return 0;
}
注意:我僅對這些進行了極少的測試-足以驗證我認為是語法上的輸入,例如: start a:=1 b:=2 end
and start a:=1+3*3 b:=a+4 c:=b*3 end
被接受(未打印出錯誤消息)並且我認為輸入不符合語法要求,例如: 9:=13
和a=13
都可以打印出syntax error
消息。 由於這不會嘗試對表達式做更多的事情來識別不符合語法的表達式,因此這是我們所能做的最好的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.