3

我在流氓中有一个简单的文件,用于指定玩具语法

module temp

import IO;

import ParseTree;

layout LAYOUT = [\t-\n\r\ ]*;

start syntax Simple 
  =  A B ;

syntax A = "Hello"+ ("joe" "pok")* ;
syntax A= "Hi";
syntax B = "world"*|"wembly";
syntax B =    C | C C*   ;


public void main () {
println("hello");
iprint(parse(#start[Simple], "Hello Hello world world world"));
}

这很好用,但是问题是我不想写

syntax B =    C | C C*   ;

我想写

syntax B =  (  C | C C*  )? 

但它被流氓拒绝为解析错误 - 即使所有

syntax B =  (  C  C C*  )? ;

syntax B =  (  C |  C*  )? ;

syntax B =    C | C C*   ;

接受罚款。谁能向我解释我做错了什么?

4

1 回答 1

2

序列符号(嵌套序列)总是需要 rascal 中的括号。元符号定义为

syntax Sym = sequence: "(" Sym+ ")" | opt: Sym "?" | alternative: "(" Sym "|" {Sym "|"}+ ")" | ... ;

因此,在您的示例中,您应该编写:

syntax B = (C | (C C*))?;

可能令人困惑的是 Rascal 使用 | 签两次。一次用于分离顶级替代方案,一次用于嵌套替代方案:

syntax X = "a" | "b"; // top-level
syntax Y = ("c" | "d"); // nested, will internally generate a new rule: 
syntax ("c" | "d") = "c" | "d";

最后,正常的替代方案有没有括号的序列,如:

syntax B 
  = C
  | C C*
  ;
// or less abstractly:
syntax Exp = left Exp "*" Exp
           > left Exp "+" Exp
           ;

顺便说一句,我们通常避免使用太多嵌套的正则表达式,因为它们是如此匿名,因此使解析树的解释变得更加困难。正则表达式的最佳用法是表达我们对内部结构不太感兴趣的词法语法。

于 2013-05-24T13:22:19.093 回答