我正在尝试使用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
你能帮助我吗?谢谢!
UPDATE :我已修复错误的函数类型错误。
答案 0 :(得分:4)
首先修复明显的错误 - 将声明添加到caesar.yy的顶部:
int yylex(void);
void yyerror(const char *);
并返回main
和yyerror
的类型(注意 - 我还在yyerror的参数中添加了const
来消除有关传递给它的字符串文字的警告。)
你需要对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
第二个 - 您的扫描仪正在尝试返回未定义的令牌RANGE。
您可以将%token RANGE
添加到caesaer.yy
进行定义,但在您的语法中不使用它(或BSTREAM
或USTREAM
等各种其他令牌)时,它只会导致语法错误。
这带给我们语法冲突。这些不是真正的错误(更像是警告),但你确实想要关注它们。在bison
中的Makefile
命令中添加-v标志,您将获得一个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
,与其他规则匹配。
答案 1 :(得分:3)
http://dinosaur.compilertools.net/flex/flex_19.html请阅读本文,了解如何将g++
与flex
一起使用。这里的问题是你在C
模式下使用它并生成C
词法分析器。将flex
与-+
切换一起使用。
答案 2 :(得分: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。