10

これは、単純な識別子(のようなcow)かっこで囲まれたもの((...))、メソッド呼び出しのような...(...)もの()、またはメンバーアクセスのようなもの()のいずれかですthing.member

def expr = identifier | 
           "(" ~> expr <~ ")" | 
           expr ~ ("(" ~> expr <~ ")") | 
           expr ~ "." ~ identifier

これはScalaParserCombinator構文で与えられていますが、理解するのはかなり簡単なはずです。これは、式が多くのプログラミング言語でどのように見えるかと似ています(そのため名前が付けexprられています)。ただし、現状では、左再帰であり、私の素敵なPEGパーサーが爆発します。

のような場合の正確さを維持しながら、左再帰を因数分解することに成功していません(cow.head).moo(dog.run(fast))。これをリファクタリングするにはどうすればよいですか、または左再帰文法を許容できるパーサジェネレータにシフトする必要がありますか?

4

1 に答える 1

20

トリックは、同じルールへの再帰呼び出しではなく、各ルールの最初の要素が次のルールである複数のルールを持つことです。残りのルールはオプションで繰り返します。たとえば、次の例では次のように動作します。

def expr              = method_call
def method_call       = member_access ~ ( "(" ~> expr <~ ")" ).*
def member_access     = atomic_expression ~ ( "." ~> identifier).*
def atomic_expression = identifier |
                        "(" ~> expr  <~ ")"
于 2012-11-14T06:48:39.933 に答える