简单的Bison脚本上的分段错误

时间:2014-01-22 03:58:21

标签: c++ c bison yacc lex

好的,我正在用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错误。

我做错了什么?

3 个答案:

答案 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);
}