簡體   English   中英

語法為Lex / Yacc

[英]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:=13a=13 可以打印出syntax error消息。 由於這不會嘗試對表達式做更多的事情來識別不符合語法的表達式,因此這是我們所能做的最好的事情。

暫無
暫無

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

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