【问题标题】:Is it possible to generate a parser for a language using the Reverse Polish notation with bison/yacc?是否可以使用带有 bison/yacc 的逆波兰表示法为一种语言生成解析器?
【发布时间】:2010-08-24 06:08:07
【问题描述】:

是否可以使用 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 是什么意思?你指的是后记语言还是指其他稍微抽象一点的东西?
  • 对于类似 Postscript 的编程语言,我的意思是像 Postscript 这样的面向堆栈的编程语言。
  • 当你说“后记”时,我想到了打印机语言en.wikipedia.org/wiki/PostScript。但我认为你的意思是“我称之为基于堆栈的反向波兰语言”:en.wikipedia.org/wiki/Stack-oriented_programming_language 但不要认为这意味着“我认为你的描述是错误的”这正是我的想法和想要的方式澄清(为我自己)。
  • 我现在明白了。 en.wikipedia.org/wiki/…我在维基百科上找到了你的例子。有时添加链接比尝试描述链接更容易。
  • 事实上,使用 Bison 的例子是一个 RPN 计算器 :)

标签: c++ yacc bison


【解决方案1】:

鉴于上面的简短描述和维基百科上的注释:
http://en.wikipedia.org/wiki/Stack-oriented_programming_language#PostScript_stacks

上面的一个简单的野牛语法可能是:

%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 '}'


%%

【讨论】:

    【解决方案2】:

    是的。假设您的意思是也使用 postscript 表示法,这意味着您将定义您的表达式,例如:

    expression: operand operand operator
    

    而不是更常见的中缀表示法:

    expression: operand operator operand
    

    但这算不上什么大不了的事。如果您所说的“类似 Postscript”的意思是其他意思,您可能需要先澄清一下,然后才能给出更好的答案。

    编辑:允许任意数量的操作数和运算符也很容易:

    operand_list: 
                | operand_list operand
                ;
    
    operator_list: 
                 | operator_list operator
                 ;
    
    expression: operand_list operator_list
              ;
    

    就目前而言,这并不试图强制任何特定操作数存在正确数量的运算符 - 您必须单独添加这些检查。在典型情况下,postscript 表示法在堆栈机器上执行,因此大多数此类检查都成为简单的堆栈检查。

    我应该补充一点,尽管您确实可以用 yacc 之类的东西编写这样的解析器,但使用 postscript 表示法的语言通常需要如此最少的解析,以至于您经常将它们直接提供给某种虚拟机解释器,该解释器执行它们非常直接,只需最少的解析(大多数情况下,如果您尝试使用尚未定义的名称,解析会引发错误)。

    【讨论】:

    • 问题是operand operand operand operand operator operator也是允许的。
    • 我认为使用 yacc 生成解析器是可能的,但对于语法类似于 Postscript 的脚本语言来说,这将是一种过度杀伤力。感谢您的回复。
    • @kiamlaluno:不。如果它适用于编译语言,那么它应该同样适用于解释语言(脚本语言)。我认为这并不过分(实际上我认为这是必不可少的,因为手工编写既困难又容易出错)。
    • @Martin:实际上,不,在这种情况下,手写相对容易。基本上,您有操作数和运算符的混合体。操作数将一个值压入堆栈,运算符从堆栈中取出一些操作数,将它们组合起来,然后将结果放回堆栈。因此,“解析”基本上只是在字典中查找标记以查看它是否已定义。如果没有,你拒绝它。
    • @杰瑞·科芬:好的。我给你那个。它看起来很简单,可以手写一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 2021-11-29
    • 2021-12-24
    • 2015-06-15
    • 2019-10-27
    相关资源
    最近更新 更多