什么是这些的野牛/ yacc语法

时间:2015-06-20 14:50:30

标签: grammar bison yacc

我正在尝试学习Flex / Bison和世界,如果充满计算器示例,其中一切都是表达;我正在尝试多一点:介绍" var"关键词;所以我卡住了 这就是我要解析的内容:

var x;
x = 3 + 4;
print x;

以后再将其复杂化:

var x = 2+3, y = x+5, xyz;
xyz = x + y + 3;
print xyz;

" var x ="一个像2 + 3的表情? 或者",y ="还有表达吗?

已编辑 - 已添加额外信息:

我正处于开始阶段:

%union 
{
    char *chars;
}

%token TOKEN_VAR
%token <chars> TOKEN_LITERAL
%token ';' TOKEN_SEMICOLON 

%%
input
: varStatement {;}
;

varStatement 
: TOKEN_VAR TOKEN_LITERAL TOKEN_SEMICOLON {AddStatement(new VarStatement($2));}
;

%%

尝试解析:&#34; var xz; var abc;&#34;我有两个问题:

  • $ 2始终为空
  • 解析器在var xz;
  • 之后停止

2 个答案:

答案 0 :(得分:3)

我不认为StackOverflow是完整介绍编写无上下文语法的正确论坛,但也许这足以让你开始。

语法由许多规则组成,每个规则的格式为&#34; X 可以是 a ,后跟 b < / em>接着是......&#34;。这些规则可以是递归,这是表达任意重复等概念的唯一方法。换句话说,因为我们不能说&#34; list 是由_Comma_s&#34;分隔的任意数量的_expression_s,我们所说的是:&#34; A list 可以是表达式,也可以是列表,后跟逗号,后跟表达式< /em>."我们通常写如下:

list: expression            /* A list can be an expression */
    | list ',' expression   /* or a list, a comma, and an expression */

|只是一个缩写。我们本来可以写的:

list: expression            /* A list can be an expression */
list: list ',' expression   /* or a list, a comma, and an expression */

请注意使用','代表逗号&#34;逗号&#34;。在野牛中,您不必考虑由单个字符组成的令牌的名称;你可以简单地在引号中使用字符本身。 (在flex中,为了返回该令牌,你做同样的事情:{ return ','; }。这是有效的,因为在C中,单引号字符是一个整数常量。)

对于多字符标记 - 例如var之类的关键字 - bison允许您使用双引号字符串,前提是您声明了标记名称。例如,你可以写:

/* Declare the token name and the string representation */
 %token TOKEN_VAR "var"

 %%
 var_statement: "var" declaration_list ';'
 declaration_list: declaration
                 | declaration_list ',' declaration
 declaration: IDENTIFIER
            | IDENTIFIER '=' expression 

现在,一个&#34;程序&#34;也是一个语句列表,但由于语句以分号结束,我们在列表中不需要任何标点符号。这是一个微不足道的差异:

 program: statement
        | program statement
 statement: var_statement
          | print_statement
          | assignment_statement

此处还有更多要填写的内容(例如expression),但希望能为您提供一些想法。

答案 1 :(得分:0)

HARD提供特定的野牛/ yacc配置,没有更多限制或正式语法。特别是如果“var x =”应该是一个表达式(评估为“x”并且副作用将“x”添加到环境中)或作为语句(不带返回类型的评估)或其他内容,则可以决定。

一般情况下,如果没有代码生成工具的支持,最好尽量为自己编写一些简单的解析器。您语言的可能语法是:

Statement ::= ExpStat | VarStat | PrintStat
VarStat ::= var InitializerList;
InitializerList ::= (Ident | Ident = Exp )( ,Ident | ,Ident = Exp)*
ExpStat ::= Exp
PrintStat ::= Print Exp;
Exp ::= Exp BinaryOp Exp | Number | Ident
BinaryOp ::= + | =
Number ::= [1-9]+[0-9]*
Ident ::= [a-z]*

添加附加约束时,数字必须大于或等于0且小于或等于2 ^ 32-1,二进制操作+在示例中为“左关联”,而二进制操作“=”是正确的 - 联想(不是说这是一个好主意,只是说它是许多可能的机会之一)。

你可以在一两个星期或两天内编译解析器,类型检查器和这种语法的评估器(也许是一个虚拟机,以便在一周内加速整个过程),但首先你需要对你的如何有一个精确的想法语言应该有效。 代码生成工具值得注意不要成为银弹,特别是如果你不能正确编写自己的解析器或者自己编写语法,那么在使用代码生成器时你可能会遇到更多问题,因为他们隐藏了很多细节,增加了额外的复杂性。