更新 添加' INT'和' STRING'类型到primary_expression解决了许多(不是全部)错误,尽管它不是ANSI C yacc语法的一部分。哦,好吧,我现在必须到期。
我正在编写编译器并且在我的生活中,我无法确定为什么这个语法给我一个语法错误。任何能够发现这里发生了什么的人都将不胜感激。这是语法
%locations
%defines
%token-table
%union {
int value;
char symbol;
char *str;
};
%{
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int yylex();
int yyparse(void);
void yyerror(const char *str);
void lyyerror(YYLTYPE t, char *str, ...);
extern FILE *yyin;
%}
%start program
%type <value> type
%type <value> compound_instruction
%type <value> instruction
%type <value> expression_instruction
%type <value> iteration_instruction
%type <value> select_instruction
%type <value> jump_instruction
%type <value> expression
%type <value> assignment
%type <value> instruction_list
%type <value> cond_instruction
%type <value> condition
%type <value> expression_additive
%type <value> expression_multiplicative
%type <value> unary_expression
%type <value> expression_postfixee
%type <value> primary_expression
%token INT
%token STRING
%token CONST_INT
%token CONST_STRING
%token IDENT
%token EXTERN
%token IF
%token ELSE
%token WHILE
%token DO
%token RETURN
%token FOR
%token THEN
%token ASSIGNMENT
%token LESSTHAN
%token EQUAL
%token GREATERTHAN
%token LESSTHANEQUAL
%token GREATERTHANEQUAL
%token DIFF
%left PLUS
%left MINUS
%left MULTI
%left DIV
%left SHIFTRIGHT
%left SHIFTLEFT
%left MODULO
%%
program :
external-declaration
| program external-declaration
;
external-declaration :
declaration // Declaration Global
| EXTERN declaration // Set Extern attribute
| function-definition
;
function-definition :
type function_declarator decl_glb_fct compound_instruction
// generate code function
;
decl_glb_fct :
// Get function name - Create a spot to store the function - set attributes
;
declaration :
type declarator_list ';'
;
type :
INT // set INT
| STRING // set String
;
declarator_list :
declarator // Propagate code
| declarator_list ',' declarator
;
declaration_list :
declaration // Set locals
| declaration_list declaration // Set locals
;
declarator :
IDENT // Create Variable
| function_declarator // Create Function
;
function_declarator :
IDENT '(' ')' // Create function name
| IDENT '(' parameter_list ')' // Create partial function
;
parameter_list :
parameter_declaration
| parameter_list ',' parameter_declaration // Insert parameters
;
parameter_declaration :
type IDENT // Type declaration
;
instruction :
';'
| compound_instruction {$$=$1;}
| expression_instruction {$$=$1;}
| iteration_instruction {$$=$1;}
| select_instruction {$$=$1;}
| jump_instruction {$$=$1;}
;
expression_instruction :
expression ';'
| assignment ';'
;
assignment :
IDENT ASSIGNMENT expression
;
compound_instruction :
block_start declaration_list instruction_list block_end {$$=$3;}
| block_start declaration_list block_end
| block_start instruction_list block_end {$$=$2;}
| block_start block_end
;
block_start :
'{' // Init your hash table - symbol table
;
block_end :
'}' // Empty hash table
;
instruction_list :
instruction {$$=$1;}
| instruction_list instruction {$$=$2;}
;
select_instruction :
cond_instruction instruction
| cond_instruction instruction ELSE instruction
;
cond_instruction :
IF '(' condition ')' {$$=$3;}
;
iteration_instruction :
WHILE '(' condition ')' instruction // Handle while loop
| DO instruction WHILE '(' condition ')'
| FOR '(' assignment ';' condition ';' assignment ')' instruction
;
jump_instruction:
RETURN expression ';'
;
condition :
expression comparison_operator expression
;
comparison_operator :
EQUAL
| DIFF
| LESSTHAN
| GREATERTHAN
| LESSTHANEQUAL
| GREATERTHANEQUAL
;
expression :
expression_additive {$$=$1;}
| expression SHIFTLEFT expression_additive // Compute expression
| expression SHIFTRIGHT expression_additive // Compute expression
;
expression_additive :
expression_multiplicative {$$=$1;}
| expression_additive PLUS expression_multiplicative // Compute expression
| expression_additive MINUS expression_multiplicative // Compute expression
;
expression_multiplicative :
unary_expression{$$=$1;}
| expression_multiplicative MULTI unary_expression
| expression_multiplicative DIV unary_expression
| expression_multiplicative MODULO unary_expression
;
unary_expression:
expression_postfixee {$$=$1;}
| MINUS unary_expression
;
expression_postfixee :
primary_expression {$$=$1;}
| IDENT '(' argument_expression_list')'
| IDENT '(' ')'
;
argument_expression_list:
expression
| argument_expression_list',' expression
;
primary_expression :
IDENT
| CONST_INT
| CONST_STRING
| '(' expression ')'
;
%%
这是lex文件。
%option noyywrap
%option stack
%option yylineno
%s COMMENT
%s MACRO
%s ENDOFLINE
%s DEFINE
%s STRING
%{
#include "calc2.tab.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
//#define YY_DECL extern "C" int yylex()
//#define YYSTYPE int
//extern YYSTYPE yylval;
#define YY_USER_ACTION
extern YY_BUFFER_STATE yy_scan_string(const char *str);
yy_buffer_state* main_buffer = 0;
yy_buffer_state* expansion_buffer = 0;
std::string var,bar,biz;
%}
%%
[ \t\n]+
^"#include ".*\n {
// can put code to "store" include files here, or else switch to a 'FILE' state
//BEGIN DEFINE;
}
"if" { ECHO; /*printf(" IF\n") */; return IF;}
"else" { ECHO; /*printf(" ELSE\n") */; return ELSE;}
"while" { ECHO; /*printf(" WHILE\n") */; return WHILE;}
"do" { ECHO; /*printf(" DO\n") */; return DO;}
"return" { ECHO; /*printf(" RETURN\n") */; return RETURN;}
"for" { ECHO; /*printf(" FOR\n") */; return FOR;}
"then" { ECHO; /*printf(" THEN\n") */; return THEN;}
"=" { ECHO; /*printf(" ASSIGNMENT\n") */; return ASSIGNMENT;}
"+" { ECHO; /*printf(" PLUS_OP\n") */; yylval.symbol = yytext[0]; return PLUS;}
"(" { ECHO; /*printf(" L_PARENTHESIS\n") */; return LEFTPARENS ;}
")" { ECHO; /*printf(" R_PARENTHESIS\n") */; return RIGHTPARENS ;}
"-" { ECHO; /*printf(" MINUS_OP\n") */; yylval.symbol = yytext[0]; return MINUS;}
"*" { ECHO; /*printf(" MULT_OP\n") */; yylval.symbol = yytext[0]; return MULTI;}
"/" { ECHO; /*printf(" DIV_OP\n") */; yylval.symbol = yytext[0]; return DIV;}
"%" { ECHO; /*printf(" MODULO_OP\n") */; yylval.symbol = yytext[0]; return MODULO;}
"<<" { ECHO; /*printf(" LEFT_SHIFT\n") */; yylval.symbol = yytext[0]; return SHIFTLEFT;}
">>" { ECHO; /*printf(" RIGHT_SHIFT\n") */; yylval.symbol = yytext[0]; return SHIFTRIGHT;}
"==" { ECHO; /*printf(" COMPARISON_OP\n") */; }
"!=" { ECHO; /*printf(" NOT_EQUAL\n") */; yylval.value = atoi(yytext); return DIFF;}
"<" { ECHO; /*printf(" LESS_THAN\n") */; yylval.value = atoi(yytext); return INF;}
">" { ECHO; /*printf(" GREATER_THAN\n") */; yylval.value = atoi(yytext); return SUP;}
"<=" { ECHO; /*printf(" LESS_THAN_OR_EQUAL\n") */; yylval.value = atoi(yytext); return INFEQUAL;}
">=" { ECHO; /*printf(" GREATER_THAN_OR_EQUAL\n") */; yylval.value = atoi(yytext); return SUPEQUAL;}
"int" { ECHO; /*printf(" INT DECLARATION\n") */; return INT;}
"string" { ECHO; /*printf(" STRING DECLARATION\n") */; return STRING;}
"extern" { ECHO; /*printf(" EXTERN\n") */; return EXTERN;}
";" { ECHO; /*printf(" SEMICOLON\n") */; yylval.symbol = yytext[0]; return ';';}
"{" { ECHO; /*printf(" LEFT_BRACE\n") */; yylval.symbol = yytext[0]; return '{';}
"}" { ECHO; /*printf(" RIGHT_BRACE\n") */; yylval.symbol = yytext[0]; return '}';}
"," { ECHO; /*printf(" COMMA\n") */; yylval.symbol = yytext[0]; return ',';}
[0-9]+ { ECHO; /*printf(" INTEGER\n") */; yylval.value = atoi(yytext); return INT;}
"\""[^"\""\n]*"\"" { ECHO; /*printf(" STRING_LITERAL\n") */; yylval.str = strdup(yytext); return STRING;}
"\""[^"\""\n]*$ { ECHO; /*printf(" * Unterminated String *\n") */; }
"const int" { ECHO; /*printf(" CONST INT DECLARATION\n") */; return CONST_INT;}
"const string" { ECHO; /*printf(" CONST STRING DECLARATION\n")*/; return CONST_STRING;}
"/*" { BEGIN COMMENT ;}
<COMMENT>"*/" { BEGIN INITIAL ;}
<COMMENT>([^*]|\n)+|.
<COMMENT><<EOF>> {
//ECHO;
/*printf("* Unterminated Comment *\n")*/;
yyterminate();
}
<DEFINE>"#define " { // probably redundant but not wanting to break code right now
BEGIN MACRO;
}
[a-zA-Z_][a-zA-Z0-9_]* { // looks for IDENTIFIERS not sharing name with macro NAME
//if(strncmp(yytext, var.c_str(),strlen(yytext))==0) {
// ** this is sort of a hack, because without grammar, hard to resolve naming collisions... **
// ** except it helps that I can rely on UPPERCASE macro naming convention
// main_buffer = YY_CURRENT_BUFFER;
// expansion_buffer = yy_scan_string(biz.c_str()); // lex macro expansion and send to stdout
// yy_switch_to_buffer(expansion_buffer);
// }
// this will create one superfluous IDENTIFIER, not sure how to rid of it, yet
// also, it's late and I'm tired of guessing what i've missed that wasn't in the actual project descript
// else ECHO; /*printf(" IDENTIFIER\n")*/ return IDENT;
ECHO;
//yylval.str = strdup(yytext);
return IDENT;
}
<MACRO>[A-Z]+" " { // find macro NAME
var = yytext; BEGIN ENDOFLINE;
}
<ENDOFLINE>.*\n { // store the rest in string variable
biz = yytext; BEGIN INITIAL;
}
<<EOF>> {
if (expansion_buffer)
{
// We were doing an expansion, return to where
// we were.
yy_switch_to_buffer(main_buffer);
yy_delete_buffer(expansion_buffer);
expansion_buffer = 0;
}
else
yyterminate();
}
%%
仅使用lex文件输出样本。
extern int bar( int baz );
int foo(int count)
{
int sum;
for (int 1 = 1; i <= count; i++)
sum = sum + foo2(i);
return sum;
}
int main(void) {
string "car";
printf("%d", IF);
const string("Hello, World!");
/* comments */
if(1)
return 1;
return 0;
}
externToken: 263 (extern)
intToken: 258 (int)
barToken: 262 (bar)
(Token: 282 (()
intToken: 258 (int)
bazToken: 262 (baz)
)Token: 283 ())
;Token: 59 (;)
intToken: 258 (int)
fooToken: 262 (foo)
(Token: 282 (()
intToken: 258 (int)
countToken: 262 (count)
)Token: 283 ())
{Token: 123 ({)
intToken: 258 (int)
sumToken: 262 (sum)
;Token: 59 (;)
forToken: 269 (for)
(Token: 282 (()
intToken: 258 (int)
1Token: 258 (1)
=Token: 271 (=)
1Token: 258 (1)
;Token: 59 (;)
iToken: 262 (i)
<=Token: 275 (<=)
countToken: 262 (count)
;Token: 59 (;)
iToken: 262 (i)
+Token: 278 (+)
+Token: 278 (+)
)Token: 283 ())
sumToken: 262 (sum)
=Token: 271 (=)
sumToken: 262 (sum)
+Token: 278 (+)
foo2Token: 262 (foo2)
(Token: 282 (()
iToken: 262 (i)
)Token: 283 ())
;Token: 59 (;)
returnToken: 268 (return)
sumToken: 262 (sum)
;Token: 59 (;)
}Token: 125 (})
intToken: 258 (int)
mainToken: 262 (main)
(Token: 282 (()
voidToken: 262 (void)
)Token: 283 ())
{Token: 123 ({)
stringToken: 5 (string)
"car"Token: 5 ("car")
;Token: 59 (;)
printfToken: 262 (printf)
(Token: 282 (()
"%d"Token: 5 ("%d")
,Token: 44 (,)
IFToken: 262 (IF)
)Token: 283 ())
;Token: 59 (;)
const stringToken: 261 (const string)
(Token: 282 (()
"Hello, World!"Token: 5 ("Hello, World!")
)Token: 283 ())
;Token: 59 (;)
ifToken: 264 (if)
(Token: 282 (()
1Token: 258 (1)
)Token: 283 ())
returnToken: 268 (return)
1Token: 258 (1)
;Token: 59 (;)
returnToken: 268 (return)
0Token: 258 (0)
;Token: 59 (;)
}Token: 125 (})
要解析的上述程序的示例输出。
extern declare EXTERN
int INT type
bar(int INT type
baz PARAMETER
);int INT type
foo(int INT type
count PARAMETER
){int INT type
sum;for(intParse Error:
syntax error, unexpected INT, expecting IDENT
有趣的是,如果我将语义动作添加到函数定义中,如下所示:
function-definition : {printf("print something");}
type function_declarator decl_glb_fct compound_instruction
然后我得到一个不同的解析器错误:
extern declare EXTERN
int INT type
bar(int INT type
baz declare PARAMETER
);int INT type
foo(int INT type
count declare PARAMETER
){Parse Error:
*** syntax error, unexpected '{', expecting ';' or ',' ***
这是一种我不明白的行为。