Parse :: RecDescent и грамматика - PullRequest
       21

Parse :: RecDescent и грамматика

1 голос
/ 27 марта 2019

Я определил следующую грамматику, используя Parse :: RecDescent

my $grammar = q{

top : operand equal value { print $item{value} }

operand: /\w+/     

equal : /\=/

value : { my $value = extract_quotelike($text) ;$return =$value;} 

};

, которую я хочу обработать в следующих случаях:

X = 2 -> должен вывести 2

X = "2" -> должен вывести 2

x = '2' -> должен вывести 2

, но приведенная выше грамматика дает разные результаты:

для x= 2 не удалось разобрать его

для x = "2" -> вывести "2"

для x = '2' -> вывести '2'

Любая идея изменить вышеуказанную грамматику, чтобы напечатать 2 во всех 3 вышеупомянутых случаях, т.е. удалить кавычки

1 Ответ

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

build_parser.pl:

use strict;
use warnings;

use Parse::RecDescent qw( );

Parse::RecDescent->Precompile(<<'__EOS__', "Parser");
   {
      # The code in rules is also covered by these pragmas.
      use strict;
      use warnings;

      sub dequote { substr($_[0], 1, -1) =~ s/\\(.)/$1/srg }
   }

   start     : assign /\Z/ { $item[1] }

   assign    : lvalue '=' expr { [ 'assign', $item[1], $item[3] ] }

   lvalue    : IDENT

   expr      : NUM_LIT { [ 'num_const', $item[1] ] }
             | STR_LIT { [ 'str_const', $item[1] ] }

   # TOKENS
   # ----------------------------------------

   IDENT     : \w+

   NUM_LIT   : /[0-9]+/

   STR_LIT   : /'(?:[^'\\]++|\\.)*+'/s { dequote($item[1]) }
             | /"(?:[^"\\]++|\\.)*+"/s { dequote($item[1]) }

__EOS__

Настройте определение строковых литералов в соответствии со своими потребностями (но не забудьте настроить и правило, и dequote).

Запуск build_parser.pl сгенерирует Parser.pm, который можно использовать следующим образом:

use strict;
use warnings;

use FindBin qw( $RealBin );
use lib $RealBin;

use Data::Dumper qw( Dumper );
use Parser       qw( );

my $parser = Parser->new();
print(Dumper( $parser->start('x = 2') ));
...