3

ネストされたブロック構文用の単純なパーサーを作成したいと思います。階層的なプレーンテキストだけです。例えば:

Some regular text.
This is outputted as-is, foo{but THIS
is inside a foo block}.

bar{
  Blocks can be multi-line
  and baz{nested}
}

これを行う最も簡単な方法は何ですか?私はすでに2つの実用的な実装を作成しましたが、それらは非常に複雑です。フルテキストの正規表現マッチングと、文字ごとのストリーミング分析を試しました。

私はそれの働きを人々に教えなければならないので、単純さが最も重要です。Lex / Yacc Flex / Bison(またはPEGjs / Jison、実際にはこれはjavascript)への依存関係を導入したくありません。

4

3 に答える 3

1
   char c; 

   boolean ParseNestedBlocks(InputStream i)
      {  if ParseStreamContent(i)
         then {  if c=="}" then return false
                            else return true
              }
         else return false;

   boolean ParseSteamContent(InputStream i)
    {  loop:
         c = GetCharacter(i);
         if c =="}" then return true;
         if c== EOF then return true;
         if c=="{"
             {  if ParseStreamContent(i)
                  {  if c!="}" return false; }
                else return false;
             }
         goto loop
     }
于 2013-02-21T03:44:54.290 に答える
1

良い選択はおそらく次のように要約されます:

  • あなたの内容を考えると、それは再帰下降になるでしょう。これは、制約がなくてもうまくいく方法です。
  • char-by-char(従来型)を解析するか、ローカル文字列ライブラリを使用して{とをスキャンする字句レイヤーを作成でき}ます。いずれの場合も、3つの終端記号とEOF(BLOCK_OF_TEXT、LEFT_BRACE、およびRIGHT_BRACE)を返すことができます。
于 2013-02-21T00:23:11.807 に答える
1

最近、私は純粋なJavascriptのいくつかのプロジェクトにパーサーコンビネーターを使用しています。コードを別のプロジェクトに引き出しました。ここで見つけることができます。このアプローチは、@ DigitalRossが提案した再帰下降パーサーに似ていますが、パーサーに固有のコードと一般的なパーサーの簿記コードがより明確に分割されています。

あなたのニーズに合ったパーサー(私があなたの要件を正しく理解していれば)は次のようになります:

var open  = literal("{"),                 // matches only '{'
    close = literal("}"),                 // matches only '}'
    normalChar = not1(alt(open, close));  // matches any char but '{' and '}'

var form = new Parser(function() {}); // forward declaration for mutual recursion

var block = node('block',
                 ['open',  open       ],
                 ['body',  many0(form)],
                 ['close', close      ]);

form.parse = alt(normalChar, block).parse; // set 'form' to its actual value

var parser = many0(form);

そして、あなたはそれをこのように使うでしょう:

// assuming 'parser' is the parser
var parseResult = parser.parse("abc{def{ghi{}oop}javascript}is great");

解析結果は構文木です。

このライブラリは、バックトラックに加えて、パーサー呼び出しの間に優れたエラーメッセージとスレッドユーザー状態を生成するのにも役立ちます。後者の2つは、中括弧のエラーメッセージを生成するのに非常に役立ち、次の場合に問題と問題のある中括弧トークンの場所の両方を報告します。1)中括弧が開いているが、閉じていない。2)中括弧の種類が一致していません-つまり(...]、または{...); 3)一致するオープンのないクローズブレース。

于 2013-02-21T21:56:18.053 に答える