LINUX.ORG.RU

парсинг функций

 ,


0

1

Доброго времени суток!

Встала задача уметь парсить выражения типа func(arg), func(arg1, arg2,arg3).

Я подумал, что для этого вполне подойдут двусвязные списки: аргументы парсим по одному, в каждый предыдущий - ссылка на следующий и на предыдущий; когда надо вывести весь список, скатываемся до первого элемента и идем в прямом порядке.

Вот что я наваял: бизон, flex.

Там имеется ряд косяков, которые я не знаю, как поправить:

1) двусвязный список не работает. хз, почему бизон выражения вида $$->prev_arg=$1; $1->next_arg=$$; трактует неправильно (или я че-то не понял...). А именно - вставляет указатель на сам элемент, а не на предыдущий или следующий.

2) обрабатывает почти корректно только первую введенную строчку. на остальных начинает сыпаться. Почти корректно - в смысле: если подается один аргумент в функцию в первый раз, то он выводится, если второй раз, то говорит, что «ошибка синтаксиса».

3) выражения вида (arg1, arg2) вроде понимает, а (arg1,arg2) не понимает. Дело в пробеле после запятой. Это вроде просто, но я пока не проверял из-за более серьезных ошибок выше.

4) всюду пишут, что использовать strdup не рекомендуется из-за утечек памяти. Отсюда вопрос - лучше сначала выделить память (байт так 128) и туда все скидывать или же делать динамически? Если динамически, то в каком месте чистить память?

★★

ах да - не выводит еще имени функции

aido ★★ ()

У вас в бизоне всё плохо и неправильно. Посмотрите какую-нибудь готовую грамматику на бизоне, например, постгреса, чтобы лучше понимать, как оно на практике делается. А также обязательно почитайте мануал по бизону, - он очень подробный и с хорошими примерами.

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

а почему плохо и неправильно? вроде все на нем стоит?

aido ★★ ()

Веб обезьяны атакуют:

PROG
  = EXPRLIST
  
EXPRLIST
  = head:EXPR _ tail:RESTEXPR* {return [head].concat(tail)}
  
RESTEXPR
  = _ ',' _ expr:EXPR _ {return expr}

EXPR
  = name:ID '(' args:ARGLIST ')' { return {type: 'func', name:name, args: args}}
  
ID 
  = body:[a-zA-Z0-9]+ { return body.join('')}
  
ARGLIST
  = _ head:ARG _ tail:RESTARGS* {return [head].concat(tail)}
  
ARG
  = ID
  
RESTARGS
  = _ ',' _ arg:ARG _ {return arg}

_ "whitespace"
  = [ \t\n\r]*

потестить можно тут: http://pegjs.org/online

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

Но вроде бизон умеет нормально списки парсить чем то типо: ARGLIST = ARGLIST ',' ARG | ARG

zz ★★★★ ()

Зачем тащить какие-то свистелки? регулярные выражения чем не подходят?

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

Ты всё перепутал, поняша. Это регулярки — свистелки, да к тому же ещё и медленные.

anonymous ()

_l.l :

%{
#include <stdio.h>
#include <stdlib.h> //atoi
#include <string.h> //strdup

#include "_y.tab.h"

extern YYSTYPE yylval;
%}

%%
[,()] {return yylval.val=yytext[0];}
[a-zA-Z][a-zA-Z0-9]*    {yylval.str=strdup(yytext); return WORD;}
[0-9]+                  {yylval.val=atoi(yytext);   return NUMBER;}
[ \t\r\n]+ {;}
%%
int yywrap(){return 1;}
_y.y :
%{
#include <stdio.h>
%}

%union {
int val;
char *str;
}
%token <val> NUMBER
%token <str> WORD

%start funcs
%%
funcs: /* empty */ | func | funcs ',' func ;
func: func_args ')' {printf(")\n");} ;
func_args: WORD '(' NUMBER {printf("%s(%d", $1, $3);}
 | WORD '(' WORD {printf("%s(%s", $1, $3);}
 | func_args ',' NUMBER {printf(", %d", $3);}
 | func_args ',' WORD {printf(", %s", $3);}
;
%%
int yyerror(const char *str){fprintf(stderr,"YYerr: %s\n",str);return 0;}
int main(){yyparse();return 0;}
bison -d _y.y; flex _l.l ; gcc -o yl _y.tab.c lex.yy.c Про "." , «||», «&&» , ... - не понял.

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