使用无上下文语法

时间:2016-01-18 22:31:13

标签: parsing boolean context-free-grammar

我正在尝试为个人项目编写一个简单的解析器。作为一个开始练习,我试图编写评估简单布尔语句的代码。例如,如果我给解析器以下字符串:

true AND (true OR false)

它应该返回true。

我的理解是,定义无上下文语法是编写解析器的第一步。定义适合我的简单布尔语句的上下文无关语法很容易:

S => S OR S
S => S AND S
S => (S)
S => true
S => false

但是,我不明白下一步。如何使用此语法开始评估语句?我完全走错了路吗?

1 个答案:

答案 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 }}