我的parser.y文件中没有冲突。但是引入构造我的句法树的动作导致了12个新的移位/减少冲突。你们对此有什么想法吗?
下面你有我的parser.y和编译日志。
Parser.y:
%{
#include <stdio.h>
#include "main.h"
#include "iks_ast.h"
%}
%union {
struct item_t *symbol;
struct node *tree;
}
%error-verbose
/* Declaração dos tokens da linguagem */
%token TK_PR_INT
%token TK_PR_FLOAT
%token TK_PR_BOOL
%token TK_PR_CHAR
%token TK_PR_STRING
%token TK_PR_IF
%token TK_PR_THEN
%token TK_PR_ELSE
%token TK_PR_WHILE
%token TK_PR_DO
%token TK_PR_INPUT
%token TK_PR_OUTPUT
%token TK_PR_RETURN
%token TK_OC_LE
%token TK_OC_GE
%token TK_OC_EQ
%token TK_OC_NE
%token TK_OC_AND
%token TK_OC_OR
%token<symbol> TK_LIT_INT
%token<symbol> TK_LIT_FLOAT
%token<symbol> TK_LIT_FALSE
%token<symbol> TK_LIT_TRUE
%token<symbol> TK_LIT_CHAR
%token<symbol> TK_LIT_STRING
%token<symbol> TK_IDENTIFICADOR
%token TOKEN_ERRO
%left TK_OC_OR TK_OC_AND
%left '<' '>' TK_OC_LE TK_OC_GE TK_OC_EQ TK_OC_NE
%left '+' '-'
%left '*' '/'
%nonassoc LOWER_THAN_ELSE
%nonassoc TK_PR_ELSE
%start programa
%type<symbol> decl_var
%type<symbol> cabecalho
%type<tree> programa
%type<tree> def_funcao
%type<tree> expressao
%type<tree> controle_fluxo
%type<tree> comando
%type<tree> chamada_funcao
%type<tree> entrada
%type<tree> saida
%type<tree> lista_expressoes
%type<tree> lista_expressoes_nao_vazia
%type<tree> retorna
%type<tree> bloco_comando
%type<tree> seq_comando
%type<tree> atribuicao
%type<tree> vetor_indexado
%%
programa: decl_global programa {$$ = $2;}
| def_funcao programa {$$ = create_node(IKS_AST_PROGRAMA); $$ = insert_child($$,$1); $1 = AST_link($1,$2);}
| {$$=NULL;}
;
decl_global: decl_var ';'
| decl_vetor ';'
| decl_var {error("Faltando o ';' no final do comando.", $1->line); return IKS_SYNTAX_ERRO;}
;
decl_local: decl_var ';' decl_local
|
;
/* Declaracao de variaveis e tipos*/
decl_var
: tipo_var TK_IDENTIFICADOR {$$ = $2;}
;
decl_vetor
: tipo_var TK_IDENTIFICADOR '[' TK_LIT_INT ']'
;
tipo_var: TK_PR_INT
| TK_PR_FLOAT
| TK_PR_BOOL
| TK_PR_CHAR
| TK_PR_STRING
;
/* Declaracao de funcao */
def_funcao: cabecalho decl_local bloco_comando {$$ = create_node(IKS_AST_FUNCAO); $$ = insert_child($$,$3);}
| cabecalho decl_local bloco_comando ';' {error("Declaração de função com ';' no final do comando.\n",$1->line); return IKS_SYNTAX_ERRO;}
;
chamada_funcao
: TK_IDENTIFICADOR '(' lista_expressoes ')' {$$ = AST_ident_exp(IKS_AST_CHAMADA_DE_FUNCAO,$1,$3);}
;
cabecalho: decl_var '(' lista_parametros ')' {$$ = $1;}
;
lista_parametros: lista_parametros_nao_vazia
|
;
lista_parametros_nao_vazia: parametro ',' lista_parametros_nao_vazia
| parametro
;
parametro: decl_var
;
comando: bloco_comando {$$ = $1;}
| controle_fluxo {$$ = $1;}
| atribuicao {$$ = $1;}
| entrada {$$ = $1;}
| saida {$$ = $1;}
| retorna {$$ = $1;}
| decl_var ';' {$$ = NULL;}
| chamada_funcao {$$ = $1;}
| ';' {$$ = NULL;}
;
bloco_comando: '{' seq_comando '}' {$$ = create_node(IKS_AST_BLOCO); $$ = insert_child($$,$2);}
;
seq_comando: seq_comando comando {$$ = AST_link($1,$2); }
| /* empty */ {//não sei se precisa
$$ = NULL;}
;
/* Atribuicoes de variaveis */
atribuicao: TK_IDENTIFICADOR '=' expressao {$$ = AST_ident_exp(IKS_AST_ATRIBUICAO,$1,$3);}
| vetor_indexado '=' expressao {$$ = create_node(IKS_AST_ATRIBUICAO); $$ = insert_child($$,$1); $$ = insert_child($$,$3); }
;
vetor_indexado
: TK_IDENTIFICADOR '[' expressao ']' { $$ = AST_ident_exp(IKS_AST_VETOR_INDEXADO,$1,$3);}
;
/* Entrada e Saida (Input e Output) */
entrada
: TK_PR_INPUT TK_IDENTIFICADOR {$$ = create_node(IKS_AST_INPUT); $$ = AST_input($$,$2);}
;
saida
: TK_PR_OUTPUT lista_expressoes_nao_vazia {$$ = create_node(IKS_AST_OUTPUT); $$ = insert_child($$,$2);}
;
lista_expressoes_nao_vazia: expressao ',' lista_expressoes_nao_vazia {$$ = AST_link($1,$3);}
| expressao {$$ = $1;}
;
retorna: TK_PR_RETURN expressao ';' {$$ = create_node(IKS_AST_RETURN); $$ = insert_child($$,$2);}
;
/* Fluxo de Controle */
controle_fluxo
: TK_PR_IF '(' expressao ')' TK_PR_THEN comando %prec LOWER_THAN_ELSE {$$ = AST_if($3,$6,NULL);}
| TK_PR_IF '(' expressao ')' TK_PR_THEN comando TK_PR_ELSE comando {$$ = AST_if($3,$6,$8);}
| TK_PR_WHILE '(' expressao ')' TK_PR_DO comando {$$ = AST_while(IKS_AST_WHILE_DO,$3,$6);}
| TK_PR_DO comando TK_PR_WHILE '(' expressao ')' {$$ = AST_while(IKS_AST_DO_WHILE,$2,$5);}
;
expressao: TK_IDENTIFICADOR {$$ = AST_ident_literal(IKS_AST_IDENTIFICADOR,$1);}
| TK_IDENTIFICADOR '[' expressao ']' {$$ = AST_ident_exp(IKS_AST_VETOR_INDEXADO,$1,$3);}
| TK_LIT_INT {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_FLOAT {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_FALSE {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_TRUE {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_CHAR {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_STRING {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| expressao '+' expressao {$$ = create_node(IKS_AST_ARIM_SOMA); $$ = AST_expression($$,$1,$3); }
| expressao '-' expressao {$$ = create_node(IKS_AST_ARIM_SUBTRACAO); $$ = AST_expression($$,$1,$3); }
| expressao '*' expressao {$$ = create_node(IKS_AST_ARIM_MULTIPLICACAO); $$ = AST_expression($$,$1,$3); }
| expressao '/' expressao {$$ = create_node(IKS_AST_ARIM_DIVISAO); $$ = AST_expression($$,$1,$3); }
| expressao '<' expressao {$$ = create_node(IKS_AST_LOGICO_COMP_L); $$ = AST_expression($$,$1,$3); }
| expressao '>' expressao {$$ = create_node(IKS_AST_LOGICO_COMP_G); $$ = AST_expression($$,$1,$3); }
| '+' expressao {$$ = $2;}
| '-' expressao {$$ = create_node(IKS_AST_ARIM_INVERSAO); $$ = AST_expression($$,$2,NULL);}
| '(' expressao ')' {$$ = $2;}
| expressao TK_OC_LE expressao {$$ = create_node(IKS_AST_LOGICO_COMP_LE); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_GE expressao {$$ = create_node(IKS_AST_LOGICO_COMP_GE); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_EQ expressao {$$ = create_node(IKS_AST_LOGICO_COMP_IGUAL); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_NE expressao {$$ = create_node(IKS_AST_LOGICO_COMP_DIF); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_AND expressao {$$ = create_node(IKS_AST_LOGICO_E); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_OR expressao {$$ = create_node(IKS_AST_LOGICO_OU); $$ = AST_expression($$,$1,$3);}
| '!' expressao {$$ = create_node(IKS_AST_LOGICO_COMP_NEGACAO); $$ = AST_expression($$,$2,NULL);}
| chamada_funcao {$$ = $1;}
;
lista_expressoes: lista_expressoes_nao_vazia {$$ = $1;}
| {$$ = NULL;}
;
%%
error(char *s, int line){
printf("Erro na linha %d: %s", line,s);
}
日志:
[ 10%] [BISON][parser] Building parser with bison 3.0.2
parser.y: warning: 12 shift/reduce conflicts [-Wconflicts-sr]
[ 20%] [FLEX][scanner] Building scanner with flex 2.5.35
Scanning dependencies of target main
[ 30%] Building C object CMakeFiles/main.dir/scanner.c.o
scanner.l:11:1: warning: data definition has no type or storage class [enabled by default]
scanner.l: In function ‘yylex’:
scanner.l:84:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:85:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:87:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:89:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:91:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:93:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:95:17: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l: In function ‘install_id’:
scanner.l:145:4: warning: return makes integer from pointer without a cast [enabled by default]
[ 40%] Building C object CMakeFiles/main.dir/parser.c.o
[ 50%] Building C object CMakeFiles/main.dir/src/main.c.o
[ 60%] Building C object CMakeFiles/main.dir/src/comp_tree.c.o
Linking C executable main
[100%] Built target main
答案 0 :(得分:1)
转移 - 减少冲突都是单一生产的结果,与语义行为无关。
制作是:
expressao : '!' expressao ;
问题是!
没有出现在优先列表中。
此外,您的语法可能不会按预期方式工作,因为您没有特定的优先声明来区分一元+
和-
运算符他们的二进制版本因此,-a*b
将解析为-(a*b)
而不是(-a)*b
。当然,对于整数运算,它们是相同的,但是使语法树更正确会更清晰。您可以通过添加
%right '!'
在所有%left
声明之后,然后将%prec '!'
添加到一元+
和-
制作的结尾。
我不知道为什么在添加语义操作时会出现问题。也许您还添加了!
的作品。