这些的 Bison/yacc 语法是什么

What are the Bison/yacc grammars for these

我正在努力学习 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());}
;

%%

正在尝试解析:"var xz; var abc;"我有 2 个问题:

很难在没有更多约束或正式语法的情况下给出特定的 bison/yacc 配置。特别是你决定 "var x=" 应该是一个表达式(计算为 "x" 并且作为副作用将 "x" 添加到环境中)还是作为一个语句(在没有 return 类型的情况下计算) 或其他内容。

总的来说,你最好尝试自己编写一些没有代码生成工具支持的简单解析器。您的语言可能的语法是:

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 并且二元运算 + 在示例 "left-associative" 中,而二元运算“=”是右结合的(不是说这是个好主意,只是说这是许多可能的机会之一)。

你可能可以在一两个下午编写解析器、类型检查器和此类语法的评估器(也许一个虚拟机可以在一周内加速整个过程),但首先你需要有一个精确的想法你的语言应该如何工作。 值得注意的是,代码生成工具并不是灵丹妙药,特别是如果您无法正确编写自己的解析器或无法自行制定语法,那么在使用代码生成器时您可能会遇到更多问题,因为他们隐藏了很多细节并增加了额外的复杂性。

我认为 Whosebug 不是完整介绍编写上下文无关语法的合适论坛,但也许这足以让您入门。

一个语法由许多规则组成,每个规则的形式都是 "An X can be an a followed by a b followed by …"。这些规则可以是递归,这是表达任意重复等概念的唯一方式。换句话说,因为我们不能说"A list is any number of _expression_s separated by _Comma_s",所以我们说的是:"A list can be an expression, or it can be a list followed by a Comma followed by an expression." 我们通常这样写:

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 */

注意用','表示"a comma"。在野牛中,您不必为由单个字符组成的标记想出名称;您可以简单地在引号中使用字符本身。 (在 flex 中,对于 return 那个标记,你做同样的事情:{ 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 

现在,"program" 也是一个语句列表,但是由于语句以分号结束,所以列表中不需要任何标点符号。这是一个微不足道的区别:

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

这里还有很多内容需要填写(例如,expression),但希望这能给您一些想法。