C++ 是否可以使用bison/yacc的反向波兰语表示法为语言生成解析器?
是否可以使用bison/yacc为使用反向波兰符号(和类似Postscript的语法)的脚本语言生成解析器 解析器应该能够解析与以下代码类似的代码:C++ 是否可以使用bison/yacc的反向波兰语表示法为语言生成解析器?,c++,yacc,bison,C++,Yacc,Bison,是否可以使用bison/yacc为使用反向波兰符号(和类似Postscript的语法)的脚本语言生成解析器 解析器应该能够解析与以下代码类似的代码: /fib { dup dup 1 eq exch 0 eq or not { dup 1 sub fib exch 2 sub fib add } if } def 对。假设您指的是一个也使用postscript符号的表达式,这意味着您将定义表达式如下: expression: operand operand
/fib
{
dup dup 1 eq exch 0 eq or not
{
dup 1 sub fib
exch 2 sub fib
add
} if
} def
对。假设您指的是一个也使用postscript符号的表达式,这意味着您将定义表达式如下:
expression: operand operand operator
而不是更常见的中缀符号:
expression: operand operator operand
但这几乎算不上什么大事。如果你所说的“PostScript like”是指其他内容,那么在给出更好的答案之前,你可能需要澄清
编辑:允许任意数量的操作数和运算符也很容易:
operand_list:
| operand_list operand
;
operator_list:
| operator_list operator
;
expression: operand_list operator_list
;
目前,这并不试图强制任何特定操作数存在适当数量的运算符——您必须单独添加这些检查。在典型的情况下,postscript表示法是在堆栈机器上执行的,因此大多数这样的检查都变成了简单的堆栈检查
我应该补充一点,虽然您当然可以用类似于yacc的语言编写这样的解析器,但是使用postscript符号的语言通常需要非常小的解析,您经常直接将它们提供给某种虚拟机解释器,该解释器非常直接地执行它们,只需进行最小的解析(大多数情况下,如果您试图使用尚未定义的名称,解析归结为抛出错误)。鉴于上面的简短描述和维基百科上的注释:
上述简单的野牛语法可以是:
%token ADD
%token DUP
%token DEF
%token EQ
%token EXCH
%token IF
%token NOT
%token OR
%token SUB
%token NUMBER
%token IDENTIFIER
%%
program : action_list_opt
action_list_opt : action_list
| /* No Action */
action_list : action
| action_list action
action : param_list_opt operator
param_list_opt : param_list
| /* No Parameters */
param_list : param
| param_list param
param : literal
| name
| action_block
operator : ADD
| DUP
| DEF
| EQ
| EXCH
| IF
| NOT
| OR
| SUB
literal : NUMBER
name : '/' IDENTIFIER
action_block : '{' program '}'
%%
你说的
Postscript
是什么意思?你指的是Postscript语言还是其他稍微抽象一点的语言?对于类似Postscript的编程语言,我指的是类似Postscript的面向堆栈的编程语言。当你说“Postscript”时,我想到的是打印机语言。但我认为你的意思是“什么?”我会称之为基于堆栈的反向波兰语(reverse polish language)”:但不要认为这意味着“我认为你的描述是错误的”这正是我思考的方式,我想澄清(我自己).我现在明白了。我在wikipedia上找到了你的例子。有时包含链接比尝试描述链接更容易。事实上,使用Bison的例子是RPN计算器:)问题是也允许使用操作数操作数运算符。我认为使用yacc生成解析器是可能的,但对于语法类似于Postscript的脚本语言来说,这将是一种过分的杀伤力。谢谢您的回复。@Kiamaluno:不。如果它适用于编译语言,那么它应该同样适用于解释语言(脚本语言)。我认为这并不过分(实际上我认为这是必要的,因为手写既难又容易出错)。@马丁:事实上,不,在这种情况下,手写相对容易。基本上,操作数和运算符是混合的。操作数将值推送到堆栈中,运算符从堆栈中取出一定数量的操作数,组合它们,然后将结果放回堆栈。因此,“解析”基本上只是在字典中查找一个标记,看看它是否已定义。如果没有,你就拒绝它。@Jerry Coffin:好的。我给你这个。它看起来很简单,可以写一个手写的。