好的,我正在用Lex / Bison(Yacc)进行一些实验,并且考虑到我的C技能相当生疏(我曾经用所有这些工具创建编译器和东西,现在我迷失了前几行......: - S),我需要你的帮助。
这就是我的Parser的样子:
%{
#include <stdio.h>
#include <string.h>
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
}
%}
%union
{
char* str;
}
%token <str> WHAT IS FIND GET SHOW WITH POSS OF NUMBER WORD
%type <str> statement
%start statements
%%
statement
: GET { printf("get\n"); }
| SHOW { printf("%s\n",$1); }
| OF { printf("of\n"); }
;
statements
: statement
| statements statement
;
问题:
所以,基本上,只要解析器遇到“get”,它就会打印“get”。等等。
但是,在尝试打印“show”时(使用$1
说明符),它会发出segmentation fault
错误。
我做错了什么?
答案 0 :(得分:1)
Lex返回一个代表令牌的数字,您需要访问yytext以获取解析内容的文本。
类似
statement : GET { printf("get\n"); }
| SHOW { printf("%s\n",yytext); }
| OF { printf("of\n"); }
;
传播终端的文本,我继续将非终端与终端关联并传回char *并开始构建解析树。注意我省略了类型decl和create_sww_ASTNode(char *,char *,char *)的实现;但是,重要的是并非所有非终结符都将返回相同的类型,因为number是一个整数,单词return char * sww返回astNode(或者你提出的任何通用抽象语法树结构)。通常超出非终端代表终端,它都是AST的东西。
sww : show word word
{
$$ = create_sww_ASTNode($1,$2,$3);
}
;
word : WORD
{
$$ = malloc(strlen(yytext) + 1);
strcpy($$,yytext);
}
;
show : SHOW
{
$$ = malloc(strlen(yytext) + 1);
strcpy($$,yytext);
}
;
number : NUMBER
{
$$ = atoi(yytext);
}
;
答案 1 :(得分:1)
您没有显示您的词法分析器代码,但问题可能是您从未将yylval
设置为任何内容,因此当您在解析器中访问$1
时,它会包含垃圾并导致崩溃。您的词法分析器操作需要将yylval.str
设置为有效的内容:
"show" { yylval.str = "SHOW"; return SHOW }
[a-z]+ { yylval.str = strdup(yytext); return WORD; }
答案 2 :(得分:0)
好的,所以这就是答案(有人可以告诉我,一旦我在SO中发布了一个问题,我总是想出解决方案吗?)
问题是解析器本身不,但实际上是Lexer。
问题是:当你告诉{ printf("%s\n",$1); }
时,我们实际告诉它打印yylval
(默认为int
,而不是字符串)。
因此,诀窍是将适当的标记转换为字符串。
这是我的(更新的)Lexer文件:
%{
#include <stdio.h>
#include "parser.tab.h"
void toStr();
%}
DIGIT [0-9]
LETTER [a-zA-Z]
LETTER_OR_SPACE [a-zA-Z ]
%%
find { toStr(); return FIND; }
get { toStr(); return GET; }
show { toStr(); return SHOW; }
{DIGIT}+(\.{DIGIT}+)? { toStr(); return NUMBER; }
{LETTER}+ { toStr(); return WORD; }
\n /* ignore end of line */;
[ \t]+ /* ignore whitespace */;
%%
void toStr()
{
yylval.str=strdup(yytext);
}