おひさしぶりです。
三日坊主も100回続けばなんとやら。という精神で今までやってきましたが、遂に三日坊主すらままならなくなってしまいました。
それもこれも、全てLemonさんのせいです!!ぷんぷんです!
質問掲示板を見ている方には解ると思いますが、謎のエラーに数日間苦しめられていたのです。
しかし、それもつい先ほど解決しました。
とりあえず
「Lemonによって生成されたC言語の構文解析プログラムをメイン関数から呼んで基本的なトークンを人力で与えて、正しく構文解析できているかテストする」
という段階まで到達できました。
文法規則ファイル basic_lemon.y
► スポイラーを表示
CODE:
%token_type {int}
%left Num_literal_token.
%left Variable_token.
%left Binary_operator.
%include {
#include
#include
#include
#include
}
program ::= input.
input ::= /* empty */. { printf("bison info : found input\n"); }
input ::= input line. { printf("bison info : found input\n"); }
line ::= formula Semicolon. { printf("bison info : found line\n"); }
line ::= Semicolon. { printf("bison info : found line\n"); }
line ::= error Semicolon. { printf("bison error : wrong formula\n"); }
formula ::= Variable_token Equal formula. { printf("bison info : found formula\n"); }
formula ::= Num_literal_token Equal formula. { printf("bison error : left-hand side must variable\n"); }
formula ::= formula Binary_operator formula. { printf("bison info : found formula\n"); }
formula ::= Variable_token. { printf("bison info : found formula\n"); }
formula ::= Num_literal_token. { printf("bison info : found formula\n"); }
出力ファイル basic_lemon.h
► スポイラーを表示
CODE:
#define Num_literal_token 1
#define Variable_token 2
#define Binary_operator 3
#define Semicolon 4
#define Equal 5
出力ファイルの一部 basic_lemon.c
► スポイラーを表示
CODE:
/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
#include
#line 9 "basic_lemon.y"
#include
#include
#include
#line 15 "basic_lemon.c"
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
CODE:
** three input tokens have been successfully shifted.
*/
if( yypParser->yyerrcntyyerrcnt = 3;
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
if( yyendofinput ){
yy_parse_failed(yypParser);
}
yymajor = YYNOCODE;
#endif
}
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
return;
}
出力されたファイルに手を加えたもの basic_lemon.cpp
► スポイラーを表示
CODE:
/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
#include
#line 9 "basic_lemon.y"
#include
#include
#include
#include
#include
#include "basic_lemon.h"
#line 15 "basic_lemon.c"
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
CODE:
** As before, subsequent error messages are suppressed until
** three input tokens have been successfully shifted.
*/
if (yypParser->yyerrcnt yyerrcnt = 3;
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
if (yyendofinput){
yy_parse_failed(yypParser);
}
yymajor = YYNOCODE;
#endif
}
} while (yymajor != YYNOCODE && yypParser->yyidx >= 0);
return;
}
int main()
{
void* pParser = ParseAlloc(malloc);
Parse(pParser, Variable_token, 0);
Parse(pParser, Equal, 0);
Parse(pParser, Num_literal_token, 0);
Parse(pParser, Semicolon, 0);
Parse(pParser, 0, 0);
ParseFree(pParser, free);
getchar();
return 0;
}
出力されたファイルは拡張子が .c であるにも関わらずiostream等のC++標準ライブラリをインクルードしているし、その関係でそのままだとコンパイルが通りません。
そこで、拡張子を .cpp にしてあげる必要があります。(少なくともVisualStudio2013Expressの初期設定のままだと、そうする必要があります。)
また、main関数ですが、別ファイルに書くとLemonの関数のプロトタイプ宣言を自分で書くはめになるため、生成されたファイルに直接書き足します。
そうです。生成されたヘッダーファイルにはLemonの関数のプロトタイプ宣言は含まれていないのです!
ここがbisonとの大きな違いの一つで、不親切な部分だと思います。
さらに、assert.hがデフォルトではインクルードされていないために、エラーが出ます。
文法規則ファイルのインクルード部でインクルード文を書いてあげる必要があります。
最後に、これが最も重要なことです。
Lemonの場合、文法規則ファイルの定義で、一番先頭のものは一意である必要があります。
つまり、
CODE:
program ::= something.
は問題ないが、
CODE:
program ::= something.
program ::= another.
はエラーになるということです。
次回はflexと連携させます。
それでは、良いプログラミングライフを!