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

Ответить