Racc 语法文件参考

全局结构

类块和用户代码块

在顶层有两个块。一个是“类”块,另一个是“用户代码”块。“用户代码”块必须放在“类”块之后。

注释

你可以在所有地方插入注释。可以使用两种注释风格,Ruby 风格的“#.….”和 C 风格的“/*.…..*/”。

类块

类块的格式如下

class CLASS_NAME
  [precedence table]
  [token declarations]
  [expected number of S/R conflicts]
  [options]
  [semantic value conversion]
  [start rule]
rule
  GRAMMARS

CLASS_NAME 是解析器类的名称。这是生成的解析器类的名称。

如果 CLASS_NAME 包含 '::',Racc 会输出模块子句。例如,写入“class M::C”会导致创建以下代码

module M
  class C
    :
    :
  end
end

语法块

语法块描述了可以被解析器理解的语法。语法如下

(token): (token) (token) (token).... (action)

(token): (token) (token) (token).... (action)
       | (token) (token) (token).... (action)
       | (token) (token) (token).... (action)

当找到 (token) 时,将执行 (action)。(action) 是一个 ruby 代码块,它用大括号括起来

{ print val[0]
  puts val[1] }

请注意,你不能在 action 中使用“%”字符串、here document、“%r”正则表达式。

可以省略动作。当省略时,使用“”(空字符串)。

action 的返回值是左侧值 ($$) 的值。它是结果值,或者由 'return' 语句返回的值。

这是整个语法块的示例。

rule
  goal: definition rules source { result = val }

  definition: /* none */   { result = [] }
    | definition startdesig  { result[0] = val[1] }
    | definition
             precrule   # this line continues from upper line
      {
        result[1] = val[1]
      }

  startdesig: START TOKEN

你可以在 action 中使用以下特殊局部变量

左侧 (lhs) 的值。默认值是 val

右侧 (rhs) 值的数组。

值的堆栈。除非你知道自己在做什么,否则不要修改此堆栈。

运算符优先级

此功能等同于 yacc 中的 '%prec'。要指定此块

prechigh
  nonassoc '++'
  left     '*' '/'
  left     '+' '-'
  right    '='
preclow

'right' 是 yacc 的 %right,'left' 是 yacc 的 %left。

'=` + (symbol) 表示 yacc 的 %prec

prechigh
  nonassoc UMINUS
  left '*' '/'
  left '+' '-'
preclow

rule
  exp: exp '*' exp
     | exp '-' exp
     | '-' exp       =UMINUS   # equals to "%prec UMINUS"
         :
         :

expect

Racc 具有 bison 的 “expect” 指令。

# Example

class MyParser
  expect 3
rule
    :
    :

此指令声明 “预期” 的移位/规约冲突的数量。如果 “预期” 数量等于实际的冲突数量,Racc 不会打印冲突警告消息。

声明标记

通过声明标记,你可以避免许多无意义的错误。如果声明的标记不存在,或者存在的标记未声明,Racc 会输出警告。声明语法为

token TOKEN_NAME AND_IS_THIS
      ALSO_THIS_IS AGAIN_AND_AGAIN THIS_IS_LAST

选项

你可以在 Racc 文件中为 Racc 命令编写选项。

options OPTION OPTION ...

选项为

是否省略空 action 调用。

是否使用局部变量 “result”。

你可以使用 'no_' 前缀来反转它们的含义。

转换标记符号

默认情况下,标记符号是

* naked token string in Racc file (TOK, XFILE, this_is_token, ...)
  --> symbol (:TOK, :XFILE, :this_is_token, ...)
* quoted string (':', '.', '(', ...)
  --> same string (':', '.', '(', ...)

你可以通过 “convert” 块来更改此默认值。这是一个例子

convert
  PLUS 'PlusClass'      # We use PlusClass for symbol of `PLUS'
  MIN  'MinusClass'     # We use MinusClass for symbol of `MIN'
end

我们可以使用几乎所有 ruby 值作为标记符号,除了 “false” 和 “nil”。这些会导致意外的解析错误。

如果你想使用 String 作为标记符号,则需要特别注意。例如

convert
  class '"cls"'            # in code, "cls"
  PLUS '"plus\n"'          # in code, "plus\n"
  MIN  "\"minus#{val}\""   # in code, \"minus#{val}\"
end

起始规则

yacc 中的 '%start'。这会更改起始规则。

start real_target

用户代码块

“用户代码块” 是一个 Ruby 源代码,它会被复制到输出。有三个用户代码块,“header”、“inner” 和 “footer”。

用户代码的格式如下

---- header
  ruby statement
  ruby statement
  ruby statement

---- inner
  ruby statement
     :
     :

如果行首存在四个 “-”,则 Racc 会将其视为用户代码块的开始。用户代码块的名称必须是一个单词。