LINUX.ORG.RU

Flex&Bisone конфликты

 ,


1

2

Доброго времени суток. Не так давно изучаю bison и flex, поэтому нужна помощь. Есть задача описать входной язык Lua. Нашёл всю грамматику тут https://lua.org.ru/contents_ru.html. При сборке возникает ошибка, которую я никак не могу решить, помогите решить эту проблему. Собираю так: bison -d имя файла.y flex имя файла.l g++ -o имя lex.yy.c y.tab.c

Bison файл


%{
#include <iostream>
#include <string>
using namespace std;
void yyerror(char const* msg);
extern FILE *yyin;
int yylex();
%}

%union{
	std::string*		stringVal;
}
%verbose
%token <stringVal> LTOE GTOE TILDEEQUAL DEQUAL DSLASH DLESS DGREATER DPOINT TPOINT
%token <stringVal> NOT NIL FALSE TRUE RETURN
%token <stringVal> OR AND WHILE REPEAT UNTIL IF THEN ELSE ELSEIF
%token <stringVal> FOR IN FUNCTION LOCAL DO END GOTO BREAK DCOLON
%token <stringVal> NAME STRING STRINGG

%token INT HEX FLOAT

%left OR
%left AND
%left '<' '>' LTOE GTOE TILDEEQUAL DEQUAL
%left '|'
%left '~'
%left '&'
%left DLESS DGREATER
%right DPOINT
%left '+' '-'
%left '*' '/' '%' DSLASH
%left '#' NOT
%left UNARY
%right '^'

%start chunk

%%


chunk : block
;

block : stat | stat retstat
;

stat : /*empty*/  
	 | stat ';' 
	 | stat varlist '=' explist 
	 | stat functioncall 
	 | stat label 
	 | stat BREAK 
	 | stat GOTO NAME 
	 | stat DO block END 
	 | stat WHILE exp DO block END 
	 | stat REPEAT block UNTIL exp 
	 | stat IF exp THEN block statelseif elseblock END
	 | stat FOR NAME '=' exp ',' exp exz DO block END
	 | stat FOR namelist IN explist DO block END
	 | stat FUNCTION funcname funcbody
	 | stat LOCAL FUNCTION NAME funcbody
	 | stat LOCAL namelist 
	 | stat LOCAL namelist '=' explist
;

statelseif:							/*('elseif' exp 'then' block)* */						
	/*empty*/
	| statelseif ELSEIF exp THEN block
	;
	
exz
	:  /*empty*/
	| ',' exp
	;
	
elseblock
	: /*empty*/
	| ELSE block
	;

retstat
    : RETURN | RETURN explist | RETURN ';'
    ;

label : DCOLON NAME DCOLON

funcname
    : NAME np 
	| NAME np ':' NAME
    ;
	
np
	: /*empty*/
	| np '.' NAME
	;

varlist
    : var |varlist ',' var
    ;

var :  NAME | prefixexp '[' exp ']' | prefixexp '.' NAME 

namelist
    : NAME 
	| namelist ',' NAME
    ;

explist
    : exp 
	| explist ',' exp
    ;

exp :  NIL | FALSE | TRUE 
	| number 
	| string 
	| TPOINT 
	| functiondef 
	| prefixexp 
	| tableconstructor 
	| exp '^' exp		
	| NOT exp
	| '#' exp
	| exp '*' exp
	| exp '/' exp
	| exp '%' exp
	| exp DSLASH exp
	| exp '+' exp
	| exp '-' exp
	| exp DPOINT exp
	| exp '<' exp
	| exp '>' exp
	| exp LTOE exp
	| exp GTOE exp
	| exp TILDEEQUAL exp
	| exp DEQUAL exp
	| exp AND exp
	| exp OR exp
	| exp '&' exp
	| exp '|' exp
	| exp '~' exp
	| exp DLESS exp
	| exp DGREATER exp
	| '-' exp %prec UNARY
	| '~' exp %prec UNARY
	;

prefixexp : var | functioncall | '(' exp ')'

functioncall :  prefixexp args | prefixexp ':' NAME args 

args: '('/*empty*/')' 
		| '(' explist ')'
		| tableconstructor
		| string
;

functiondef : FUNCTION funcbody

funcbody: '('/*empty*/')' block END
		| '('parlist')' block END

parlist: namelist 
		| namelist ',' TPOINT
		| namelist TPOINT
;

tableconstructor: '{'/*empty*/'}'
		| '{' fieldlist '}'
;

fieldlist: field fieldlistREP
		| field fieldlistREP fieldsep
;
fieldlistREP: /*empty*/ 
		| fieldlistREP fieldsep field
;

field : '[' exp ']' '=' exp | NAME '=' exp | exp

fieldsep : ',' | ';'



number
    : INT | HEX | FLOAT
    ;
	
string
	: STRING | STRINGG
	;



%%
void yyerror(char const* msg) {}


int main() {

	yyin = fopen("bisontest.txt", "r");
    //yyparse();

    if (yyparse() == 0) {
        cout << "Success" << endl;
    } else {
		cout << "Syntax error" << endl;
	}
    return 0;
}

flex файл

 
%option noyywrap yylineno
%{
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "bisondoc.tab.h"
using namespace std;
void showError();
int ch;

%}

%%
[ \t\r\n]+ 					{ /* игнорируем пробелы, табы и переносы строк */ }

"("				{return 40;}
")"				{return 41;}
"["				{return 91;}
"]"				{return 93;}
"{"				{return 123;}
"}"				{return 125;}
"<"			   	{return 60;}
">"			   	{return 62;}
","				{return 44;}
"."				{return 46;}
"+"			   	{return 43;}
"-"			   	{return 45;}
"*"			   	{return 42;}
"/"			   	{return 47;}
"="			   	{return 61;}
":"			   	{return 58;}
";"			   	{return 59;}
"%"			   	{return 37;}
"&"			   	{return 38;}
"|"			   	{return 124;}
"~"			   	{return 126;}
"#"			   	{return 35;}
"^"			   	{return 94;}
["]			   	{return 34;}
"'"			   	{return 39;}
"\\"			{return 92;}

"<="			{yylval.stringVal = new std::string(yytext, yyleng); return (LTOE);}
">="			{yylval.stringVal = new std::string(yytext, yyleng); return (GTOE);}
"~="			{yylval.stringVal = new std::string(yytext, yyleng); return (TILDEEQUAL);}
"=="			{yylval.stringVal = new std::string(yytext, yyleng); return (DEQUAL);}
"//"			{yylval.stringVal = new std::string(yytext, yyleng); return (DSLASH);}
"<<"			{yylval.stringVal = new std::string(yytext, yyleng); return (DLESS);}
">>"			{yylval.stringVal = new std::string(yytext, yyleng); return (DGREATER);}
".."			{yylval.stringVal = new std::string(yytext, yyleng); return (DPOINT);}
"..."			{yylval.stringVal = new std::string(yytext, yyleng); return (TPOINT);}

"not"			{yylval.stringVal = new std::string(yytext, yyleng); return (NOT);}
"nil"			{yylval.stringVal = new std::string(yytext, yyleng); return (NIL);}
"false"			{yylval.stringVal = new std::string(yytext, yyleng); return (FALSE);}
"true"			{yylval.stringVal = new std::string(yytext, yyleng); return (TRUE);}
"return"		{yylval.stringVal = new std::string(yytext, yyleng); return (RETURN);}
"or"			{yylval.stringVal = new std::string(yytext, yyleng); return (OR);}
"and"			{yylval.stringVal = new std::string(yytext, yyleng); return (AND);}
"while"			{yylval.stringVal = new std::string(yytext, yyleng); return (WHILE);}
"repeat"		{yylval.stringVal = new std::string(yytext, yyleng); return (REPEAT);}
"until"			{yylval.stringVal = new std::string(yytext, yyleng); return (UNTIL);}
"if"			{yylval.stringVal = new std::string(yytext, yyleng); return (IF);}
"then"			{yylval.stringVal = new std::string(yytext, yyleng); return (THEN);}
"else"			{yylval.stringVal = new std::string(yytext, yyleng); return (ELSE);}
"elseif"		{yylval.stringVal = new std::string(yytext, yyleng); return (ELSEIF);}
"for"			{yylval.stringVal = new std::string(yytext, yyleng); return (FOR);}
"in"			{yylval.stringVal = new std::string(yytext, yyleng); return (IN);}
"function"		{yylval.stringVal = new std::string(yytext, yyleng); return (FUNCTION);}
"local"			{yylval.stringVal = new std::string(yytext, yyleng); return (LOCAL);}
"do"			{yylval.stringVal = new std::string(yytext, yyleng); return (DO);}
"end"			{yylval.stringVal = new std::string(yytext, yyleng); return (END);}
"goto"			{yylval.stringVal = new std::string(yytext, yyleng); return (GOTO);}
"break"			{yylval.stringVal = new std::string(yytext, yyleng); return (BREAK);}
"::"			{yylval.stringVal = new std::string(yytext, yyleng); return (DCOLON);}


[a-zA-Z_][a-zA-Z_0-9]* 		{yylval.stringVal = new std::string(yytext, yyleng); return (NAME);}
\"[ -~]*\"					{yylval.stringVal = new std::string(yytext, yyleng); return (STRING);}
\'[ -~]*\'				    {yylval.stringVal = new std::string(yytext, yyleng); return (STRINGG);}

[0-9]+						{return (INT);}
0[xX][0-9a-fA-F]+ 			{return (HEX);}
([0-9]*\.[0-9]+|[0-9]+\.)	{return (FLOAT);}

.      			{showError(); return 0;}
%%


void showError(){
    printf("Other input\n");
}

Ответ на: комментарий от seiken

Пока не разобрался как сюда скрины лить.

bisondoc.y: конфликты 1сдвига/вывода, 1 вывода/вывода bisondoc.output: Состояние 24 конфликты: 1 вывода/вывода Состояние 44 конфликты: 1 сдвига/вывода

состояние 24

7 stat: stat functioncall .

79 prefixexp: functioncall .

STRING    вывод с использованием правила 79 (prefixexp)
STRINGG   вывод с использованием правила 79 (prefixexp)
':'       вывод с использованием правила 79 (prefixexp)
'.'       вывод с использованием правила 79 (prefixexp)
'['       вывод с использованием правила 79 (prefixexp)
'('       вывод с использованием правила 7 (stat)
'('       [вывод с использованием правила 79 (prefixexp)]
'{'       вывод с использованием правила 79 (prefixexp)
$default  вывод с использованием правила 7 (stat)

состояние 44

38 var: prefixexp . ‘[’ exp ’]’ 39 | prefixexp . ‘.’ NAME 51 exp: prefixexp . 81 functioncall: prefixexp . args 82 | prefixexp . ‘:’ NAME args

STRING   сдвиг, и переход в состояние 31
STRINGG  сдвиг, и переход в состояние 32
':'      сдвиг, и переход в состояние 66
'.'      сдвиг, и переход в состояние 67
'['      сдвиг, и переход в состояние 68
'('      сдвиг, и переход в состояние 69
'{'      сдвиг, и переход в состояние 40

'('       [вывод с использованием правила 51 (exp)]
$default  вывод с использованием правила 51 (exp)

args              переход в состояние 70
tableconstructor  переход в состояние 71
string            переход в состояние 72
LSTSnaiper ()
Ответ на: комментарий от LSTSnaiper

prefixexp : var | functioncall | ‘(’ exp ‘)’

functioncall : prefixexp args | prefixexp ‘:’ NAME args

ну так это рекурсия

переосмыслите и перепишите эти или это правило(одно из них)

и да кстати, точку с запятой в правилах не забыли ?

anonymous ()

Думаю что неоднозначность тут в самом языке (https://lua.org.ru/contents_ru.html, параграф 3.3.1 – Блоки):

Вызовы функций и присваивания могут начинаться с открывающейся скобки. Эта возможность ведет к неоднозначности в грамматике Lua. Рассмотрим следующий фрагмент:

a = b + c
(print or io.write)('done')

Грамматика может рассматривать это двумя путями:

a = b + c(print or io.write)('done')    
a = b + c; (print or io.write)('done')

Текущий парсер всегда рассматривает такие констркции первым путем, интерпретируя открывающуюся скобку, как начало аргументов для вызова.

То, что неоднозначность возникает на границе между stat, видно в том числе если добавить в грамматику принудительные точки с запятой после разных видов stat (конфликты уходят).

Грамматику можно немного переделать, чтобы reduce/reduce конфликт перешёл в shift/reduce (который по умолчанию разрешается в пользу shift):

-prefixexp : var | functioncall | '(' exp ')'
+prefixexp_nf : var | '(' exp ')'
+prefixexp : prefixexp_nf | functioncall
 
-functioncall :  prefixexp args | prefixexp ':' NAME args 
+functionargs : args | ':' NAME args
+functioncall : prefixexp_nf functionargs | functioncall functionargs
skvadrik ()
Ответ на: комментарий от xaizek

Я дошёл только до этого

Lua.l

%option noyywrap yylineno
%{
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "lua.tab.h"
using namespace std;
void showError();
int ch;
%}

NESTED_STR ("=" NESTED_STR "=" | "[" .*? "]")

%%
"\n"			{ch = 1;}
[ \t\r]+ 		{ /* игнорируем пробелы, табы и переносы строк */ }

"("				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 40;}
")"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 41;}
"["				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 91;}
"]"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 93;}
"{"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 123;}
"}"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 125;}
"<"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 60;}
">"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 62;}
","				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 44;}
"."				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 46;}
"+"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 43;}
"-"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 45;}
"*"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 42;}
"/"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 47;}
"="			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 61;}
":"			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 58;}
";"			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 59;}
"%"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 37;}
"&"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 38;}
"|"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 124;}
"~"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 126;}
"#"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 35;}
"^"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 94;}
["]			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 34;}
"'"			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 39;}
"\\"			{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 92;}

"<="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (LTOE);}
">="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (GTOE);}
"~="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (TILDEEQUAL);}
"=="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DEQUAL);}
"//"			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DSLASH);}
"<<"			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DLESS);}
">>"			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DGREATER);}
".."			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DPOINT);}
"..."			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (TPOINT);}

"not"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (NOT);}
"nil"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (NIL);}
"false"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FALSE);}
"true"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (TRUE);}
"return"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (RETURN);}
"or"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (OR);}
"and"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (AND);}
"while"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (WHILE);}
"repeat"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (REPEAT);}
"until"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (UNTIL);}
"if"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (IF);}
"then"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (THEN);}
"else"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (ELSE);}
"elseif"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (ELSEIF);}
"for"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FOR);}
"in"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (IN);}
"function"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FUNCTION);}
"local"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (LOCAL);}
"do"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DO);}
"end"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (END);}
"goto"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (GOTO);}
"break"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (BREAK);}
"::"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DCOLON);}

[a-zA-Z_][a-zA-Z_0-9]* 	{printf("IDENTIFIER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (NAME);}
\".*\" 					{printf("STRING (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (STRING);}
\'.*\'                	{printf("STRING (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (CHARSTRING);}
"--[" NESTED_STR "]"	{printf("MULTILINECOMMENT (%d, %d)\n", yylineno, ch); ch += yyleng; return (LINECOMMENT);}
"--".*\n?				{printf("LINECOMMENT (%d, %d)\n", yylineno, ch); ch += yyleng; return (LINECOMMENT);}

[0-9]+						{printf("NUMBER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (INT);}
0[xX][0-9a-fA-F]+ 			{printf("NUMBER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (HEX);}
([0-9]*\.[0-9]+|[0-9]+\.)	{printf("NUMBER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FLOAT);}

.      			{showError();}
%%

void showError(){
	printf("Lexical error in line: %d, char: %d.\n", yylineno, ch+1);
}

У меня, почему-то многострочные комментарии воспринимаются как однострочные, не могу понять как явно указать лексеру что есть что. Может есть у кого идеи? Буду благодарен.

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

Я же говорю, надо использовать состояния. Примерно так:

%option noyywrap yylineno
%{
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "lua.tab.h"
#define YY_DECL extern "C" int yylex()
using namespace std;
void showError();
int ch;
int mlLine;
int mlChar;
int mlLevel;
%}

%X mlcomment slcomment

%%
<INITIAL,mlcomment,slcomment>"\n"			{ch = 1;}
[ \t\r]+ 		{ /* игнорируем пробелы, табы и переносы строк */ }

"("				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 40;}
")"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 41;}
"["				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 91;}
"]"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 93;}
"{"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 123;}
"}"				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 125;}
"<"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 60;}
">"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 62;}
","				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 44;}
"."				{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 46;}
"+"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 43;}
"-"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 45;}
"*"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 42;}
"/"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 47;}
"="			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 61;}
":"			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 58;}
";"			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 59;}
"%"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 37;}
"&"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 38;}
"|"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 124;}
"~"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 126;}
"#"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 35;}
"^"			   	{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 94;}
["]			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 34;}
"'"			   	{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 39;}
"\\"			{printf("DELIM (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return 92;}

"<="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (LTOE);}
">="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (GTOE);}
"~="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (TILDEEQUAL);}
"=="			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DEQUAL);}
"//"			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DSLASH);}
"<<"			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DLESS);}
">>"			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DGREATER);}
".."			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DPOINT);}
"..."			{printf("OPERATION (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (TPOINT);}

"not"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (NOT);}
"nil"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (NIL);}
"false"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FALSE);}
"true"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (TRUE);}
"return"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (RETURN);}
"or"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (OR);}
"and"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (AND);}
"while"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (WHILE);}
"repeat"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (REPEAT);}
"until"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (UNTIL);}
"if"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (IF);}
"then"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (THEN);}
"else"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (ELSE);}
"elseif"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (ELSEIF);}
"for"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FOR);}
"in"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (IN);}
"function"		{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FUNCTION);}
"local"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (LOCAL);}
"do"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DO);}
"end"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (END);}
"goto"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (GOTO);}
"break"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (BREAK);}
"::"			{printf("KEYWORD (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (DCOLON);}

[a-zA-Z_][a-zA-Z_0-9]* 	{printf("IDENTIFIER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (NAME);}
\".*\" 					{printf("STRING (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (STRING);}
\'.*\'                	{printf("STRING (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (CHARSTRING);}

"--["=*"["              {BEGIN(mlcomment);
                         printf("MULTILINECOMMENT start\n");
                         mlLine = yylineno;
                         mlChar = ch;
                         mlLevel = yyleng - 4;
                          ch += yyleng;}
<mlcomment>"]"=*"]"     {if(yyleng - 2 == mlLevel) {
                             BEGIN(INITIAL);
                             printf("MULTILINECOMMENT (%d, %d)\n", mlLine, mlChar); ch += yyleng;
                         }
                        }
<mlcomment>. { ++ch; }

"--"				{BEGIN(slcomment); printf("LINECOMMENT (%d, %d)\n", yylineno, ch); ch += yyleng;}
<slcomment>.     {}
<slcomment>\n     {BEGIN(INITIAL);}

[0-9]+						{printf("NUMBER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (INT);}
0[xX][0-9a-fA-F]+ 			{printf("NUMBER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (HEX);}
([0-9]*\.[0-9]+|[0-9]+\.)	{printf("NUMBER (%d, %d): %s\n", yylineno, ch, yytext); ch += yyleng; return (FLOAT);}

.      			{showError();}
%%

void showError(){
    printf("Lexical error in line: %d, char: %d.\n", yylineno, ch+1);
}
xaizek ★★★★★ ()