这些的 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 个问题:
- $2 始终为空
- 解析器在 var xz 之后停止;
很难在没有更多约束或正式语法的情况下给出特定的 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
),但希望这能给您一些想法。
我正在努力学习 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 个问题:
- $2 始终为空
- 解析器在 var xz 之后停止;
很难在没有更多约束或正式语法的情况下给出特定的 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
),但希望这能给您一些想法。