0
下面是我解析C源代碼的yacc代碼。我對此有點新,這是一個已經存在的代碼。編譯Yacc代碼
{
%{
#include <stdio.h>
#include <string.h>
#include "Expression.c"
%}
%token Identifier
%token Number
%token '=' '+' '-' '*' '/' ',' ';' '(' ')' '{' '}' '[' ']' '<' '>'
%token INT
%token CHAR
%token FLOAT
%token LONG
%token DOUBLE
%token RETURN
%token IF
%token ELSE
%token EQ /* == */
%token BADTOKEN
%%
program
: function
{ $$ = $1; }
| program function
{ $$ = binaryNode("",$1,$2);}
| error '}'
function:
typename Identifier '(' formal.arguments ')' function.body
{ $$ = attachAllChildren($2,$1,$4,$6); }
typename
: INT
{ $$ = leafNode("INT");}
| CHAR
{ $$ = leafNode("CHAR"); }
| DOUBLE
{ $$ = leafNode("DOUBLE"); }
| LONG
{ $$ = leafNode("LONG"); }
| FLOAT
{ $$ = leafNode("FLOAT"); }
formal.arguments
: /* empty */
{ $$ = NULL; }
| formal.argument.list
{ $$ = $1; }
formal.argument.list
: formal.argument
{ $$ = $1; }
| formal.argument.list ',' formal.argument
{ $$ = binaryNode(",", $1, $3); }
formal.argument
: typename Identifier
{ $$ = attachChild($2, $1); }
function.body
: '{' '}'
{ $$ = NULL; }
| '{' statements '}'
{ $$ = $2; }
statements
: statement
{ $$ = $1; }
| statements statement
{ $$ = attachChild($1,$2);}
statement
: declaration
{ $$ = $1; }
| RETURN expression ';' /* return statement */
{ $$ = unaryNode("RETURN", $2); }
| if.statement
{ $$ =$1; }
| term '=' expression ';' /* assignment */
{ $$ = binaryNode("=", $1, $3); }
| expression ';'
{ $$ = $1; }
| '{' statements '}'
{ $$ = $2; }
| ';' /* null statement */
{ $$ = NULL; }
declaration
: typename Identifier ';'
{ $$ = attachChild($2,$1); }
| typename Identifier '[' Number ']' ';' /* array */
{ $$ = attachSiblings($2, $1, $4); }
if.statement
: IF '(' expression ')' statement
{ $$ = ternaryNode("IF",$3,$5, NULL); }
| IF '(' expression ')' statement ELSE statement
{ $$ = ternaryNode("IF", $3, $5, $7); }
expression
: additive.expression
{ $$ = $1; }
| expression EQ additive.expression
{ $$ = binaryNode("=",$1, $3); }
| expression '>' additive.expression
{ $$ = binaryNode(">", $1, $3); }
| expression '<' additive.expression
{ $$ = binaryNode("<", $1, $3); }
additive.expression
: term
{ $$ = $1; }
| additive.expression '+' term
{ $$ = binaryNode("+", $1, $3);}
| additive.expression '-' term
{ $$ = binaryNode("-", $1, $3);}
term
: Identifier
{ $$ = leafNode($1);}
| Number
{ $$ = leafNode($1);}
| Identifier '(' opt.actual.arguments ')' /* function call */
{ $$ = attachChild($1,$3);}
| Identifier '[' expression ']' /* array access */
{ $$ = attachChild($1,$3); }
| '(' expression ')'
{ $$ = $2;}
opt.actual.arguments
: /* empty */
{ $$ = NULL;}
| actual.arguments
{ $$=$1; }
actual.arguments
: expression
{ $$ = $1; }
| actual.arguments ',' expression
{ $$ = binaryNode(",",$1, $3); }
%%
yyerror(msg)
char* msg;
{
#if !defined(YYBISON)
extern int yynerrs;
++yynerrs;
#endif
fprintf(stderr, "Error: %s\n",msg);
}
main()
{
extern int yynerrs;
yyparse();
fprintf(stderr, "%d errors.\n", yynerrs);
return 0;
}
}
在編譯上面的代碼時,我得到一個警告,說明代碼中有1個shift/reduce衝突。我該如何解決這個問題?
絕對是的,但是我的詞法分析器應該生成什麼樣的標記(我主要希望只生成算術操作及其相應的操作符?我也可以直接刪除節點賦值語句,直到抽象語法樹在上面的解析器中有關嗎? –
@AbhijeetMohanty:我不確定我是否理解你的後續問題,你的詞法分析器需要生成你的解析器使用的標記,你的.y文件的賦值語句(在動作中)建立一個AST 。如果你不想要/需要一個AST,那麼你可以擺脫它們 - 動作對解析的語言沒有影響(除非它們將信息反饋給詞法分析器),它們只是在解析器減少規則時運行。 –