LINUX.ORG.RU

[perl] Parse::RecDescent построчная обработка

 


0

1

Товарищи! Если тут есть кто-то понимающий в Parse::RecDescent

Есть код, задача которого парсить построчно:

$Parse::RecDescent::skip = '';

my $grammar = q{
  Page: Line(s) {print "Finished! \n"}
  Line: /^.*/   /\n|\Z/  {print "Line: '$item[1]'\n"}
};

my $parser = new Parse::RecDescent($grammar);

my $text = "aaaaa\nbbbbbb\nccccc";

if ($parser->Page($text))
{
  print "Happy!\n"
} else
{
  print "Unhapy :-(\n"
}

Однако парсер почему-то находит еще одну пустую строку в конце:

Line: 'aaaaa'
Line: 'bbbbbb'
Line: 'ccccc'
Line: ''
Finished! 
Happy!

Я че-то не понимаю почему, пытался смотреть на $::RD_TRACE = 1; но тоже не вкурил...

Кто-нибудь может объяснить почему так происходит? И как такие вещи делать правильно?

К сожалению родная рассылка полудохлая там спрашивать почти что бесполезно. Я спросил, но когда ответят — неизвесно...

★★★

> Кто-нибудь может объяснить почему так происходит?

потому что пустая строка соответствует регекспу «/^.*/». замени на «/^.+/».

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

потому что пустая строка соответствует регекспу «/^.*/». замени на «/^.+/»

Тогда my $text = «aaaaa\n\n\n\nbbbbbb\nccccc»; Не будет работать правильно...

Кроме того там же последовательность /^.*/ /\n|\Z/

То есть матчится с чем угодно и в конце перевод строки или конец файла... Или я как-то не верно трактую символ \Z и после него парсинг все равно продолжается?

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

> Тогда my $text = «aaaaa\n\n\n\nbbbbbb\nccccc»; Не будет работать правильно...

«/\n|\Z/» → «/\n+|\Z/». или что есть «правильно»?

> То есть матчится с чем угодно и в конце перевод строки или конец файла...

баг, наверное… \Z действительно должен был попасть в предыдущее совпадение. или же наплодить +∞ совпадений \Z, но не одно. согласен, странное поведение…

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

Тогда my $text = «aaaaa\n\n\n\nbbbbbb\nccccc»; Не будет работать правильно...

«/\n|\Z/» → «/\n+|\Z/». или что есть «правильно»?

«правильно» найти три пустых строки после строки из букв 'a'

Я на самом деле хотел завести правило EOL: /\n|\Z/ и просто в конце каждого правила описывающие строки разного типа ставить EOL.

EOL: /\n/ не подойдет, потому как в конце последней строки может не быть перевода, и тогда парсер ее не впарсивает. А вот со \Z'ом происходит описанная фигня...

Не, я конечно могу сделать workaround и добавлять \n в конец, если его там нету, но это не совсем красиво...

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

ну хз, странный парсер.

Line: /^.+|(?=\n)/   /\n?/  {print "Line: '$item[1]'\n"}

или «/\n?/» → «/\n|\Z/», в данном случае без разницы.

// и вообще, данная задача решается через split, без регекспов :)

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

ну хз, странный парсер.

Ну, MediaWiki оно Line based. Строка начинающася с «=», строка начинающаяся с " ", строка наничающаяся с «#»

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

я конкретно о Parse::RecDescent говорил :)

что за задача, кстати? есть подозрение, что парсер на грамматиках для неё и не нужен.

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

\Z - это EOF (я не знаю лунный перл)?

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

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

Может: MediaWiki->export_xml->xslt->result_tree ?

Возможно...

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