LINUX.ORG.RU

Бизон выдает ошибки

 , ,


0

0

Здравствуйте!Изучаю bison+flex. На данный момент необходимо выводить все слова(буквы,цифры и пробелы), остальное - пропускать. При компиляции бизон выдает ошибку,вида

bison.b:31.29-30: $1 шч `PRINT' эх шьххЄ юяшёрээюую Єшяр

flex.l

%{				// Начало блока, прямо копируемого в результирующий файл
#include <stdio.h> 
#include <string.h>
#include "p_bison.hpp"	// Файл, содержащий макроопределения сделанные в bison.b

extern YYSTYPE yylval;


%}				// Окончание блока, прямо копируемого в результирующий файл

comments   \/\*[^*]*\*+([^/*][^*]*\*+)*\/
formating	[\n\r\t\f]*
except_spaces [ ]{2,}
word [a-zA-Zа-яА-Я0-9 ]+



%%

{word}			{
					yylval.str=strdup(yytext); 
					return T_STRING;
				}
.+				// пропускаем остальное

%%

int yywrap()			// Функция обработки обнаружения конца файла
{
	return(1);		// После обнаружения конца файла прекратить парсинг
}

bison.b


%{					// Начало блока, прямо копируемого в результирующий файл
 
#include <stdio.h>
#include <string.h>

extern int yylex(void);		// Объявление внешней функции yylex
void yyerror(char *s);			// Объявление функции обработки ошибки

char out_str[255];
 


%}

%debug

%union
{
char* str;
}					
 
%token <str> T_STRING

%start PRINT

%%					// Начало секции определения правил

PRINT:
	| STR
	{
		printf("%s",$1);
	}
	;
STR:
	T_STRING
	| STR T_STRING
	; 

%%						
#include <stdio.h>

void yyerror(char *s)				// Функция сообщения об ошибке
{
	fflush(stdout);
	printf("\n%s\n", s);
}

$ LANG=«C» bison -d bison.b
bison.b:31.29-30: $1 of `PRINT' has no declared type

Открываешь документацию и понимаешь, что нужно сказать

%type <str> STR

Но твой код всё равно не будет работать так, как ты думаешь, ведь ты во-первых не определил какую строку STR должен отдавать вверх, после получения на вход «T_STRING T_STRING», а во-вторых

info flex «Flex is not matching my patterns in the same order that I defined them.»

kim-roader ★★ ()
Ответ на: комментарий от kim-roader

%type <str> STR

Упустил момент,спасибо.Подобное объявление нужно ведь только при использовании %union?

ты во-первых не определил какую строку STR должен отдавать вверх, после получения на вход «T_STRING T_STRING»

У меня не работали конструкции типа $$=$1; .Видимо как раз потому что не определил тип STR. Сейчас я убрал %union, использую один тип std::string. Но опять таки при компиляции такого кода, получаю результат в виде мусора между квадратными скобками при выполнении printf(«AT-RULE-CHARSET[ %s ]\n»,$$);. При использовании вместо $$ переменной out_str все работает правильно.

flex.l

%{				// Начало блока, прямо копируемого в результирующий файл
#include <stdio.h> 
#include <iostream>

#define YYSTYPE std::string

#include "p_bison.hpp"	// Файл, содержащий макроопределения сделанные в bison.b

void yyerror(char *s);

extern YYSTYPE yylval;

%}				// Окончание блока, прямо копируемого в результирующий файл

comments   \/\*[^*]*\*+([^/*][^*]*\*+)*\/
formating	[\n\r\t\f]*
except_spaces [ ]{2,}
propname [a-zA-Z][-_a-zA-Z0-9]*

%x STR

%%

{propname}	{ yylval=yytext; return T_PROPNAME;}

["]             { yylval = ""; BEGIN(STR); }
<STR>[^\\\n"]+  yylval += yytext;
<STR>\\n        yylval += '\n';
<STR>\\["]      yylval += '"';
<STR>\\         yyerror("Invalid escape sequence");
<STR>\n         yyerror("Newline in string literal");
<STR>["]        { BEGIN(INITIAL); return T_STRING; }

[-{};()=<>+*/!,:@] { return *yytext; }

{comments}
{except_spaces}	
{formating}	


%%

int yywrap()			// Функция обработки обнаружения конца файла
{
	return(1);		// После обнаружения конца файла прекратить парсинг
}

bison.b

%{					// Начало блока, прямо копируемого в результирующий файл
 
#include <stdio.h>
#include <iostream>

extern int yylex(void);		// Объявление внешней функции yylex
void yyerror(char *s);			// Объявление функции обработки ошибки

std::string out_str = "";

#define YYSTYPE std::string
 
%}

%token T_PROPNAME
%token T_STRING
%token T_SYMBOL

%%					// Начало секции определения правил
PRINT: ATRULE_CHARSET 
	{
		printf("AT-RULE-CHARSET[ %s ]\n",$$); 
	}
	| PROPERTY 
	{
		printf("PROPERTY [ %s ]\n",$$); 
	}
	;
ATRULE_CHARSET:
	'@' T_PROPNAME T_STRING ';' { $$ = $3; }
	;

PROPERTY:
	T_PROPNAME ':' { $$=$1; }
	;

%%						
#include <stdio.h>

void yyerror(char *s)				// Функция сообщения об ошибке
{
	fflush(stdout);
	printf("\n%s\n", s);
}

Входной файл:

/* # */
/* } */
/* { */
/* . */

/* h1 on frontpage */
/*
#main .blog-featured h1
{
  border-top:solid 0px #ddd;
  border-bottom:solid 0px #ddd;*/
/*}
*/

@charset "win-1251";

/*#right h3 span.backh2
{

}*/

h3.js_heading
{
  border-bottom:solid 1px #fff !important;
  background:/*#ddf0f2  #E1E9E9*/ #095469 url("../images/nature/h3_js_bg.gif") bottom left repeat-x;
  counter-increment: my_counter;
  clip: rect(40px, auto, auto, 40px); /* Прячем часть текста */
  quotes: "\00ab" "\00bb"; /* Кавычки в виде двойных угловых скобок */
}

/* сщььуте */
body {
	  margin: 50px;
	  font: 12px Arial,/* sdf */ Helvetica , sans-serif; /* сщььуте*/
	  }

Вывод:

Starting parse Entering state 0 Reading a token: Next token is token '@' () Shifting token '@' () Entering state 2 Reading a token: Next token is token T_PROPNAME () Shifting token T_PROPNAME () Entering state 7 Reading a token: Next token is token T_STRING () Shifting token T_STRING () Entering state 9 Reading a token: Next token is token ';' () Shifting token ';' () Entering state 10 Reducing stack by rule 3 (line 31): $1 = token '@' () $2 = token T_PROPNAME () $3 = token T_STRING () $4 = token ';' () -> $$ = nterm ATRULE_CHARSET () Stack now 0 Entering state 4 Reducing stack by rule 1 (line 21): $1 = nterm ATRULE_CHARSET () AT-RULE-CHARSET[ Ёт4 ] -> $$ = nterm PRINT () Stack now 0 Entering state 3 Reading a token: Next token is token T_PROPNAME ()

syntax error Error: popping nterm PRINT () Stack now 0 Cleanup: discarding lookahead token T_PROPNAME () Stack now 0 Для продолжения нажмите любую клавишу . . .

Еще: Как я понял, из того, что флекс не хотел принимать регулярное выражение вида (?<!шаблон) - флекс не поддерживает шаблоны регулярных выражений. Каким образом в таком случае пропустить пробелы до и после символов [:;,] ?

info flex «Flex is not matching my patterns in the same order that I defined them.»

Я понимаю это так - флекс применяет шаблоны не обязательно в том порядке,в каком они описаны.Правильно?Тогда (.+) может пропустить сначала символы все,а потом по 1му шаблону флекс будет пытаться найти символы.Тогда для пропуска символов просто вообще их не указывать?

P.S. Простите за такие вопросы, предчувствую предложения почитать документацию, чем сейчас и буду заниматься..

DarkKnight_spb ()
Ответ на: комментарий от DarkKnight_spb

Я понимаю это так - флекс применяет шаблоны не обязательно в том порядке,в каком они описаны.Правильно?

Не совсем. флекс парсит все шаблоны одновременно и возвращает только самый длинный.

Таким образом в твоём изначальном коде .* — гарантированно матчит всю строку, а {word} только подстроку из букв, цифр и пробелов. То есть если не было других символов, вроде запятых, то в строке найдётся единственное слово, а если есть, то длиннейшим совпадением будет вся строка, которая будет проигнорирована.

Как я понял, из того, что флекс не хотел принимать

info flex Patterns

Каким образом в таком случае пропустить пробелы до и после символов [:;,] ?

А ты уверен что ты хочешь именно этого? Может быть тебе надо игнорировать все пробельные символы вне строковых литералов, как ничего не значащие (info flex 'Simple Examples')? Или ты хочешь убедиться, что после [:;,] обязательно есть пробел (info flex Patterns)?

Вывод: … предчувствую предложения почитать документацию

Ну как бы да. Но на первый взгляд у тебя лексер должен спотыкаться на символе «#» в твоём «border-bottom:solid 1px #fff !important;». Ну и если ничего не помогает, то настало время прочитать «info bison Debugging»

kim-roader ★★ ()
Ответ на: комментарий от kim-roader

info flex Patterns

Прочел, убедился что regex-шаблоны не поддерживаются) Нашел другой способ, но он не всегда работает,об этом ниже.

А ты уверен что ты хочешь именно этого? Может быть тебе надо игнорировать все пробельные символы вне строковых литералов, как ничего не значащие (info flex 'Simple Examples')? Или ты хочешь убедиться, что после [:;,] обязательно есть пробел (info flex Patterns)?

Да,я уверен. Убрать все пробелы было бы слишком просто)) Например здесь

clip: rect(40px, auto, auto, 40px);
Это сработает корректно.А вот здесь:
background:/*#ddf0f2  #E1E9E9*/ #095469 url("../images/nature/h3_js_bg.gif") bottom left repeat-x;
Пропуск всех пробелов превратит значение свойства в мусор.

у тебя лексер должен спотыкаться на символе «#» в твоём «border-bottom:solid 1px #fff !important;».

Разбор значений пока не приоритет. Пока решил стараться убрать лишние пробелы,табуляцию и комментарии.

Вот такой код у меня сейчас: flex.l


%{				// Начало блока, прямо копируемого в результирующий файл
#include <stdio.h> 
#include <iostream>

#define YYSTYPE std::string

#include "p_bison.hpp"	// Файл, содержащий макроопределения сделанные в bison.b

void yyerror(char *s);

extern YYSTYPE yylval;

%}				// Окончание блока, прямо копируемого в результирующий файл

comments   \/\*[^*]*\*+([^/*][^*]*\*+)*\/
formating	[\n\r\t\f]*
except_spaces [ ]{2,}

reserved_word [a-zA-Z][-_a-zA-Z0-9]*
digit [0-9]*[.]?[0-9]*
dt_px {digit}+(px)


%x STR

%%

{comments}
{except_spaces}	
{formating}	

[{][ ]+			return T_OPENBRACE;
[}][ ]+			return T_CLOSEBRACE;
[;][ ]+			return T_SEMICOLON;
[(][ ]+			return T_OPENBRACKET;
[:][ ]+			return T_COLON;
[<][ ]+			return T_LESS;
[>][ ]+			return T_GREATER;
[*][ ]+			return T_STAR;
[@][ ]+			return T_AT;
[.][ ]+			return T_DOT;
[,][ ]+			return T_COMMA;
[#][ ]+			return T_GRILL;

[ ]/[{]
[ ]/[}]
[ ]/[;]
[ ]/[(]
[ ]/[)]
[ ]/[:]
[ ]/[<]
[ ]/[>]
[ ]/[,]


%%

int yywrap()			// Функция обработки обнаружения конца файла
{
	return(1);		// После обнаружения конца файла прекратить парсинг
}

bison.b

%{					// Начало блока, прямо копируемого в результирующий файл
 
#include <stdio.h>
#include <iostream>

extern int yylex(void);		// Объявление внешней функции yylex
void yyerror(char *s);			// Объявление функции обработки ошибки

std::string out_str = "";

#define YYSTYPE std::string
 
%}

%token T_OPENBRACE T_CLOSEBRACE T_SEMICOLON T_OPENBRACKET T_CLOSEBRACKET T_COLON T_LESS T_GREATER T_STAR T_AT T_DOT T_COMMA T_GRILL
%token T_STRING T_RESERVEDWORD T_DIGIT T_PX 


%%					// Начало секции определения правил

print: fsdg 
| print fsdg;

fsdg:
| T_COLON {printf(":");}
| T_OPENBRACE {printf("{");}
| T_CLOSEBRACE {printf("}");}
| T_SEMICOLON {printf(";");}
| T_OPENBRACKET {printf("(");}
| T_CLOSEBRACKET {printf(")");}
| T_DOT {printf(".");}
| T_COMMA {printf(",");}


%%						
#include <stdio.h>

void yyerror(char *s)				// Функция сообщения об ошибке
{
	fflush(stdout);
	printf("\n%s\n", s);
}

Файл тот же,за исключением того, что блоки правил поменяны местами. Получаю такой вывод:

@charset «win-1251»;body{margin:50px;font:12px Arial, Helvetica,sans-serif;}h3.j s_heading{border-bottom:solid 1px #fff !important;background: #095469 url("../im ages/nature/h3_js_bg.gif") bottom left repeat-x;counter-increment:my_counter;cli p:rect(40px,auto,auto,40px);quotes:«\00ab» «\00bb»;}Для продолжения нажмите любу ю клавишу . . .

Итак, как видно из кода пропуск пробелов я постарался решить шаблонами, типа `r/s' .Они отлично работают,только вот не везде. Например в строке

font:12px Arial, Helvetica,sans-serif;

Пробел не пропущен, а это в следствии того,что впереди стоял комментарий. Задание дополнительно шаблона «*/ » (чтобы он просто пропускал это) не принесла результатов. Вопросы: 1. Можно ли пропускать пробелы перед определенными символами каким то другим способом,возможно более простым и оптимальным? 2. Как быть в ситуации,описанной выше?

П.С. Документацию дочитал еще не до конца

DarkKnight_spb ()
Ответ на: комментарий от DarkKnight_spb

Второй вопрос решился так:

[,]			BEGIN(es0); // Remove space, after ","
<es0>"/*"		in_comment = true;
<es0>[^ ]		{ if(in_comment == false) { yyless(yyleng-1); BEGIN(INITIAL); return T_COMMA;}  }
<es0>[ ]
<es0>"*/"		in_comment = false;
<es0>[ ]		{BEGIN(INITIAL); return T_COMMA;}

DarkKnight_spb ()
Ответ на: комментарий от DarkKnight_spb

Это сработает корректно.А вот здесь:

background:/*#ddf0f2 #E1E9E9*/ #095469 url("../images/nature/h3_js_bg.gif") bottom left repeat-x;

Пропуск всех пробелов превратит значение свойства в мусор.

Нет, всё таки ты что-то понял не правильно. С чего это значению превращаться в мусор? Если выкидывать все пробелы и коменты лексером, то поток токенов будет чем-то вроде:

WORD COLON GRILL WORD WORD OPENBRACKET STRING CLOSEBRACKET WORD WORD WORD SEMICOLON

И это замечательно разбирается грамматикой. Пробелы, кроме как для определения границ токенов, не нужны.

kim-roader ★★ ()
Ответ на: комментарий от kim-roader

Дело в том,что я не знаю сколько будет «слов» указано через пробел.Можно конечно сделать эти слова зарезервированными,но тогда может возникнуть конфликт,например «line» и «linear».Как я понимаю об эти слова должны определиться как line.В любом случае,я подумаю над этим,спасибо.

DarkKnight_spb ()
Ответ на: комментарий от DarkKnight_spb

Так тебе всё равно нужны все слова до SEMICOLON. Откуда тут может возникнуть конфликт — я не вижу.

kim-roader ★★ ()
Ответ на: комментарий от DarkKnight_spb

Снова возвращаюсь к %union,и снова проблемы)) Весь код выкладывать не буду, выкладываю начало файла бизона:

%{					// Начало блока, прямо копируемого в результирующий файл
 
#include <stdio.h>
#include <iostream>
#include "Definitions.h"
#include "CSSBisonOutStructs.h"

#pragma warning(disable : 4065)

extern int yylex(void);		// Объявление внешней функции yylex
void yyerror(char *s);			// Объявление функции обработки ошибки

std::string out_str = "";
CSSPTNode* treeRoot = NULL;
vector<CSSBisonNodeName*> blocknameCollect;

//  #define YYSTYPE std::string

 
%} /* ============================================== TOKEN DEFINION SECTION =================================== */

%union
{
	CSSBisonNodeName *name;
	std::string str;
}

Ошибки такие:

1> error C2143: синтаксическая ошибка: отсутствие ";" перед «*» 1> error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию 1> error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию 1> error C2039: string: не является членом «std» 1> error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором «str» 1> error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию 1> error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию

Тобишь ругается на юнион,якобы неизвестные типы. Хотя выше,в секции предопределений, он с этими типами отлично работает. Если заменить нужные мне типы на стандартные,то все работает,но суть то в том что мне нужны МОИ :) что бы это могло быть? Сам ошибок не нашел,вроде все правильно..

З.Ы. Ниже юниона все ок,типы определены. Ошибки только в юнионе.

DarkKnight_spb ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.