3

おもちゃの文法を指定するための単純なファイルがrascalにあります

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*  )? 

しかし、rascal によって解析エラーとして拒否されました。

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 が | を使用していることです。二回サイン。トップレベルの代替を分離するために 1 回、ネストされた代替のために 1 回:

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 に答える