2017-12-10 11 views
3

Superpowerでパーサを作成しようとしています。私はすでにレポで見つかったサンプルを見てきましたが、少なくとも私のような初心者にとっては理解するのが少し難しいです。だから私はこの小さな挑戦をしました。スーパーパワーで単純なテキスト文法を解析する

私は学ぶために非常に基本的な文法を発明しました。私はエレベーターを考え、上り、下り、待つという指示のリストに従っています。

例:

(UP 100), 
(DOWN 200), 
(DOWN 100), 
(DOWN @1), 
(UP @3), 
(WAIT), 
(UP 300) 

見ての通り、これは、例えば、エレベーターを動かすためにカンマで区切られた動詞のリストから構成されます。

  • 動詞は、DOWN又はWAIT UPあります。
  • すべて動詞が括弧で囲まれている:DOWN UPと
  • ()は、絶対数又はエレベータが移動する必要がありするフロアを示す相対数、いずれかを必要とします。相対的なフロア番号は、番号の前に@が付いています。
  • WAITはエレベーターをしばらく停止するため、番号は受け付けません。

私は本当にスーパーパワーを使用する方法を理解するために、スタートとして、この文法のトークンベースのパーサーを作成する方法を学習したいと思います。

誰でもお手伝いできますか?

ありがとうございます!

+0

[This](https://github.com/datalust/superpower/tree/dev/sample/DateTimeTextParser)? [readme](https://github.com/datalust/superpower/blob/dev/README.md)を超える多くのドキュメントはありませんが、いくつかのサンプルと、文法の構築方法を示すテストがあります。 – dlatikay

+0

@PatrickArtner StackOverflowをより大きな場所にしてくれてありがとう。 – SuperJMN

+0

@dlatikayありがとう、私はそれらのサンプルを知っていますが、それでも私はそれを処理することはできません。だから私はこの愚かなサンプルを作ったのです:学習のためです。あなたが私が既存のドキュメントで尋ねたパーサーを作成する能力があれば、分かち合いましょう。 – SuperJMN

答えて

5

Superpowerパーサーを書くことのステップ1は、トークンの種類が何であるか把握することです。

// ECL - Elevator Control Language ;-) 
enum EclToken { 
    LParen, 
    RParen, 
    UpKeyword, 
    DownKeyword, 
    WaitKeyword, 
    AtSymbol, 
    Number, 
    Comma 
} 

ステップ2、Tokenizer<EclToken>を書く:あなたはのようなものを持っています。これは、Superpower v1の直接のプログラミング作業として残されています。多くの助けが必要ないので、the examplesのようにコードを書くだけです。

トークナイザは入力文字列を取り出し、空白を取り除き、トークンの順序を把握します。あなたの例の入力について

、最初の行は次のようになりますコンテンツを含むNumberようなトークンの

// (UP 100), 
LParen, UpKeyword, Number, RParen, Comma 

Result<EclToken>に関連付けられたスパンは、トークンに対応する入力文字列の部分を指します。この行の番号はTextSpanで、100です。

ステップ3は、入力をどのように解析してにするかを調べることです。ネストされた式を持つプログラミング言語の場合、これは通常ASTです。

struct ElevatorCommand {   
    public int Distance; // + or - 
    public bool IsRelative; 
} 

ステップ4、パーサ:あなたはそれを切る可能性があるので、ECLのサンプルの場合、それはかなり簡単です。これは、通常、静的クラスに埋め込まれます。パーサの仕事は、より簡単な結果(数、移動)からより複雑な結果(ここではElevatorCommand[])を構築することです。

これは、特に期待や誤りに関して、Superpowerが重い吊り上げをする場所です。

static class EclParser 
{ 
    static TokenListParser<EclToken, int> Number = 
     Token.EqualTo(EclToken.Number).Apply(Numerics.IntegerInt32); 
} 

私たちがまず行うことは、数値のパーサを定義することです。この例ではがEclToken.Numberスパンの内容に組み込まれています。

this exampleには、さらに多くの構文解析ツールがあります。

さらにいくつかの手がかりは、(/コンパイルはおろか、確認テスト構文ではない)あなたは道を見つけるのに役立つ:

static TokenListParser<EclToken, ElevatorCommand> Up = 
     from _ in Token.EqualTo(EclToken.UpKeyword) 
     from distance in Number 
     select new ElevatorCommand { 
      Distance = distance, 
      IsRelative = false 
     }; 

    static TokenListParser<EclToken, ElevatorCommand> Command = 
     from lp in Token.EqualTo(EclToken.LParen) 
     from command in Up // .Or(Down).Or(Wait) 
     from rp in Token.EqualTo(EclToken.RParen) 
     select command; 

    static TokenListParser<EclToken, ElevatorCommand[]> Commands = 
     Command.ManyDelimitedBy(Token.EqualTo(EclToken.Comma)); 
} 

Commandsは、あなたが入力に適用することができます完了パーサーです。

パーサーを段階的に構築し、各小さなパーサーを解析することが予想される入力塊でテストするのが最善です。

+0

わかりました。今、私はパーサーを作成しようとしています:)今のところ、私は疑いがあります。 ElevatorCommandは距離だけでなく、相対的なコマンドであるかどうかでモデル化しました。しかし、WAITコマンドはどのように表現されますか? – SuperJMN

+1

ちょうどニッピッカーズコーナーのヘッドアップ、「スーパーパワー」の「p」は小文字です:-) –

+1

クール!申し訳ありませんが、私はそれが私のPascalCaseManiaだと信じています: - P – SuperJMN

1

私は最終的にそれを得ることができました。 @Nicholas Blumhardtの案内ではそれほど難しくありませんでした。

私はシナリオを説明するためにa project in GitHubを作成しました。クラスはポストのために大きなされているので、私は、ファイルにリンクしています:

関連する問題