2012-03-13 11 views
3

私は非常に単純な言語の割り当てで構成されたLALR文法を作成しようとしています。たとえば、次のようにLALR文法、末尾のコンマ、および複数行のリストの割り当て

foo = "bar" 
bar = 42 

また、例えば、値のリストを処理する必要があります言語:

foo = 1, 2, 3 

しかし、私はまた、複数行のリスト処理したい:

foo = 1, 2 
     3, 4 

カンマを末尾に(シングルトンと言語の柔軟性のため):

foo = 1, 
foo = 1, 2, 

そして、明らかに、両方同時に:

foo = 1, 
     2, 
     3, 

私は、コンマまたは複数行のリストを末尾に文法を書くことができるんだけど、両方ではないため、同時に。

私の文法は次のようになります。

content : content '\n' 
     : content assignment 
     | <empty> 

assignment : NAME '=' value 
      | NAME '=' list 

value : TEXT 
     | NUMBER 

list : ??? 

注:事前による

foo 
= 
"bar" 

おかげで、

:私はこの種のコードを禁止する文法中の '\ n' のを必要とします

アントワーヌ。

+0

あなたは、JavaScript、Go、Scala(というよりも、私の頭の上にあるもの)がセミコロンを推論する方法を見てみることができます。しかし、これは改行(改行を越えて広がっている表現)につながり、かなりのプログラマーがそれを嫌っていることに注意してください。おそらく、より多くの制限を加えるべきです(例えば、 "parens/brakets/braces内の式だけが複数の行にまたがることができます"、これはPythonのことです)。 – delnan

+0

実際、私の言語はプログラミング言語ではなく、構成形式なので、式はありません。私はリストの周りに何かを追加することを考えましたが、私はできれば私は好きではありません。 – Antoine

+0

構文解析コードへのリンクを提供して、文法と一緒に遊んで、それがうまくいくかどうかを確認できますか? –

答えて

2

あなたの設定言語は基本的にフリーフォームのようです。文法の中で改行をトークンにすることは忘れてしまいます。改行の制限が必要な場合は、それをいくつかのレキシカルタイインルールとしてハックすることができます。これにより、パーサーはレクサーに追加された小さなAPIを呼び出して、レクサーに文法のどこにあるかを知らせ、レクサーは、改行をしたり、エラーでそれらを拒否したりする。

この文法を試してみてください。

%token NAME NUMBER TEXT 

%% 

config_file : assignments 
      | /* empty */ 
      ; 

assignments : assignment 
      | assignments assignment 
      ; 

assignment : NAME '=' values comma_opt 

comma_opt : ',' | /* empty */; 

values : value 
     | values ',' value 
     ; 

value : NUMBER | TEXT ; 

これは矛盾なく構築されています。私はそれを実行しませんでしたが、y.outputのカジュアルな読みは、移行が正気であるように見えます。

この文法は、当然のことながら、レクサーとの追加の通信なし

foo = 1, 2, 3, bar = 4, 5, 6 xyzzy = 7 answer = 42 

を可能にします。

制限は、値に改行のみが許可されていることを意味します。 2つのNAMEトークンが同じ行に表示されてはならず、=は前のNAMEと同じ行に表示されなければなりません(おそらく最初の値も必要です)。

パーサーが最初の値をスキャンすると、それはレクサーに "値が今スキャンされていること、改行の許可をオンにする"と伝えることができます。 comma_optを減らすと、これをもう一度オフにすることができます。comma_optが縮小されている場合、レクサーはすでに次の割り当てのNAMEトークンを読み取っている可能性がありますが、これは以前のNAMEと異なる行で発生していることを確認できます。あなたはレクサーがとにかく正確な行数を追跡することを望みます。

+0

私はあなたのアイデアをテストしましたが、記述した通り正確ではないかもしれませんが、それはうまく動作します:-)。ありがとう!レコードの場合、パーサに記録されている "現在の行"がレクサーの現在の行と同じで、それ以外の場合は "現在の行"を設定している場合は例外を発生させる検査を追加しました。このチェックは各割り当てまたはセクションルールで呼び出されます。 – Antoine

0

私は実際にこれに多くの経験はありませんが、これは機能しますか?

listvalue : value , 
      | value '\n' 
      | value , '\n' 

list : listvalue list 
関連する問題