Большая проблема с регулярным выражением в Lex (лексический анализатор) - PullRequest
1 голос
/ 27 марта 2010

У меня есть такой контент:

    author = "Marjan Mernik  and Viljem Zumer",
    title = "Implementation of multiple attribute grammar inheritance in the tool LISA",
    year = 1999

    author = "Manfred Broy and Martin Wirsing",
    title = "Generalized
             Heterogeneous Algebras and
             Partial Interpretations",
    year = 1983

    author = "Ikuo Nakata and Masataka Sassa",
    title = "L-Attributed LL(1)-Grammars are
             LR-Attributed",
    journal = "Information Processing Letters"

И мне нужно поймать все между двойными кавычками для title . Моя первая попытка была такой:

^(" "|\t)+"title"" "*=" "*"\"".+"\","

Который ловит первый пример, но не два других. Другие имеют несколько строк, и это проблема. Я думал об изменении на что-то с \n где-нибудь, чтобы разрешить несколько строк, например:

^(" "|\t)+"title"" "*=" "*"\""(.|\n)+"\","

Но это не помогает, вместо этого он ловит все .

Чем я все-таки "хочу получить между двойными кавычками, что если я поймаю все, пока не найду другой ", за которым следует ,? Таким образом, я мог бы знать, был ли я в конце название или нет, независимо от количества строк, например:

^(" "|\t)+"title"" "*=" "*"\""[^"\""]+","

Но здесь есть другая проблема ... В приведенном выше примере ее нет, но символ двойной кавычки (") может находиться между объявлением title . Например:

title = "aaaaaaa \"X bbbbbb",

И да, ему всегда будет предшествовать обратный слеш (\).

Есть предложения по исправлению этого регулярного выражения?

Ответы [ 2 ]

2 голосов
/ 27 марта 2010

Классическое регулярное выражение для сопоставления строк в двойных кавычках:

\"([^\"]|\\.)*\"

В вашем случае вам нужно что-то вроде этого:

"title"\ *=\ *\"([^\"]|\\.)*\"

PS: ИМХО, вы помещаете слишком много цитат в свои регулярные выражения, их трудно прочитать.

0 голосов
/ 27 марта 2010

Вы можете использовать начальные условия для упрощения каждого отдельного шаблона, например:

%x title
%%
"title"\ *=\ *\"  { /* mark title start */
  BEGIN(title);
  fputs("found title = <|", yyout);
}

<title>[^"\\]* { /* process title part, use ([^\"]|\\.)* to grab all at once */
  ECHO;
}

<title>\\. { /* process escapes inside title */
  char c = *(yytext + 1);
  fputc(c, yyout); /* double escaped characters */
  fputc(c, yyout);
}

<title>\" { /* mark end of title */
  fputs("|>", yyout);
  BEGIN(0); /* continue as usual */
}

Чтобы сделать исполняемый файл:

$ flex parse_ini.y
$ gcc -o parse_ini lex.yy.c -lfl

Запустите его:

$ ./parse_ini < input.txt 

Где input.txt:

author = "Marjan\" Mernik  and Viljem Zumer",
title = "Imp\"lementation of multiple...",
year = 1999

Выход:

author = "Marjan\" Mernik  and Viljem Zumer",
found title = <|Imp""lementation of multiple...|>,
year = 1999

Он заменяет '"' вокруг заголовка на '<|', а '|>'. Also '\ "'` заменяется на "" "внутри заголовка.

...