2016-05-05 8 views
0

LBNFでC/C++関数の宣言に次のような形式(略称)を指定しようとしています(<sym>はoptionallity、[rule]もっとリスト):LBNF、C関数宣言/定義、reduce reduce conflict

type ident ([type <id>]); 

関数定義は次の形式を持っているが:

entrypoints Program ; 
Program. Program ::= [TopDef] ; 

FnDef.  TopDef ::= Type Ident "(" [Arg] ")" Block ; 
FnDecl. TopDef ::= Type Ident "(" [Par] ")" ";" ; 
separator nonempty TopDef "" ; 

Param.  Par ::= Type ; 
NParam. Par ::= Type Ident ; 
separator Par "," ; 

Arg.  Arg ::= Type Ident; 
separator Arg "," ; 

-- Types --------------------------------------------------- 

Int.  Type ::= "int" ; 
--- more types... 
separator Type "," ; 

type ident ([type id]) { [stmt] } 

現在、私は次のLBNFを持っています10

予想どおりの縮小/縮小の競合が発生します。 パーサー/レクサーでこれを解決する方法はありますか?

私は、次の文法でそれを解決することができます:どのように...

FnDef.  TopDef ::= Type Ident "(" [Arg] ")" Block ; 
FnDecl. TopDef ::= Type Ident "(" [Arg] ")" ";" ; 
separator nonempty TopDef "" ; 

Arg.  Arg ::= Type Ident; 
Arg.  Arg ::= Type; 
separator Arg "," ; 

そして定義は各引数の識別子を持っているが、これはあまり満足のいく感じに機能型チェッカーでチェックこれは通常Cのような言語で扱われますか?

+0

CまたはC++。 C++にはC言語では存在しないデコレータがあります。 – NathanOliver

+0

@NathanOliverでは、CやC++ではない虚偽のはるかに単純な言語を考えてみましょう。私の質問は、上記の2つの形式とそれらの違いです。 – Centril

+0

'('と ')'は入力記号であることを明確に意図しているので、あなたはオプションのために '<...>'を使用していると思っています....ああ、あなたは気づかなかったが、 ''はマークダウンがそれを削除するHTMLマークアップに似ています。 – rici

答えて

2

あなたが不満を感じるのは、実際にはそれが達成される方法です。

しかし、正確なLALR(1)文法を生成することができます。ここに矛盾のない完全なbison仕様があります:

%token TYPE ID 
%% 
prog  : 
      | prog decl ';' 
decl  : TYPE ID def_list block 
      | TYPE ID def_list ';' 
      | TYPE ID dec_list ';' 
block  : '{' prog '}' 
def_list : '(' ')' 
      | '(' type_ids ')' 
dec_list : '(' type_opt_ids ')' 
type_opt_id: type_only 
      | type_id 
type_ids : type_id 
      | type_ids ',' type_id 
type_opt_ids 
      : type_only 
      | type_ids ',' type_only /* SEE BELOW */ 
      | type_opt_ids ',' type_opt_id 
type_id : TYPE ID 
type_only : TYPE   

重要な点は、パーサが強制的に決定しないようにすることです。パラメータのリストを渡すので、匿名のパラメータにヒットしない限り、それはtype_opt_idsを引き続き減らすことができます。 1つに当たった場合、それはtype_idsを減らし、匿名であるかどうかに関わらず、残りのパラメータについて続けます。結局のところ、この定義ではtype_idsしか許されていますが、宣言は(明示的に)どちらかを受け入れます。その仕事をするために

type_idstype_opt_idsの両方がそのタイプのリストでなければならないため、type_idtype_onlyのためのセマンティックタイプは、同じである必要があります。そうしないと、あなたは(私はあなたの形式主義にあることを変換しないために謝るが、私は実際には、それがあることを確認するためにバイソンでそれをテストしたい、conflict- /* SEE BELOW */

でマークされた生産にtype_opt_idstype_idsを変換する必要があります無料。変換するのは簡単でなければなりません。)C++は、パラメータ名なしで関数定義を許可して幸せですが、Cではない


注意。一方、Cでは、型のない関数定義や、パラメータ名リストと本文の間の型宣言を使用することができます。しかし、これは副問題です。

+0

素晴らしい答え。結局のところ、私はいくつかの挑戦が必要です。しかし、私は今、通常の方法であるので、代わりに型チェッカーでそれを行うだろうと思う=) – Centril