3

Handlebars 用の Ruby/Parslet パーサーを作成しようとしていますが、{{ else }}キーワードに行き詰まっています。ハンドルバーを使用しない人のために簡単に説明すると、if/else は次のように記述されます。

{{#if my_condition}}
  show something
{{else}}
  show something else
{{/if}}

ただし、インライン化とヘルパーが同じ構文を使用できるため、注意が必要です。次に例を示します。

Name: {{ name }}
Address: {{ address }}

そこで、最初に置換を認識するルールを作成しました。

rule(:identifier)  { match['a-zA-Z0-9_'].repeat(1) }
rule(:path)        { identifier >> (dot >> identifier).repeat }

rule(:replacement) { docurly >> space? >> path.as(:item) >> space? >> dccurly}

{{name}}またはのようなものに一致し{{people.name}}ます。{{ else }}もちろん問題は、それがブロックとも一致することです。if/else ブロックに一致するルールを作成した方法は次のとおりです。

rule(:else_kw) {str('else')}
rule(:if_block) {
  docurly >>
  str('#if') >>
  space >>
  path.as(:condition) >>
  space? >>
  dccurly >>
  block.as(:if_body) >>
  (
    docurly >>
    else_kw >>
    dccurly >>
    block.as(:else_body)
  ).maybe >>
  docurly >>
  str('/if') >>
  dccurly
}

(注: docurly は{{、dccurly は}}、 block は多かれ少なかれ何でもかまいません)

したがって、「識別子」ルールを書き直して、「else」ではなく任意の単語に一致するようにする必要があります。

前もってありがとう、ヴィンセント

4

2 に答える 2

0

一致させようとしている構文によって異なります。{{if}} {{/if}}ペアの中にいなかった場合{{else}}、有効な識別子または構文エラーとして扱われるべきですか? パスがあった場合、a.else.bそれは有効ですか?

有効でない場合a.else.bは、次のことができます。

rule(:identifier)
    { (else_kw).absent? >> match['a-zA-Z0-9_'].repeat(1) | else_kw >> match['a-zA-Z0-9_'].repeat(1) }

「else」を除くすべての文字列を受け入れます。「else で始まらない任意の文字列、または、else で始まる文字列のうち、少なくとも 1 文字以上ある文字列」と指定します。

注: これは、「なぜelse特別なのか?」と考えさせられます。ここですべてのキーワードを除外する必要がありますか?

が有効な場合a.else.b、識別子レベルで除外することはできません。pathその場合、あなたができないと言った方が正確"else"です。

あなたが言った場合:

rule(:path)        { else_kw.absent? >> (identifier >> (dot >> identifier).repeat) }

これにより、「else」で始まる識別子、たとえば「elsewise.option」が除外されます。

したがってabsent?、ブロックが終了したことを示すために何かを一致させる必要もあります。

rule(:path)        { (else_kw >> dccurly).absent? >> (identifier >> (dot >> identifier).repeat) }

ここでの問題は、dccurly厳密には正しくない (そして空白を扱わない) で終わるという考えに path を結合していることです。したがって、「パス」はこのようなものを置くのに適切な場所ではありません。

置換をマッチングから止めようとしていた場合else、それはより簡単になります。

rule(:replacement) { docurly >> space? >> (else_kw >> space? >> dccurly).absent? >> path.as(:item) >> space? >> dccurly}

それは置換の一致を防ぎますが、またはelseを許可します。elsewise.somethingelse.something

「else.something」が必要ない場合は、次のようなものが必要です。

rule(:replacement) { docurly >> space? >> (else_kw >> (space | dccurly | dot)).absent? >> path.as(:item) >> space? >> dccurly}

「else」「else」のように。および「else}}」はすべて防止されます。

于 2015-03-25T00:59:53.827 に答える