2015-01-22 23:28 GMT+03:00 Nikolay Mishin <[email protected]>:
> Руслан,
> я тут понаписав парсеров на регулярках
> с удовольсвием послушал бы про MarpaX::Repa
> и как с помощью него распарсить скажем css
> или html, если это, конечно, возможно,
>
С HTML сложно, но возможно, есть Marpa::HTML (не помню точное имя) который
делает парсинг согласно HTML5 стандарту (по словам автора модуля, он же
автор Marpa). Там все старшно внутри.
> ну для примера, как сделать грамматику для такой конструкции:
>
> BEGIN DSSUBRECORD
> Name "$APT_DBNAME"
> Prompt "DB2 Database"
> Default "BANKDATA"
> HelpTxt "Default DB2 database to use"
> ParamType "0"
> ParamLength "0"
> ParamScale "0"
> END DSSUBRECORD
>
> если это вообще стоит делать,т.к. я просто
> это распарсил такой функцией:
>
cd ~/projs/mods/MarpaX-Repa/
git co master
cp examples/template.pl ttt.pl
vi ttt.pl
прикрепил
>
> sub split_fields_by_new_line {
> my ($curr_record) = @_;
> my %fields_and_values = ();
> while (
> $curr_record =~ m/
> (?<name>\w+)[ ]"(?<value>.*?)(?<!\\)"|
> ((?<name2>\w+)[ ]\Q=+=+=+=\E
> (?<value2>.*?)
> \Q=+=+=+=\E)
> /xsg
> )
> {
> my ($value, $name) = ('', '');
> if (defined $+{name}) {
> $name = $+{name};
> $value = $+{value};
> }
> elsif (defined $+{name2}) {
> $name = $+{name2};
> $value = $+{value2};
> }
> $fields_and_values{$name} = $value;
> }
> return \%fields_and_values;
> }
>
>
>
> > Marpa, Parse::RecDescent, Parse::Yapp, Parse::Eyapp.
> >
> > Первый мне очень нравиться. Попрбуйте с MarpaX::Repa. "Репу" написал сам
> и мне очень удобно с ним писать парсеры ибо можно написать грамматику и не
> определить все токены, то есть итеративно дополнять в процессе свой парсер
> без фатальных ошибок на этапе компиляции парсера. В новых версиях Marpa
> есть Scanless интерфейс - это самое близкое к Repa так как включает лексер
> и самое простое для начала.
> >
> > 2015-01-14 12:34 GMT+03:00 Харпалёв Иван <[email protected]>:
> >
> >> Доброго времени, могучий MoscowPM!
> >>
> >> Сейчас пишу небольшой язык.
> >> То есть пишу транслятор из него в awk и С. (Сначала в awk, чтобы
> потренироваться, а потом в C, там типизация, там сложнее).
> >>
> >> Когда язык был совсем примитивный, я его парсил регэкспами и по
> рабоче-крестьянски собирал код на целевом языке.
> >> Но язык подростает. И рефакторить оказывается очень печально.
> >>
> >> Как я понимаю весь процесс работы транслятора состоит из стандартных
> стадий, например:
> >> токенизация
> >> построение дерева разбора
> >> сбор кода на целевом языке из полученного описания.
> >>
> >> В общем тория у меня хромает и очень интересна. Но первым делом
> практика.
> >> Скажите, чем строить дерево синтаксического разбора?
> >> что-то вроде
> >>
> >> --
> >>
> >> Moscow.pm mailing list
> >>
> >> [email protected] | http://moscow.pm.org
> >
> > --
> > Best regards, Ruslan.
> --
> С уважением
> Николай Мишин
>
>
> --
> Moscow.pm mailing list
> [email protected] | http://moscow.pm.org
>
--
Best regards, Ruslan.
use strict; use warnings;
use Marpa::R2;
use MarpaX::Repa::Lexer;
use MarpaX::Repa::Actions;
use Regexp::Common qw /delimited/;
my $grammar = Marpa::R2::Grammar->new( {
action_object => 'MarpaX::Repa::Actions',
default_action => 'do_scalar_or_list',
start => 'config',
rules => [
{ lhs => 'config', rhs => [qw(BEGIN list END)] },
{ lhs => 'list', rhs => [qw/item/], separator => 'EOL', min => 1 },
{ lhs => 'item', rhs => [qw/WS? name WS quoted/] },
{ lhs => 'WS?', rhs => [] },
{ lhs => 'WS?', rhs => ['WS'], action => 'do_ignore' },
],
});
$grammar->precompute;
my $recognizer = Marpa::R2::Recognizer->new( { grammar => $grammar } );
my $lexer = MarpaX::Repa::Lexer->new(
tokens => {
name => { match => qr{\b(?!END|BEGIN)\w+\b}, store => 'scalar' },
'quoted' => {
match => qr[$RE{delimited}{-delim=>qq{\"}}],
store => sub {
${$_[1]} =~ s/^"//;
${$_[1]} =~ s/"$//;
${$_[1]} =~ s/\\([\\"])/$1/g;
return $_[1];
},
},
BEGIN => { match => qr{BEGIN\s+(\w+)}, store => sub { ${$_[1]} =~ s/^BEGIN\s+//; return $_[1] } },
END => { match => qr{END\s+(\w+)}, store => sub { ${$_[1]} =~ s/^END\s+//; return $_[1] } },
EOL => { match => qr{\r*\n}, store => 'undef' },
WS => { match => qr{\s+}, store => 'undef' },
},
debug => 1,
);
use Data::Dumper;
print Dumper( $lexer->recognize( $recognizer => \*DATA )->value );
__DATA__
BEGIN DSSUBRECORD
Name "$APT_DBNAME"
Prompt "DB2 Database"
Default "BANKDATA"
HelpTxt "Default DB2 database to use"
ParamType "0"
ParamLength "0"
ParamScale "0"
END DSSUBRECORD
--
Moscow.pm mailing list
[email protected] | http://moscow.pm.org