sailor@sailor:~/Test/compiler-labs/build$ make
[ 2%] [BISON][syntax] Building parser with bison 3.8.2
syntax_analyzer.y:89.15-24: warning: symbol FLOATCONST redeclared [-Wother]
89 | %token <fval> FLOATCONST
| ^~~~~~~~~~
syntax_analyzer.y:43.20-29: note: previous declaration
43 | IDENT INTCONST FLOATCONST HEX_CONST OCT_CONST STRING_CONST CHAR_CONST
| ^~~~~~~~~~
syntax_analyzer.y:89.15-24: error: %type redeclaration for FLOATCONST
89 | %token <fval> FLOATCONST
| ^~~~~~~~~~
syntax_analyzer.y:43.20-29: note: previous declaration
43 | IDENT INTCONST FLOATCONST HEX_CONST OCT_CONST STRING_CONST CHAR_CONST
| ^~~~~~~~~~
make[2]: *** [src/parser/CMakeFiles/syntax.dir/build.make:74: src/parser/syntax_analyzer.c] Error 1
make[1]: *** [CMakeFiles/Makefile2:350: src/parser/CMakeFiles/syntax.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
sailor@sailor:~/Test/compiler-labs/build$ make clean
sailor@sailor:~/Test/compiler-labs/build$ cmake …
– Found LLVM 14.0.0
– Using LLVMConfig.cmake in: /usr/lib/llvm-14/cmake
– Configuring done
– Generating done
– Build files have been written to: /home/sailor/Test/compiler-labs/build
sailor@sailor:~/Test/compiler-labs/build$ make
[ 2%] [BISON][syntax] Building parser with bison 3.8.2
syntax_analyzer.y:89.14-23: warning: symbol ‘FloatConst’ is used, but is not defined as a token and has no rules [-Wother]
89 | %type <node> FloatConst
| ^~~~~~~~~~
syntax_analyzer.y: warning: 1 nonterminal useless in grammar [-Wother]
syntax_analyzer.y:89.14-23: warning: nonterminal useless in grammar: FloatConst [-Wother]
89 | %type <node> FloatConst
| ^~~~~~~~~~
syntax_analyzer.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
syntax_analyzer.y: warning: 18 reduce/reduce conflicts [-Wconflicts-rr]
syntax_analyzer.y: note: rerun with option ‘-Wcounterexamples’ to generate conflict counterexamples
syntax_analyzer.y:464.14-467.1: warning: rule useless in parser due to conflicts [-Wother]
464 | PrimaryExp : Floatnum {
| ^~~~~~~~~~
[ 4%] [FLEX][lex] Building scanner with flex 2.6.4
[ 6%] Building C object src/parser/CMakeFiles/syntax.dir/syntax_analyzer.c.o
syntax_analyzer.y: In function ‘yyparse’:
syntax_analyzer.y:459:17: error: ‘struct _parse_tree_node’ has no member named ‘float_val’
syntax_analyzer.y:460:17: error: ‘struct _parse_tree_node’ has no member named ‘data_type’
syntax_analyzer.y:460:31: error: ‘FLOAT_TYPE’ undeclared (first use in this function)
syntax_analyzer.y:460:31: note: each undeclared identifier is reported only once for each function it appears in
syntax_analyzer.y:466:17: error: ‘struct _parse_tree_node’ has no member named ‘data_type’
make[2]: *** [src/parser/CMakeFiles/syntax.dir/build.make:87: src/parser/CMakeFiles/syntax.dir/syntax_analyzer.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:351: src/parser/CMakeFiles/syntax.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
%option noyywrap
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include “parse_tree.h”
#include “syntax_analyzer.h”
int lines = 1;
int pos_start = 1;
int pos_end = 1;
char token_name[20];
void new_node(char *text) {
yylval.node = new_parse_tree_node(text);
}
void handle_float_suffix(char* text) {
char *endptr;
if (text[strlen(text)-1] == ‘f’ || text[strlen(text)-1] == ‘F’) {
text[strlen(text)-1] = ‘\0’;
}
yylval.fval = strtof(text, &endptr);
}
#define SET_TOKEN(name) do {
pos_start = pos_end;
pos_end += yyleng;
strcpy(token_name, #name);
new_node(yytext);
} while(0)
%}
%x COMMENT
DIGIT [0-9]
OCTAL [0-7]
HEX [0-9a-fA-F]
ID [a-zA-Z_][a-zA-Z0-9_]*
EXPONENT [Ee][±]?{DIGIT}+
HEX_EXP [Pp][±]?{DIGIT}+
DEC_INT 0|([1-9]{DIGIT}*)
OCT_INT 0{OCTAL}+
HEX_INT 0[xX]{HEX}+
FLOAT_SUFFIX [fF]
DEC_FLOAT ({DIGIT}+.{DIGIT}*|.{DIGIT}+){EXPONENT}?{FLOAT_SUFFIX}?
HEX_FLOAT 0xX{HEX_EXP}{FLOAT_SUFFIX}?
%%
<INITIAL>{
“/” { BEGIN(COMMENT); pos_start = pos_end; pos_end += 2; }
“//”. { pos_start = pos_end; pos_end += yyleng; }
/* 数字常量 */
{DEC_INT} { SET_TOKEN(INTCONST); return INTCONST; }
{OCT_INT} { SET_TOKEN(INTCONST); return INTCONST; }
{HEX_INT} { SET_TOKEN(INTCONST); return INTCONST; }
{DEC_FLOAT} {
handle_float_suffix(yytext);
SET_TOKEN(FLOATCONST);
return FLOATCONST;
}
{HEX_FLOAT} {
handle_float_suffix(yytext);
SET_TOKEN(FLOATCONST);
return FLOATCONST;
}
/* 关键字 */
“int” { SET_TOKEN(INT); return INT; }
“float” { SET_TOKEN(FLOAT); return FLOAT; }
“void” { SET_TOKEN(VOID); return VOID; }
“return” { SET_TOKEN(RETURN); return RETURN; }
“if” { SET_TOKEN(IF); return IF; }
“else” { SET_TOKEN(ELSE); return ELSE; }
“while” { SET_TOKEN(WHILE); return WHILE; }
“break” { SET_TOKEN(BREAK); return BREAK; }
“continue” { SET_TOKEN(CONTINUE); return CONTINUE; }
“const” { SET_TOKEN(CONST); return CONST; }
/* 运算符 /
“;” { SET_TOKEN(SEMICOLON); return SEMICOLON; }
“,” { SET_TOKEN(COMMA); return COMMA; }
“=” { SET_TOKEN(ASSIGN); return ASSIGN; }
“<” { SET_TOKEN(LT); return LT; }
“<=” { SET_TOKEN(LET); return LET; }
“>” { SET_TOKEN(GT); return GT; }
“>=” { SET_TOKEN(GET); return GET; }
“==” { SET_TOKEN(EQ); return EQ; }
“!=” { SET_TOKEN(NEQ); return NEQ; }
“+” { SET_TOKEN(ADD); return ADD; }
“-” { SET_TOKEN(SUB); return SUB; }
"" { SET_TOKEN(MUL); return MUL; }
“/” { SET_TOKEN(DIV); return DIV; }
“%” { SET_TOKEN(MOD); return MOD; }
“&&” { SET_TOKEN(AND); return AND; }
“||” { SET_TOKEN(OR); return OR; }
“!” { SET_TOKEN(NOT); return NOT; }
/* 括号 */
“(” { SET_TOKEN(LPARENTHESIS); return LPARENTHESIS; }
“)” { SET_TOKEN(RPARENTHESIS); return RPARENTHESIS; }
“[” { SET_TOKEN(LBRACKET); return LBRACKET; }
“]” { SET_TOKEN(RBRACKET); return RBRACKET; }
“{” { SET_TOKEN(LBRACE); return LBRACE; }
“}” { SET_TOKEN(RBRACE); return RBRACE; }
/* 标识符 */
{ID} { SET_TOKEN(IDENT); return IDENT; }
/* 空白处理 */
[ \t\r]+ { pos_start = pos_end; pos_end += yyleng; }
\n { lines++; pos_start = 1; pos_end = 1; }
. { SET_TOKEN(ERROR); return ERROR; }
}
<COMMENT>{
“*/” { BEGIN(INITIAL); pos_end += 2; }
\n { lines++; pos_start = 1; pos_end = 1; }
. { pos_end++; }
<<EOF>> { fprintf(stderr, “Error: Unclosed comment at line %d\n”, lines); exit(1); }
}
%%
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include “parse_tree.h”
extern int yylex();
extern int yyparse();
extern int yyrestart();
extern FILE * yyin;
extern int lines;
extern char * yytext;
extern int pos_end;
extern int pos_start;
parse_tree *gt;
void yyerror(const char *s);
parse_tree_node *node(const char *node_name, int children_num, …);
%}
%union {
struct _parse_tree_node *node;
float fval;
}
%token <node>
// 运算符
EQ NEQ LE GE ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ASSIGN
LT LET GT GET ADD SUB MUL DIV MOD AND OR NOT
LSHIFT RSHIFT INC DEC BIT_NOT BIT_AND BIT_OR BIT_XOR
// 分隔符
LPARENTHESIS RPARENTHESIS LBRACE RBRACE LBRACKET RBRACKET SEMICOLON COMMA DOT ARROW COLON QUESTION
// 关键字
IF ELSE WHILE FOR RETURN INT CHAR FLOAT VOID STRUCT TYPEDEF DO BREAK CONTINUE CONST
// 标识符和常量
IDENT INTCONST HEX_CONST OCT_CONST STRING_CONST CHAR_CONST
// 错误标记
ERROR
%type <node> Program
%type <node> CompUnit
%type <node> Decl
%type <node> ConstDecl
%type <node> VarDecl
%type <node> ConstDefList
%type <node> BType
%type <node> ConstDef
%type <node> ConstExpList
%type <node> ConstInitVal
%type <node> ConstInitValList
%type <node> VarDef
%type <node> VarDeclList
%type <node> InitVal
%type <node> InitValList
%type <node> FuncDef
%type <node> FuncFParams
%type <node> FuncFParam
%type <node> ExpList
%type <node> Block
%type <node> BlockList
%type <node> BlockItem
%type <node> Stmt
%type <node> Exp
%type <node> Cond
%type <node> LVal
%type <node> PrimaryExp
%type <node> Number
%type <node> UnaryExp
%type <node> UnaryOp
%type <node> FuncRParams
%type <node> MulExp
%type <node> AddExp
%type <node> RelExp
%type <node> EqExp
%type <node> LAndExp
%type <node> LOrExp
%type <node> ConstExp
%type <node> Integer
%type <node> Floatnum
%type <node> FloatConst
%token <fval> FLOATCONST
// 指定起始符号
%start Program
%%
Program : CompUnit {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("Program", 1, $̲1);
gt->roo…
; } ;
CompUnit : CompUnit Decl {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"CompUnit", 2, $̲1, $2);
}
| Com…
= node(“CompUnit”, 2, $1, $2); } | Decl {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"CompUnit", 1, $̲1);
}
| FuncDef…
= node(“CompUnit”, 1, $1); } ;
Decl : ConstDecl {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Decl", 1, $̲1);
}
| VarDecl…
= node(“Decl”, 1, $1); } ;
ConstDecl : CONST BType ConstDefList SEMICOLON {
$$ = node(“ConstDecl”, 4, $1, $2, $3, $4);
}
;
ConstDefList : ConstDef {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 28: …stDefList", 1, $̲1);
}
| ConstDe…
= node(“ConstDefList”, 3, $1, $2, $3); } ;
BType : INT {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 21: …de("BType", 1, $̲1);
}
| FLOAT {…
= node(“BType”, 1, $1); } ;
ConstDef : IDENT ConstExpList ASSIGN ConstInitVal {
$$ = node(“ConstDef”, 4, $1, $2, $3, $4);
}
;
ConstExpList : /* ε */ {
ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 29: …tExpList", 0);
}̲
| ConstExpList…
= node(“ConstExpList”, 4, $1, $2, $3, $4); } ;
ConstInitVal : ConstExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 28: …stInitVal", 1, $̲1);
}
| LBRACE …
= node(“ConstInitVal”, 3, $1, $2, $3); } | LBRACE RBRACE { $$ = node(“ConstInitVal”, 2, $1, $2); } ;
ConstInitValList : ConstInitVal {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 32: …itValList", 1, $̲1);
}
| ConstIn…
= node(“ConstInitValList”, 3, $1, $2, $3); } ;
VarDecl : BType VarDef VarDeclList SEMICOLON {
$$ = node(“VarDecl”, 4, $1, $2, $3, $4);
}
;
VarDeclList : /* ε */ {
ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 28: …DeclList", 0);
}̲
| VarDeclList …
= node(“VarDeclList”, 3, $1, $2, $3); } ;
VarDef : IDENT ConstExpList {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("VarDef", 2, $̲1, $2);
}
| IDE…
= node(“VarDef”, 4, $1, $2, $3, $4); } ;
InitVal : Exp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("InitVal", 1, $̲1);
}
| LBRACE …
= node(“InitVal”, 3, $1, $2, $3); } | LBRACE RBRACE { $$ = node(“InitVal”, 2, $1, $2); } ;
InitValList : InitVal {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 27: …itValList", 1, $̲1);
}
| InitVal…
= node(“InitValList”, 3, $1, $2, $3); } ;
FuncDef : BType IDENT LPARENTHESIS RPARENTHESIS Block {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("FuncDef", 5, $̲1, $2, $3, $4, …
= node(“FuncDef”, 5, $1, $2, $3, $4, $5); } | VOID IDENT LPARENTHESIS FuncFParams RPARENTHESIS Block {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("FuncDef", 6, $̲1, $2, $3, $4, …
= node(“FuncDef”, 6, $1, $2, $3, $4, $5, $6); } ;
FuncFParams : FuncFParam {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 27: …ncFParams", 1, $̲1);
}
| FuncFPa…
= node(“FuncFParams”, 3, $1, $2, $3); } ;
FuncFParam : BType IDENT {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …uncFParam", 2, $̲1, $2);
}
| BTy…
= node(“FuncFParam”, 5, $1, $2, $3, $4, $5); } ;
ExpList : /* ε */ {
ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 24: …"ExpList", 0);
}̲
| ExpList LBRA…
= node(“ExpList”, 4, $1, $2, $3, $4); } ;
Block : LBRACE BlockList RBRACE {
$$ = node(“Block”, 3, $1, $2, $3);
}
;
BlockList : /* ε */ {
ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 26: …lockList", 0);
}̲
| BlockList Bl…
= node(“BlockList”, 2, $1, $2); } ;
BlockItem : Decl {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 25: …BlockItem", 1, $̲1);
}
| Stmt {
…
= node(“BlockItem”, 1, $1); } ;
Stmt : LVal ASSIGN Exp SEMICOLON {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 4, $̲1, $2, $3, $4);…
= node(“Stmt”, 2, $1, $2); } | SEMICOLON {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 1, $̲1);
}
| Block {…
= node(“Stmt”, 1, $1); } | IF LPARENTHESIS Cond RPARENTHESIS Stmt {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 5, $̲1, $2, $3, $4, …
= node(“Stmt”, 7, $1, $2, $3, $4, $5, $6, $7); } | WHILE LPARENTHESIS Cond RPARENTHESIS Stmt {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 5, $̲1, $2, $3, $4, …
= node(“Stmt”, 2, $1, $2); } | CONTINUE SEMICOLON {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 20: …ode("Stmt", 2, $̲1, $2);
}
| RET…
= node(“Stmt”, 3, $1, $2, $3); } | RETURN SEMICOLON { $$ = node(“Stmt”, 2, $1, $2); } ;
Exp : AddExp {
$$ = node(“Exp”, 1, $1);
}
;
Cond : LOrExp {
$$ = node(“Cond”, 1, $1);
}
;
LVal : IDENT ExpList {
$$ = node(“LVal”, 2, $1, $2);
}
;
PrimaryExp : LPARENTHESIS Exp RPARENTHESIS {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …rimaryExp", 3, $̲1, $2, $3);
}
|…
= node(“PrimaryExp”, 1, $1); } | Number { $$ = node(“PrimaryExp”, 1, $1); } ;
Number : Integer {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("Number", 1, $̲1);
}
| Floatnu…
= node(“Number”, 1, $1); } ;
UnaryExp : PrimaryExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"UnaryExp", 1, $̲1);
}
| IDENT L…
= node(“UnaryExp”, 4, $1, $2, $3, $4); } | IDENT LPARENTHESIS RPARENTHESIS {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 24: …"UnaryExp", 3, $̲1, $2, $3);
}
|…
= node(“UnaryExp”, 2, $1, $2); } ;
UnaryOp : ADD {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("UnaryOp", 1, $̲1);
}
| SUB {
…
= node(“UnaryOp”, 1, $1); } | NOT { $$ = node(“UnaryOp”, 1, $1); } ;
FuncRParams : Exp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 27: …ncRParams", 1, $̲1);
}
| FuncRPa…
= node(“FuncRParams”, 3, $1, $2, $3); } ;
MulExp : UnaryExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("MulExp", 1, $̲1);
}
| MulExp …
= node(“MulExp”, 3, $1, $2, $3); } | MulExp DIV UnaryExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("MulExp", 3, $̲1, $2, $3);
}
|…
= node(“MulExp”, 3, $1, $2, $3); } ;
AddExp : MulExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("AddExp", 1, $̲1);
}
| AddExp …
= node(“AddExp”, 3, $1, $2, $3); } | AddExp SUB MulExp { $$ = node(“AddExp”, 3, $1, $2, $3); } ;
RelExp : AddExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("RelExp", 1, $̲1);
}
| RelExp …
= node(“RelExp”, 3, $1, $2, $3); } | RelExp LET AddExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("RelExp", 3, $̲1, $2, $3);
}
|…
= node(“RelExp”, 3, $1, $2, $3); } | RelExp GET AddExp { $$ = node(“RelExp”, 3, $1, $2, $3); } ;
EqExp : RelExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 21: …de("EqExp", 1, $̲1);
}
| EqExp E…
= node(“EqExp”, 3, $1, $2, $3); } | EqExp NEQ RelExp { $$ = node(“EqExp”, 3, $1, $2, $3); } ;
LAndExp : EqExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 23: …("LAndExp", 1, $̲1);
}
| LAndExp…
= node(“LAndExp”, 3, $1, $2, $3); } ;
LOrExp : LAndExp {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 22: …e("LOrExp", 1, $̲1);
}
| LOrExp …
= node(“LOrExp”, 3, $1, $2, $3); } ;
ConstExp : AddExp {
$$ = node(“ConstExp”, 1, $1);
}
;
Integer : INTCONST {
$$ = node(“Integer”, 1, $1);
}
;
Floatnum : FLOATCONST {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …loatConst", 1, $̲1);
->float_val = $1;
$$->data_type = FLOAT_TYPE; } ;
PrimaryExp : Floatnum {
ParseError: KaTeX parse error: Can't use function '$' in math mode at position 26: …rimaryExp", 1, $̲1);
->data_type = FLOAT_TYPE; } ; %%
void yyerror(const char * s)
{
fprintf(stderr, “Syntax Error at line %d, column %d: %s. Near ‘%s’\n”, lines, pos_start, s, yytext);
exit(1);
}
parse_tree *parse(const char *input_path)
{
if (input_path != NULL) {
if (!(yyin = fopen(input_path, “r”))) {
fprintf(stderr, “[ERR] Open input file %s failed.\n”, input_path);
exit(1);
}
} else {
yyin = stdin;
}
lines = pos_start = pos_end = 1;
gt = new_parse_tree();
yyrestart(yyin);
yyparse();
return gt;
}
parse_tree_node *node(const char *name, int children_num, …)
{
parse_tree_node *p = new_parse_tree_node(name);
parse_tree_node *child;
if (children_num == 0) {
child = new_parse_tree_node(“epsilon”);
parse_tree_add_child(p, child);
} else {
va_list ap;
va_start(ap, children_num);
for (int i = 0; i < children_num; ++i) {
child = va_arg(ap, parse_tree_node *);
parse_tree_add_child(p, child);
}
va_end(ap);
}
return p;
}
给出改正后的完整代码
#ifndef __PARSETREE_H__
#define __PARSETREE_H__
#include <stdio.h>
#define PARSE_TREE_NODE_NAME_MAX 5000
struct _parse_tree_node {
struct _parse_tree_node * parent; // 父节点指针
struct _parse_tree_node * children[10]; // 子节点数组
int children_num; // 子节点数量
char name[PARSE_TREE_NODE_NAME_MAX]; // 节点名称
};
typedef struct _parse_tree_node parse_tree_node;
// 创建一个新的解析树节点
parse_tree_node * new_parse_tree_node(const char * name);
// 向父节点添加子节点
int parse_tree_add_child(parse_tree_node * parent, parse_tree_node * child);
// 删除解析树节点
void del_parse_tree_node(parse_tree_node * node, int recursive);
// 解析树结构
struct _parse_tree {
parse_tree_node * root; // 解析树根节点
};
typedef struct _parse_tree parse_tree;
// 创建一个新的解析树
parse_tree* new_parse_tree();
// 删除解析树
void del_parse_tree(parse_tree * tree);
// 打印解析树
void print_parse_tree(FILE * fout, parse_tree * tree);
#endif /* PARSETree.h */