#c #yacc #lex
#c #yacc #лексический
Вопрос:
В моем файле lex есть:
word [^{}"=,tn@\ ]
{ {
return(LBRACE);
}
} {
return(RBRACE);
}
{word} {
yylval = yytext; printf("WORD=%s",yytext); return(WORD);
}
Мой файл yacc имеет:
phrase: LBRACE WORD RBRACE {printf("LBRACE %s RBRACEn",$2);};
При вводе:
{FooBar}
Я получаю:
WORD=FooBar
LBRACE FooBar} RBRACE
Я не уверен, почему я получаю дополнительную правую скобку, хотя я печатаю всего 2 доллара, что должно быть идеально
Ответ №1:
Здесь:
{word} {
yylval = yytext; printf("WORD=%s",yytext); return(WORD);
}
Значение yytext допустимо только при обработке этой лексемы. Как только вы переходите к следующей лексеме, содержимое буфера может быть перезаписано. Таким образом, сохранение указателя yytext не принесет вам никакой пользы. Вам нужно скопировать токен из буфера.
{word} { yylval = (char*)calloc(yylen 1, sizeof(char));
strncpy(yylval, yytext, yylen); // Remember you need to free this.
return WORD;
}
Комментарии:
1. Спасибо за ответ! Я думаю, вы имеете в виду глобальную переменную
yyleng
, верно? Кроме того, не должно лиstrncpy
быть большеyyleng 1
символов, чтобы получить завершающий null? Еслиstrndup
используется, это добавило бы завершающий null самостоятельно.2. @crypto: Да, я имею в виду глобальный yylen, предоставленный lex. Вам не нужен strncpy для копирования yylen 1, потому что я использую calloc(), который гарантирует обнуление возвращаемой базовой памяти. Таким образом, не имеет значения, добавляет strncpy дополнительный » или нет, поскольку это все равно будет ‘ 0’.
Ответ №2:
Вам решать, сохранять значение yytext
(через yylval
) в WORD
рабочей среде. Это просто указатель на рабочее пространство lex. Вы видите изменение рабочего пространства после его синтаксического анализа RBRACE
. Представьте себе правило yacc, подобное LBRACE WORD COMMA WORD LBRACE
, и что бы там происходило.
Если вы не хотите создавать отдельное производство, я думаю, вы можете сделать LBRACE WORD { code to strdup yylval } RBRACE { ... }
Комментарии:
1. Почему существует разница в значении
$2
amp; переданнойyylval
строке?2.
yylval
это не «строка» как таковая, это указатель , который указывает на личные данные lex. Вы владеетеyylval
, но вы не владеете тем, на что это указывает. Она действительна только для данного терминального символа между моментом, которыйyylex()
возвращается, и повторным вызовом. Попробуйтеyylval = strdup(yytext)
понять, что я имею в виду.3. strdup небезопасен. Нет гарантии, что lex-буфер завершается ‘ 0’. Вам нужно использовать yylen для извлечения необходимой вам части буфера.