【发布时间】:2021-09-05 14:23:44
【问题描述】:
我正在尝试使用 flex-bison “从头开始”制作编译器。 我试图在网上寻求帮助,但我没有找到太多的东西 我设法找到了一本书:John Levine 的 flex & bison
它非常有用,但我不知道该怎么做。
这是我的弹性代码:
%option noyywrap
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parser.tab.h"
extern FILE *yyin;
extern FILE *yyout;
int line_no = 1;
//the function of lexer analysis. Return the token
int yylex();
//error function
void yyerror();
//print statement function
void print_return(char *token);
%}
%x ML_COMMENT
alphabet [a-zA-Z]
digit [0-9]
alphanumeric {alphabet}|{digit}
print [ -~]
underscore _
identifier ({alphabet}|{underscore})+({alphanumeric}|{underscore})*
integer "0"|[0-9]{digit}*
float_number "0"|{digit}*"."{digit}+
char \'{print}\'
%%
"PROGRAM" { print_return("PROGRAM"); return PROGRAM}
"%".* { print_return("COMMENT"); return COMMENT; }
"BREAK" { print_return("BREAK"); return BREAK; }
"VARS" { print_return("VARS"); return VARS; }
"STARTMAIN" { print_return("STARTMAIN"); return STARTMAIN; }
"ENDMAIN" { print_return("ENDMAIN"); return ENDMAIN;}
"IF" { print_return("IF"); return IF; }
"THEN" { print_return("THEN"); return THEN;}
"ELSEIF" { print_return("ELSEIF"); return ELSEIF; }
"ELSE" { print_return("ELSE"); return ELSE; }
"ENDIF" { print_return("ENDIF"); return ENDIF; }
"FOR" { print_return("FOR"); return FOR; }
"TO" { print_return("TO"); return TO; }
"STEP" { print_return("STEP"); return STEP; }
"ENDFOR" { print_return("ENDFOR"); return ENDFOR; }
"SWITCH" { print_return("SWITCH"); return SWITCH; }
"CASE" { print_return("CASE"); return CASE; }
"ENDSWITCH" { print_return("ENDSWITCH"); return ENDSWITCH; }
"RETURN" { print_return("RETURN"); RETURN; }
"FUNCTION" { print_return("FUN"); return FUN; }
"ENDFUNCTION" { print_return("ENDFUNCTION"); return ENDFUNCTION; }
"PRINT" { print_return("PRINT"); return PRINT; }
"WHILE" { print_return("WHILE"); return WHILE;}
"ENDWHILE" { print_return("ENDWHILE"); return ENDWHILE;}
";" { print_return("QM"); return QM; }
"\n" { line_no++; print_return("NEWLINE"); return NEWLINE; }
"\t" { print_return("INDENT"); return INDENT; }
"+=" { print_return("ADD_ASSIGN"); return ADD_ASSIGN; }
"-=" { print_return("SUB_ASSIGN"); return SUB_ASSIGN; }
"/=" { print_return("DIV_ASSIGN"); return DIV_ASSIGN; }
"%=" { print_return("MOD_ASSIGN"); return MOD_ASSIGN; }
"--" { print_return("DEC_OP"); return DEC_OP; }
"++" { print_return("INC_OP"); return INC_OP; }
"AND" { print_return("AND_OP"); return AND_OP; }
"OR" { print_return("OR_OP"); return OR_OP; }
"==" { print_return("EQ_OP"); return EQ_OP; }
">=" { print_return("GE_OP"); return GE_OP; }
"<=" { print_return("LE_OP"); return LE_OP; }
"!=" { print_return("NE_OP"); return NE_OP; }
"{" { print_return("L_BRACE"); return L_BRACE; }
"}" { print_return("R_BRACE"); return R_BRACE; }
"," { print_return("COMMA"); return COMMA; }
"=" { print_return("ASSIGN"); return ASSIGN; }
"(" { print_return("L_PAR"); return L_PAR; }
")" { print_return("R_PAR"); return R_PAR;}
"[" { print_return("L_BRACK"); return L_BRACK; }
"]" { print_return("R_BRACK"); return R_BRACK;}
"." { print_return("DOT"); return DOT; }
"_" { print_return("UNDERSCORE"); return UNDERSCORE; }
"-" { print_return("MINUS"); return MINUS; }
"+" { print_return("PLUS"); return PLUS; }
"*" { print_return("MUL"); return MUL; }
":" { print_return("COLON"); return COLON; }
"/" { print_return("DIV"); return DIV; }
"<" { print_return("LT"); return LT; }
">" { print_return("GT"); return GT; }
[ ] ;
. { yyerror("Unkown character"); }
{identifier} { print_return("ID"); strcpy(yylval.name, yytext); return IDENTIFIER; }
{integer} { yylval.integer_val = atoi(yytext); print_return("INTEGER"); return INTEGER; }
{float_number} { print_return("FLOAT"); return FLOAT; }
{char} { print_return("CHAR"); return CHAR; }
%%
/*---------------------------------------------------------------------------------------------------------------------*/
void print_return(char *token)
{
printf("Token: %s\t\t Line: %d\t\t Text: %s\n", token, line_no, yytext);
}
这是我的野牛文件:
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "print_console.c"
//pointer to input file of lexer
extern FILE *yyin;
//pointer to output file of lexer
extern FILE *yyout;
//line counter
extern int line_no;
//reads the input stream generates tokens
extern int yylex();
//temporary token save
extern char* yytext;
//Function Initilize
int yylex();
void yyerror(char *message);
%}
//struct for print_console
%union
{
char name[500];
int integer_val;
}
/* --------------------------------------- TOKENS ---------------------------------------*/
//starting symbol
%start PROGRAM
%token COMMENT
%token BREAK
%token VARS
%token QM
%token STARTMAIN
%token ENDMAIN
%token IF
%token THEN
%token ELSEIF
%token ELSE
%token ENDIF
%token FOR
%token TO
%token STEP
%token ENDFOR
%token SWITCH
%token CASE
%token ENDSWITCH
%token RETURN
%token FUNCTION
%token ENDFUNCTION
%token PRINT
%token WHILE
%token ENDWHILE
%token NEWLINE
%token INDENT
%token ADD_ASSIGN
%token SUB_ASSIGN
%token DIV_ASSIGN
%token MOD_ASSIGN
%token DEC_OP
%token INC_OP
%token AND_OP
%token OR_OP
%token EQ_OP
%token GE_OP
%token LE_OP
%token NE_OP
%token L_BRACE
%token R_BRACE
%token COMMA
%token COLON
%token ASSIGN
%token L_PAR
%token R_PAR
%token L_BRACK
%token R_BRACK
%token DOT
%token UNDERSCORE
%token MINUS
%token PLUS
%token MUL
%token DIV
%token LT
%token GT
%token FLOAT
%token CHAR
%token <name> IDENTIFIER
%token <integer_val> INTEGER
//type for access to $$
%type <integer_val> line int_op int_data
%type <name> calc_assignment
%%
/* --------------------------------------- BNF GRAMMAR ---------------------------------------*/
program: program line;
line: if_stmt {;}
| elseif_stmt {;}
| else_stmt {;}
| for_statement {;}
| function NEWLINE INDENT {;}
| function NEWLINE indent2 {;}
| function NEWLINE {;}
| function_call {;}
| comments NEWLINE {;}
| action {;}
| print NEWLINE {;}
| switch NEWLINE case NEWLINE {;}
| dictionaries NEWLINE {;}
| calc_assignment NEWLINE {;}
| NEWLINE {;} ;
/*--------- BREAK -------------*/
break:BREAK QM NEWLINE ;
/*--------- ACTION & indents -------------*/
indent2: INDENT INDENT;
indent3: INDENT INDENT INDENT;
indent4: INDENT INDENT INDENT INDENT;
indent5: INDENT INDENT INDENT INDENT INDENT;
action: INDENT line
| indent2 line
| indent3 line
| indent4 line
| indent5 line ;
/*--------- DATA TYPES -------------*/
data_type: CHAR
| INTEGER
| IDENTIFIER;
/*--------- FUNCTIONS --------------*/
function: FUNCTION IDENTIFIER L_PAR optional_parameters R_PAR ;
end_function: ENDFUNCTION NEWLINE;
function_call: IDENTIFIER L_PAR optional_parameters R_PAR
| IDENTIFIER L_PAR data_type R_PAR
| IDENTIFIER L_PAR data_type COMMA data_type R_PAR
| IDENTIFIER L_PAR data_type COMMA data_type COMMA data_type R_PAR;
/*------------ INSPECTORS -------------*/
inspector:IDENTIFIER operators IDENTIFIER
|IDENTIFIER operators INTEGER
|INTEGER operators IDENTIFIER
|INTEGER operators INTEGER ;
inspector_gen: inspector | inspector AND_OR_operators;
/*----------- IF & FOR STATEMENTS -------------*/
if_stmt:IF L_PAR inspector_gen R_PAR THEN NEWLINE action ;
elseif_stmt: ELSEIF L_PAR inspector_gen R_PAR NEWLINE action ;
else_stmt: ELSE NEWLINE action ;
end_if_stmt:ENDIF NEWLINE ;
for_statement: FOR IDENTIFIER COLON ASSIGN INTEGER TO INTEGER STEP INTEGER NEWLINE action;
end_for_statement: ENDFOR NEWLINE;
/*---------- SWITCH / CASE STATEMENT -----------------*/
switch: SWITCH L_PAR LT IDENTIFIER GT R_PAR NEWLINE action;
case: CASE L_PAR LT INTEGER GT R_PAR NEWLINE action;
end_switch: ENDSWITCH NEWLINE;
/*-------------- WHILE ---------------*/
while: WHILE L_PAR inspector_gen R_PAR NEWLINE action ;
end_wile: ENDWHILE NEWLINE;
/*-------------- OPERATORS ---------------*/
operators:EQ_OP
| GE_OP
| LE_OP
| NE_OP
| DEC_OP
| INC_OP
| LT
| GT;
AND_OR_operators:AND_OP
|OR_OP;
optional_parameters: IDENTIFIER
| optional_parameters COMMA IDENTIFIER ;
/*-------------- COMMENTS ---------------*/
comments: COMMENT;
/*-------------- PRINT ---------------*/
print: PRINT L_PAR data_type R_PAR QM;
/*-------------- MAIN ---------------*/
start_main: STARTMAIN NEWLINE action;
end_main: ENDMAIN NEWLINE ;
/* --- DICTIONARIES --- */
dictionaries: IDENTIFIER ASSIGN L_BRACE dictionary_data R_BRACE
| IDENTIFIER ASSIGN IDENTIFIER L_PAR L_BRACK L_PAR dictionary_data R_PAR R_BRACK R_PAR
IDENTIFIER ASSIGN IDENTIFIER L_PAR dictionary_data optional_parameters dictionary_data R_PAR ;
dictionary_data: data_type COLON data_type
|data_type COLON data_type COMMA dictionary_data
| data_type COMMA data_type optional_parameters
| IDENTIFIER ASSIGN data_type | /* empty */ ;
/* --- CALCULATE --- */
calc_assignment: IDENTIFIER ASSIGN int_op { Change($1, $3); };
int_op: int_data { $$ = $1; }
| int_op PLUS int_data { $$ = $1 + $3; }
| int_op MINUS int_data { $$ = $1 - $3; }
| int_op MUL int_data { $$ = $1 * $3; }
| int_op DIV int_data { $$ = $1 / $3; } ;
int_data: INTEGER { $$ = $1; }
| IDENTIFIER { $$ = Search($1) -> integer_val; };
%%
/* ------------------------------------------------ C FUNCTIONS -------------------------------------------- */
void yyerror(char *message){
printf("Error: \"%s\"\t in line %d. Token = %s\n", message, line_no, yytext);
exit(1);
}
/* ------------------------------------------ MAIN FUNCTION --------------------------------------------- */
int main(int argc, char *argv[]){
hashTable = (hash *) calloc(SIZE, sizeof(hash));
int flag;
yyin = fopen(argv[1],"r");
//yyparse(): reads tokens, executes actions
flag = yyparse();
fclose(yyin);
printf("Parsing finished succesfully!\n\n");
printf(" __________________________\n");
Print();
printf(" __________________________\n");
return flag;
}
我被困住了,不知道该怎么办。编译器就是不喜欢我的代码:
parser.y: warning: 9 nonterminals useless in grammar [-Wother]
parser.y: warning: 9 rules useless in grammar [-Wother]
parser.y:136.1-5: warning: nonterminal useless in grammar: break [-Wother]
136 | break:BREAK QM NEWLINE ;
| ^~~~~
parser.y:157.1-12: warning: nonterminal useless in grammar: end_function [-Wother]
157 | end_function: ENDFUNCTION NEWLINE;
| ^~~~~~~~~~~~
parser.y:177.1-11: warning: nonterminal useless in grammar: end_if_stmt [-Wother]
177 | end_if_stmt:ENDIF NEWLINE ;
| ^~~~~~~~~~~
parser.y:180.1-17: warning: nonterminal useless in grammar: end_for_statement [-Wother]
180 | end_for_statement: ENDFOR NEWLINE;
| ^~~~~~~~~~~~~~~~~
parser.y:188.1-10: warning: nonterminal useless in grammar: end_switch [-Wother]
188 | end_switch: ENDSWITCH NEWLINE;
| ^~~~~~~~~~
parser.y:191.1-5: warning: nonterminal useless in grammar: while [-Wother]
191 | while: WHILE L_PAR inspector_gen R_PAR NEWLINE action ;
| ^~~~~
parser.y:192.1-8: warning: nonterminal useless in grammar: end_wile [-Wother]
192 | end_wile: ENDWHILE NEWLINE;
| ^~~~~~~~
parser.y:217.1-10: warning: nonterminal useless in grammar: start_main [-Wother]
217 | start_main: STARTMAIN NEWLINE action;
| ^~~~~~~~~~
parser.y:218.1-8: warning: nonterminal useless in grammar: end_main [-Wother]
218 | end_main: ENDMAIN NEWLINE ;
| ^~~~~~~~
parser.y: warning: 48 shift/reduce conflicts [-Wconflicts-sr]
parser.y: warning: 68 reduce/reduce conflicts [-Wconflicts-rr]
parser.y:141.10-29: warning: rule useless in parser due to conflicts [-Wother]
141 | indent3: INDENT INDENT INDENT;
| ^~~~~~~~~~~~~~~~~~~~
parser.y:142.10-36: warning: rule useless in parser due to conflicts [-Wother]
142 | indent4: INDENT INDENT INDENT INDENT;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
parser.y:143.10-43: warning: rule useless in parser due to conflicts [-Wother]
143 | indent5: INDENT INDENT INDENT INDENT INDENT;
我知道我做错了什么。请帮我! 我不知道如何继续。
【问题讨论】:
标签: c compiler-construction bison flex-lexer