2017-01-07 9 views
1

フレックスとバイソンを使って単純化したPython 3のパーサを作成しなければなりません。これらの2つのエラーを取得しています。ターミナルには78行目の79行目書かれた。私は形式のこの種を持つクラスから他の「.L」の例を持っており、彼らは正常に動作FLEXの「認識できないルール」と「致命的な解析エラー」

これは私が

%option noyywrap 

%{ 
#define YYSTYPE double 
#include "scanner.tab.h" 
#include <stdlib.h> 
#include <string> 

extern int flag; 
extern int line; 
%} 

DELIMITER [ ]+|[/t]+ 

KEYWORD  False|class|finally|is|return|None|continue|for|lambda|try|True|def|from|nonlocal|while|and|del|global|not|with|as|elif|if|or|yield|assert|else|import|pass|break|except|in|raise 

OPERATOR  ([+\[email protected]&|^~])|(\*{1,2})|(\/{1,2})|(<[=<]?)|(>[=>]?)|(==)|! 

COMMENT  #.+ 

IDENTIFIER [a-zA-Z_][a-zA-Z0-9_]* 
ID_ERR  [0-9]{IDENTIFIER} 

STRINGESCAPESEQ [\\]. 
SHORTSTRINGCHAR1 [^\\'\n]* 
SHORTSTRINGCHAR2 [^\\"\n]* 
SHORTSTRINGITEM1 {SHORTSTRINGCHAR1}|{STRINGESCAPESEQ} 
SHORTSTRINGITEM2 {SHORTSTRINGCHAR2}|{STRINGESCAPESEQ} 
STRING  [']{SHORTSTRINGITEM1}*[']|(["]{SHORTSTRINGITEM2}*["]) 
STRING_ERR ['].[^'\n\t]*|["].[^"\n\t]* 

BINDIGIT  [01] 
BININTEGER 0[bB]{BINDIGIT}+ 
BIN_ERR1  0[Bb]+{BINDIGIT}+ 

DIGIT  [0-9] 
NONZERODIGIT  [1-9] 
INTEGER  {NONZERODIGIT}{DIGIT}*|[0]+ 
INT_ERR1  {INTEGER}[a-zA-Z]{DIGIT} 
INT_ERR2  [-+]{INTEGER} 
INT_ERR3  [0+]{INTEGER} 

INTPART  {DIGIT}+ 
EXPONENT  [eE][+-]*{INTPART} 
FRACTION  [\.]{INTPART} 
EXPONENTFLOAT ({INTPART}|{POINTFLOAT}){EXPONENT} 
POINTFLOAT {INTPART}*{FRACTION}|{INTPART}[\.] 
FLOATNUMBER {POINTFLOAT}|{EXPONENTFLOAT} 
FLOAT_ERR_POINT {INTPART}*[\.]+{DIGIT}+[\.]*{DIGIT}*|{INTPART}[\.]+ 
FLOAT_ERR_SIGN ([-+]{FLOATNUMBER}) 
FLOAT_ERR_LETTER {FLOATNUMBER}[A-Za-z]+ 

IMAGINARYNUMBER ({FLOATNUMBER}|{INTPART})[jJ] 

%% 

{DELIMITER}  { } 
{KEYWORD}  { return KEYWORD; } 
{OPERATOR}  { } 
{COMMENT}  { printf("Line %d: Found COMMENT\n", line); } 
{IDENTIFIER}  { printf("Line %d: Found IDENTIFIER %s\n", line, yytext);     return IDENTIFIER; } 
{ID_ERR}  { printf("Line %d: !!ERROR!!\tWrong IDENTIFIER statement %s\n", line, yytext);   return ID_ERR;} 
{STRING}  { printf("Line %d: Found STRING %s\n", line, yytext);      return STRING; } 
{STRING_ERR}  { printf("Line %d: !!ERROR!!\tWrong STRING statement %s\n", line, yytext);   return STRING_ERR;} 
{BININTEGER}  { printf("Line %d: Found BINARY INTEGER NUMBER %s\n", line, yytext);     return BININTEGER; } 
{BIN_ERR1}  { printf("Line %d: !!ERROR!!\tWrong BINARY NUMBER statement, too many 'Bb's%s\n", line, yytext); return BIN_ERR1;} 
{INTEGER}  { printf("Line %d: Found INTEGER NUMBER %s\n", line, yytext);     return INTEGER; } 
{INT_ERR1}  { printf("Line %d: !!ERROR!!\tWrong INT statement %s\n", line, yytext);    return INT_ERR1;} 
{INT_ERR2}  { printf("Line %d: !!ERROR!!\tWrong INT statement, '+/-' found %s\n", line, yytext);   return INT_ERR2;} 
{INT_ERR3}  { printf("Line %d: !!ERROR!!\tWrong INT statement, first digit(s) zeros %s\n", line, yytext); return INT_ERR3;} 
{FLOATNUMBER}  { printf("Line %d: Found FLOAT NUMBER %s\n", line, yytext);     return FLOATNUMBER; } 
{FLOAT_ERR_POINT} { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, too many '.' %s\n", line, yytext);  return FLOAT_ERR_POINT;} 
{FLOAT_ERR_POINT} { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, '+/-' FOUND %s\n", line, yytext);  return FLOAT_ERR_SIGN;} 
{FLOAT_ERR_LETTER { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, letter FOUND %s\n", line, yytext);  return FLOAT_ERR_LETTER;} 
{IMAGINARYNUMBER} { printf("Line %d: Found IMAGINARY NUMBER %s\n", line, yytext);     return IMAGINARYNUMBER; } 
.   { printf("Line %d: UNKNOWN TOKEN:%s", line, yytext); BEGIN(error);} 
\n     { line++; } 
<<EOF>>   { printf("#END OF FILE\n"); exit(0); } 

を書かれたものであるフルエラー出力:あり

flex scanner.l 
scanner.l:79: unrecognized rule 
scanner.l:79: fatal parse error 
+0

完全なエラー出力を質問に貼り付けることはできますか? – snakecharmerb

+0

もちろん、ちょうど – spyros

答えて

3

行74で最後に行方不明ブレースです:

{FLOAT_ERR_LETTER { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, letter FOUND %s\n", line, yytext);  return FLOAT_ERR_LETTER;} 
       ^<--- here 

将来の読者にこの答えを有用にするために漠然とした試みで

、問題は簡単なタイプミスであることから、ここで私が問題を発見した方法です:

for n in {57..79}; do head -n$n g.l | flex -o /dev/null -w || { echo $n; break; } done 

後の行で致命的なエラーがほとんどの時間フレックス入力の終了は、中括弧やその他の同様の問題が発生した結果ですが、ファイル全体を校正することは痛みを伴います。上記のようなトリックは、時間を大幅に節約することができます。 (それは常にそれほど単純ではない。この場合には、何のアクションは複数行にわたっていない。)


あなたがそのエラーを修正したら、あなたはいくつかのパターンを一致させることができないことを発見します。パターンはライン72({FLOAT_ERR_POINT})と同一なので、ライン73は照合できません。 0Bの後に数字が続き、そのパターンにはIDERRと一致しています(奇妙なことに、1つの数字に続けて識別子が付いているため)65行目と66行目(BININTEGERBIN_ERR1)は一致しません。 (あなたはおそらく[[:digit:]]+{IDENTIFIER}を意味していたでしょう)全体的に、正しいトークンのパターンよりも決して優先しないように、エラーパターンを最後に置くべきです。これにより、エラートークンを書くのがずっと簡単になります。 (BIN_ERR1IDERR前に来る必要がありますように、また、あなたは、より一般的なものの前に特定のエラーパターンを配置する必要があります。)

いくつかの他のコメント:

あなたはフレックス一致パターンを見たい場合は、--debug(または-dを追加します)をコード全体に振りかざすのではなく、コマンドラインにprintfコマンドを振りかざすだけです。何が起こっているかを示す良い仕事をし、ファイル全体を編集することなくオンとオフを切り替えることができます。

<意見> 全体として、入力ファイルのようにフレックスマクロを過剰に使用することはあまり役に立ちません。実際には、マクロのあらゆる使用法を調べなければならないので、仕様を読みにくくします。個人的には、私はそれらを数回使用する必要があるときだけマクロを使用します。それだけでは、単に組み込みの文字クラスを隠す方法ではない場合は[[:digit:]]です。 < /意見>

+0

に感謝して、このすべてを書く時間と情報に感謝します。 – spyros

関連する問題