2

从大表达式解析/识别双引号字符串时出现问题。

use strict;
use Marpa::R2;
use Data::Dumper;

my $grammar = Marpa::R2::Scanless::G->new({
    default_action => '[values]',
    source => \(<<'END_OF_SOURCE'),

:start ::= expression

expression ::= expression OP expression
expression ::= expression COMMA expression
expression ::= func LPAREN PARAM RPAREN
expression ::= PARAM
PARAM ::= STRING | REGEX_STRING

:discard    ~ sp
sp          ~ [\s]+

COMMA                      ~ [,]
STRING                     ~ [^ \/\(\),&:\"~]+
REGEX_STRING               ~ yet to identify
OP                         ~ ' - ' | '&'
LPAREN                     ~ '('
RPAREN                     ~ ')'
func                       ~ 'func'

END_OF_SOURCE
});

my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});

my $input1 = "func(foo)&func(bar)";-> 能够通过将 foo 和 bar 解析为 STRING LEXEME 来正确解析它。

my $input2 = "\"foo\"";-> 在这里,我想将 foo 解析为 regex_string LEXEME。REGEX_STRING 是用双引号括起来的东西。

my $input3 = "func(\"foo\") - func(\"bar\")";-> 这里,func 应该被当作 func LEXEME,( 应该是 LPAREN,) 应该是 RPAREN,foo 作为 REGEX_STRING,- 作为 OP 和 func(\"bar\") 相同

my $input4 = "func(\"foo\")";-> 此处,func 应视为 func LEXEME,( 应为 LPAREN,) 应为 RPAREN,foo 应为 REGEX_STRING

print "Trying to parse:\n$input\n\n";
$recce->read(\$input);
my $value_ref = ${$recce->value};
print "Output:\n".Dumper($value_ref);

我尝试了什么: 第一种方法: 我的 REGEX_STRING 应该是:REGEX_STRING -> ~ '\"([^:]*?)\"'

如果我尝试将上面REGEX_STRING的代码放入带有输入表达式的代码中,my $input4 = "func(\"foo\")";则会出现如下错误:

SLIF 解析中的错误:在第 1 行第 5 列找不到词位 * 错误前的字符串:func(* 错误出现在第 1 行第 5 列和字符 0x0022 '"', ... * 此处:"foo") Marpa::R2 异常

方法二:

尝试包括如下规则:

PARAM ::= STRING | REGEX_STRING
REGEX_STRING ::= '"' QUOTED_STRING '"'

STRING ~ [^ \/\(\),&:\"~]+
QUOTED_STRING ~ [^ ,&:\"~]+

这里的问题是->输入是使用:

my $input4 = "func(\"foo\")";

所以,这里它给出了错误,因为现在有两种方法来解析这个表达式,或者双引号之间的整个东西是 func(\"foo\") 被当作 QUOTED_STRING 或者 func 应该被当作 func LEXEME 等等。

请帮助我如何解决这个问题。

4

2 回答 2

1
use 5.026;
use strictures;
use Data::Dumper qw(Dumper);
use Marpa::R2 qw();

my $grammar = Marpa::R2::Scanless::G->new({
    bless_package => 'parsetree',
    source        => \<<'',
:default ::= action => [values] bless => ::lhs
lexeme default = bless => ::name latm => 1
:start ::= expression
expression ::= expression OP expression
expression ::= expression COMMA expression
expression ::= func LPAREN PARAM RPAREN
expression ::= PARAM
PARAM ::= STRING | REGEXSTRING
:discard    ~ sp
sp          ~ [\s]+
COMMA           ~ [,]
STRING          ~ [^ \/\(\),&:\"~]+
REGEXSTRING     ::= '"' QUOTEDSTRING '"'
QUOTEDSTRING    ~ [^ ,&:\"~]+
OP              ~ ' - ' | '&'
LPAREN          ~ '('
RPAREN          ~ ')'
func            ~ 'func'

});
# say $grammar->show_rules;

for my $input (
    'func(foo)&func(bar)', '"foo"', 'func("foo") - func("bar")', 'func("foo")'
) {
    my $r = Marpa::R2::Scanless::R->new({
        grammar => $grammar,
#         trace_terminals => 1
    });
    $r->read(\$input);
    say "# $input";
    say Dumper $r->value;
}
于 2018-03-22T12:25:26.630 回答
0

有问题的第二种方法对我有用。我只需要包括:

lexeme default = latm => 1

在我的代码中。

于 2018-03-26T17:20:20.270 回答