Pegjs: 空白の区切り文字を保持する方法は?

作成日 2019年10月03日  ·  6コメント  ·  ソース: pegjs/pegjs

問題の種類

  • バグレポート: _no_
  • 機能リクエスト: _no_
  • 質問: _はい_
  • 問題ではありません: _no_

前提条件

  • 問題を再現できますか?: _はい_
  • リポジトリの問題を検索しましたか?: _ yes_
  • フォーラムを確認しましたか?: _はい_
  • Web検索(google、yahooなど)を実行しましたか?: _ yes_

PEG.jsパーサーに方程式の元の空白を保持させるのに苦労しています。

現在の動作: 2 * 5 + SUM(1, 2, 3)

[
   "2",
   "*",
   "5",
   "+",
   "SUM",
   "(",
   [
      "1",
      ",",
      "2",
      ",",
      "3"
   ],
   ")"
]

望ましい動作2 * 5 + SUM(1, 2, 3)

[
   "2",
   " ",
   "*",
   " ",
   "5",
   " ",
   "+",
   " ",
   "SUM",
   "(",
   [
      "1",
      ",",
      " ",
      "2",
      ",",
      " ",
      "3"
   ],
   ")"
]

コピーする文法: https ://pastebin.com/zpwqT6Uw
PEG.jsプレイグラウンドhttps://pegjs.org/online

私は何が欠けていますか?

最も参考になるコメント

@ marek-baranowskiもう1つの穏やかなping:smiley_cat:

また、文法のデバッグを容易にするためにPEG.jsプラグインpegjs-syntactic-actionsを作成しました。具体的には、アクションとは関係なく、どの文字がどのルールによってキャプチャされるかを確認します。これは、@ StoneCypherで説明されているようにおそらくここでの問題です。

このプラグインの理由は次のとおりです。グローバルな結果が期待どおりでない場合、それは多くの小さなアクションの組み合わせの結果であり、動作が悪い/スタンジェリーである可能性があるため、グローバルな結果を理解するのは難しい場合があります。時間がかかる。 このプラグインを使用すると、どのルールがどのキャラクターをキャプチャするかを確認し、アクションの名前を指定します。

全てのコメント6件

@futagozaご迷惑をおかけして大変申し訳ありませんが、PEG.jsを扱うのは初めてであり、この問題は私にとって重大です。 ちょっとしたヒントをお願いしてもいいですか?

よろしくお願いします、
マレク

私はあなたの文法を(昨日と今)調べてみましたが、それを理解するのは本当に難しいので(命名規則はさておき、正直なところ、形式はいたるところにあります)、解決策を見つけるのに時間がかかりました:

  1. スペースとデータを消費するルールはそれを返します(たとえば、 const[left_space, cnst, right_space] $を返します)
  2. 結果を取得するルール/アクションは、次のようにする必要があります: [].concat.apply([], con)

それでも、あなたに正直に言うと、これは私にとってハッキーな解決策のように感じます。 スペックなどへのリンクはありますか? 上記のハッキーな解決策なしで望ましい結果を得るために私が変更できるルールと変更できないルールを知ることは役に立ちます。

そうでない場合は、時間をかけて文法を整理し、いくつかのルールの名前を変更することをいとわない限り(あなたが望むものを理解しやすくするため)、私は喜んでそれをもう一度突き刺そうとします😉

@ marek-baranowski-申し訳ありませんが、これは今まで見ていませんでした。 うまくいけば、これはまだあなたに役立ちます

スペースを保持したい場合は、それらを一致するコンテンツのように扱ってください。

2つのスペースに何が必要かは明確ではありません。 2つのスペースの文字列、または2つの1つのスペースの文字列の配列のいずれかを使用できます。 通常は前者を期待しますが...あなたのすべてはキャラクターごとです

また...関数呼び出しを除いて、なぜそのような迷子の文字が必要なのですか? パーサーはそれらを合計する必要があります。

ともかく

これはあなたが求めたものです:

Document = Expression*

Whitespace
  = tx:[ \r\n]+ { return tx.join(''); }

Number
  = str:[0-9]+ { return str.join(''); }

Oper
  = '+'
  / '-'
  / '/'
  / '*'
  / ','

Label
  = l:[a-zA-Z]+ { return l.join(''); }

Parens 
  = '(' Whitespace? ex:Expression* Whitespace? ')' { return ex; }

Expression 
  = Number 
  / Oper
  / Whitespace
  / Label
  / Parens
  / [^()]+

image

実は、それが実際にあなたが望んでいるものだと私は確信していません。 代わりに、例として、数値と演算子を解析し、それぞれについて標準化されたノード形状を返すことができます。

Document = Expression*

Whitespace
  = tx:[ \r\n]+ { return { 
    ast: 'whitespace', value: tx.join('') 
  }; }

Number
  = str:[0-9]+ { return {
    ast: 'number', value: parseInt(str,10)
  }; }

Oper
  = '+' { return { ast: 'oper', value: 'add' }}
  / '-' { return { ast: 'oper', value: 'subtract' }}
  / '/' { return { ast: 'oper', value: 'divide' }}
  / '*' { return { ast: 'oper', value: 'multiply' }}
  / ',' { return { ast: 'oper', value: 'sequence' }}

Label
  = l:[a-zA-Z]+ { return { 
    ast: 'label', value: l.join('') 
  }; }

Parens 
  = '(' Whitespace? ex:Expression* Whitespace? ')' { 
    return { ast: 'parens', value: ex 
  }; }

Expression 
  = Number 
  / Oper
  / Whitespace
  / Label
  / Parens
  / [^()]+

これでまだ空白がありますが、適切に解析されたツリーもあり、パーサーの出力を解析するためにパーサーを作成する必要はありません。また、行番号などの正規化された機能の追加を開始するのも簡単です。

image

@ marek-baranowski-この課題追跡システムのサイズをいくらか縮小したい

上記が必要な場合は、この問題を解決することを検討してください。 ありがとう😄

そうでない場合は、理由を教えてください。もう一度やり直します

@ marek-baranowskiもう1つの穏やかなping:smiley_cat:

また、文法のデバッグを容易にするためにPEG.jsプラグインpegjs-syntactic-actionsを作成しました。具体的には、アクションとは関係なく、どの文字がどのルールによってキャプチャされるかを確認します。これは、@ StoneCypherで説明されているようにおそらくここでの問題です。

このプラグインの理由は次のとおりです。グローバルな結果が期待どおりでない場合、それは多くの小さなアクションの組み合わせの結果であり、動作が悪い/スタンジェリーである可能性があるため、グローバルな結果を理解するのは難しい場合があります。時間がかかる。 このプラグインを使用すると、どのルールがどのキャラクターをキャプチャするかを確認し、アクションの名前を指定します。

ああすごいこれは実際には本当にきれいです

このページは役に立ちましたか?
0 / 5 - 0 評価