Ошибка сегментации на простом скрипте Bison

Хорошо, я провожу несколько экспериментов с Lex / Bison (Yacc), и учитывая, что мои навыки C довольно ржавые (я когда-то создавал компиляторы и прочее со всеми этими инструментами, и теперь я потерялся в первых нескольких строках …: -S), мне нужна твоя помощь.

Вот как выглядит мой парсер:

%{
#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». И так далее.

Тем не менее, при попытке напечатать «шоу» (используя $1 спецификатор) выдает segmentation fault ошибка.

Что я делаю неправильно?

1

Решение

Лекс возвращает число, представляющее токен, вам нужно получить доступ к yytext, чтобы получить текст того, что анализируется.

что-то вроде

statement               : GET { printf("get\n"); }
| SHOW  { printf("%s\n",yytext); }
| OF { printf("of\n"); }
;

Чтобы распространить текст терминалов, я связываю нетерминал с терминалом, возвращаю символ * и начинаю, например, строить дерево разбора. Обратите внимание, что я пропустил тип decl и реализацию create_sww_ASTNode (char *, char *, char *); Однако важно то, что не все нетерминалы будут возвращать один и тот же тип, поскольку число — это целое число, слово return char * sww return 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

Другие решения

Вы не показываете свой код лексера, но проблема, вероятно, в том, что вы никогда не устанавливали yylval ни к чему, поэтому при доступе $1 в парсере он содержит мусор, и вы получаете сбой. Ваши действия лексера должны быть установлены yylval.str к чему-то так будет действительно:

"show"   { yylval.str = "SHOW"; return SHOW }
[a-z]+   { yylval.str = strdup(yytext); return WORD; }
1

Итак, вот ответ (Может кто-нибудь сказать мне, что я всегда придумываю решение, как только я уже опубликовал вопрос здесь в SO? LOL!)

Проблема была не с самим парсером, но на самом деле с лексером.

Дело в том, что когда вы говорите это { 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);
}
0
По вопросам рекламы [email protected]