我正在尝试为个人项目编写一个简单的解析器。作为一个开始练习,我试图编写评估简单布尔语句的代码。例如,如果我给解析器以下字符串:
true AND (true OR false)
它应该返回true。
我的理解是,定义无上下文语法是编写解析器的第一步。定义适合我的简单布尔语句的上下文无关语法很容易:
S => S OR S
S => S AND S
S => (S)
S => true
S => false
但是,我不明白下一步。如何使用此语法开始评估语句?我完全走错了路吗?
答案 0 :(得分:0)
语法(bool.l)的词法定义文件可能如下所示:
%{
#include "y.tab.h"
%}
%%
"true" return TRUE;
"false" return FALSE;
"OR" return OR;
"AND" return AND;
"(" return '(';
")" return ')';
[ \t] {}
\n return 0;
. return *yytext;
%%
将输入流解析为令牌。解析器调用词法分析器,每次都返回下一个标记。也可以返回像NUMBER这样的标记,并将变量设置为读取的实际数字(对于字符串文字,标识符等也是如此)。
语法定义(bool.y):
%{
#include <stdio.h>
#include "y.tab.h"
%}
%left AND
%left OR
%token TRUE FALSE LB RB
%%
start: s { printf("Result is: %d\n", $1); }
s: s OR s { $$ = $1 || $3; }
| s AND s { $$ = $1 && $3; }
| LB s RB { $$ = $2; }
| TRUE { $$ = 1; }
| FALSE { $$ = 0; }
%%
int main (void) {
return yyparse();
}
解析器根据语法定义解析标记,并在每次规则匹配时在括号中执行代码。 $$
是规则的返回值,而$n
是第n个令牌的值。
您可以使用
进行编译yacc -d bool.y
flex bool.l
gcc -O2 y.tab.c lex.yy.c -o bool -ll -ly
并启动它:
echo false OR true | bool
或使用./bool
并在stdin上输入您的条款。
Yacc从定义文件构建LALR(1)shift / reduce-parser。
如果你想更深入地了解yacc如何生成解析器,请在生成时指定-v
选项,然后yacc会将状态机的描述(何时移位,何时降低)写入{{1 }}