2

g++を使用しておもちゃの言語用のスキャナーとパーサーをコンパイルしようとしています。これが私が使用するすべてのファイルのコードです(必要に応じて、pastebin他の場所に投稿できます)。

caesar.ll

/* Simple scanner for a Caesar language */
%{
#include "caesar.tab.h"
#include <iostream>
#include <string>
int chars = 0;
int words = 0;
int lines = 0;
%}

/* Define constants */
OWS            [" "\t]*
COMMA          {OWS}","{OWS}
ID             [A-Za-z_][A-Za-z0-9_]*
INT            ([0-9]+)|("0x"[A-Ha-h0-9]+)
FLOAT          [0-9]+"."[0-9]+
BSTREAM        b[\'\"].*[\'\"]
USTREAM        u?[\'\"].*[\'\"]
ARRAY          {LBRACE}({INT}|{FLOAT})({COMMA}({INT}|{FLOAT})){RBRACE}
LIST           {LBRACKET}.*({COMMA}.*){RBRACKET}
RANGE          {LBRACE}{INT}":"{INT}(":"{INT})?{RBRACE}
ARGS           {ID}({COMMA}{ID})*
LPARENTHESIS   "("{OWS}
RPARENTHESIS   {OWS}")"
LBRACE         "{"{OWS}
RBRACE         {OWS}"}"
LBRACKET       "["{OWS}
RBRACKET       {OWS}"]"

%%
%{
/*============================================================================*/
/* Define types */
/*============================================================================*/
%}
{INT} {
  cout << "int: " << yytext << endl;
  yylval = atoi(yytext);
  return INT;
} /* int type */

{FLOAT} {
  cout << "float: " << yytext << endl;
  yylval = atof(yytext);
  return FLOAT;
} /* float type */

{BSTREAM} {
  cout << "bstream: " << yytext << endl;
  return BSTREAM;
} /* bstream type */

{USTREAM} {
  cout << "ustream: " << yytext << endl;
  return USTREAM;
} /* ustream type */

%{
/*============================================================================*/
/* Define operators */
/*============================================================================*/
%}
"+"    { return ADD; }
"-"    { return SUB; }
"*"    { return MUL; }
"/"    { return DIV; }
"//"   { return FDIV; }
"|"    { return ABS; }
"\n"   { return EOL; }

%{
/*============================================================================*/
/* Define statements */
/*============================================================================*/
%}
{RANGE} {
  cout << "range: " << yytext << endl;
  return RANGE;
} /* range function */

%%

caesar.yy

/* Simple parser for a Caesar language */
%{
#include <iostream>
using namespace std;
%}

/* Define built-in types */
%token INT FLOAT BSTREAM USTREAM 
%token ADD SUB MUL DIV FDIV ABS
%token EOL

%%

calclist: /* nothing */
  | calclist exp EOL {
      cout << $2 << endl;
    }
  | calclist EOL {
      cout << ">>> ";
    }
  ;

exp: factor
  | exp ADD exp { $$ = $1 + $3; }
  | exp SUB factor { $$ = $1 - $3; }
  | exp ABS factor { $$ = $1 | $3; }
  ;

factor: term
  | factor MUL term { $$ = $1 * $3; }
  | factor DIV term { $$ = $1 / $3; }
  ;

term: INT
  | ABS term { $$ = $2 >= 0? $2 : - $2; }
  ;

%%

main()
{
  cout << ">>> ";
  yyparse();
}

yyerror(char *error)
{
  cerr << error;
}

Makefile

caesar: caesar.ll caesar.yy
    bison -d caesar.yy
    flex caesar.ll
    g++ -o $@ caesar.tab.cc lex.yy.c -lfl

を使用してコンパイルしようとするとmake、いくつかのエラーが表示されます。

bison -d caesar.yy
caesar.yy: conflicts: 3 shift/reduce
flex caesar.ll
g++ -o caesar caesar.tab.cc lex.yy.c -lfl
caesar.tab.cc: In function 'int yyparse()':
caesar.tab.cc:1281:16: error: 'yylex' was not declared in this scope
caesar.tab.cc:1470:35: error: 'yyerror' was not declared in this scope
caesar.tab.cc:1612:35: error: 'yyerror' was not declared in this scope
caesar.yy: At global scope:
caesar.yy:46:20: error: ISO C++ forbids declaration of 'yyerror' with no type [-fpermissive]
caesar.ll:3:24: fatal error: caesar.tab.h: No such file or directory
compilation terminated.
make: *** [caesar] Error 1

私を手伝ってくれますか?ありがとう!

更新:関数の型が正しくない場合のエラーはすでに修正されています。

4

3 に答える 3

4

最初に明らかなエラーを修正します -- caesar.yy の先頭に宣言を追加します。

int yylex(void);
void yyerror(const char *);

mainandの型を返しますyyerror(注 - constyyerror の引数に追加して、渡された文字列リテラルに関する警告を黙らせました)。

caesar.ll にも同様の簡単な修正が必要です。

#include "caesar.tab.hh"
using namespace std;

これで、実際のエラーを確認できます:

caesar.yy: conflicts: 3 shift/reduce
caesar.ll: In function ‘int yylex()’:
caesar.ll:79:10: error: ‘RANGE’ was not declared in this scope

最初の 2 つ目 -- スキャナは、定義されていないトークン RANGE を返そうとしています。to を追加%token RANGEcaesaer.yyて定義することはできますが、文法でそれ (または or のような他のさまざまなトークン) を使用しないため、構文エラーが発生するだけですBSTREAMUSTREAM

それが文法の衝突につながります。これらは実際にはエラーではありません (警告のようなものです) が、注意を払う必要があります。bisonのコマンドに-v フラグを追加すると、競合に関する情報をMakefile含むファイルが得られます。caesaer.output

3 つの競合はすべて状態 16 から発生しており、.output ファイルで確認できます。

state 16

    5 exp: exp . ADD exp
    5    | exp ADD exp .
    6    | exp . SUB factor
    7    | exp . ABS factor

    ADD  shift, and go to state 10
    SUB  shift, and go to state 11
    ABS  shift, and go to state 12

    ADD       [reduce using rule 5 (exp)]
    SUB       [reduce using rule 5 (exp)]
    ABS       [reduce using rule 5 (exp)]
    $default  reduce using rule 5 (exp)

これは、3 つの競合すべてがexp: exp ADD expルールに起因していることを示しています。左再帰と右再帰の両方のルールを持つことは常にあいまいですが、この場合の修正は明らかです。それを に変更しexp: exp ADD factor、残りのルールと一致させます。

于 2012-10-23T01:45:20.107 に答える
3

http://dinosaur.compilertools.net/flex/flex_19.htmlg++での使用方法については、こちらをお読みくださいflex。ここでの問題は、Cモードで使用していて、Cレクサーを生成することです。スイッチflexで使用。-+

于 2012-10-22T22:15:35.827 に答える
0

FWIW、一致するルールを確認するためにコードを手動で計測しても意味がありません。Flex と Bison の両方が無料でそれを行います。Flex については http://westes.github.io/flex/manual/Debugging-Options.html を Bisonについてはhttp://www.gnu.org/software/bison/manual/bison.html#Tracingを参照してください。

于 2012-10-23T14:59:03.027 に答える