使用Marpa:r2perl解析单引号字符串

使用Marpa:r2perl解析单引号字符串,perl,grammar,marpa,regexp-grammars,Perl,Grammar,Marpa,Regexp Grammars,如何使用Marpa:r2解析单引号字符串? 在我下面的代码中,单引号字符串在解析时附加“\” 代码: 上面是所有输入的输出,我不希望第三个输入后面加上“\”和单引号。。我希望它像OUTPUT2一样被解析。请告知 理想情况下,它应该根据参数在单引号之间选择内容:=(')引号(')您的结果不包含\',它包含'转储程序只是将结果格式化为这样,这样就可以清楚地知道字符串中有什么和没有什么 您可以自己测试此行为: use Data::Dumper; my $tick = chr(39); my $bac

如何使用Marpa:r2解析单引号字符串? 在我下面的代码中,单引号字符串在解析时附加“\”

代码:

上面是所有输入的输出,我不希望第三个输入后面加上“\”和单引号。。我希望它像OUTPUT2一样被解析。请告知


理想情况下,它应该根据参数在单引号之间选择内容:=(')引号(')

您的结果不包含
\'
,它包含
'
<代码>转储程序只是将结果格式化为这样,这样就可以清楚地知道字符串中有什么和没有什么

您可以自己测试此行为:

use Data::Dumper;

my $tick = chr(39);
my $back = chr(92);

print "Tick Dumper: " . Dumper($tick);
print "Tick Print:  " . $tick . "\n";
print "Backslash Dumper: " . Dumper($back);
print "Backslash Print:  " . $back . "\n";
您可以在此处看到演示:


如果您不希望输出包含单引号,您可能需要自己将其从输入中删除。

我不太熟悉
Marpa::R2
,但您能否尝试对
表达式
规则使用操作:

Expression ::= Param action => strip_quotes
然后,实现一个简单的报价剥离器,如:

sub MyActions::strip_quotes {
    @{$_[1]}[0] =~ s/^'|'$//gr;
}

关于Data::Dumper输出的另一个答案是正确的。然而,你的语法并没有按照你所期望的方式工作

当你解析输入<代码> 'Foo' < /代码>时,MARPA将考虑三<代码> PARAM < /代码>备选方案。该位置的预测词素为:

  • Unquoted~[^\s\/\(\),&:\“~]+
  • 引用(
是的,最后一个是字面上的
)引号(
),而不是包含单个引号的任何内容

即使它被
(['])引用(['])
:由于最长的标记匹配,未引用的词素将匹配整个输入,包括单引号

“foo”
(带双引号)这样的输入会发生什么情况?现在,只有
词素匹配,然后任何空格都会被丢弃,然后被引用的词素匹配,然后任何空格都会被丢弃,然后关闭
就会被匹配

为了防止这种跳过空白的行为,并防止由于LATM而首选不带引号的规则,将带引号的字符串描述为词素是有意义的。例如:

Param ::= Unquoted | Quoted
Unquoted ~ [^'"]+
Quoted ~ DQ | SQ
DQ ~ '"' DQ_Body '"'  DQ_Body ~ [^"]*
SQ ~ ['] SQ_Body [']  SQ_Body ~ [^']*
然后,这些词素将包含任何引号和转义符,因此您需要对词素内容进行后期处理。您可以使用事件系统(这在概念上是干净的,但实现起来有点麻烦)执行此操作,也可以在解析计算期间添加执行此处理的操作

由于词汇表不能有操作,通常最好添加一个代理产品:

Param ::= Unquoted | Quoted
Unquoted ~ [^'"]+
Quoted ::= Quoted_Lexeme action => process_quoted
Quoted_Lexeme ~ DQ | SQ
DQ ~ '"' DQ_Body '"'  DQ_Body ~ [^"]*
SQ ~ ['] SQ_Body [']  SQ_Body ~ [^']*
然后,该操作可以执行以下操作:

sub process_quoted {
  my (undef, $s) = @_;
  # remove delimiters from double-quoted string
  return $1 if $s =~ /^"(.*)"$/s;
  # remove delimiters from single-quoted string
  return $1 if $s =~ /^'(.*)'$/s;
  die "String was not delimited with single or double quotes";
}

my$input3=“'foo”“”;如果您这样输入,输出中仍然会出现斜杠。此外,如果您将输入设置为:my$input3=“\'foo1\”;这里在输出中也不会显示斜杠。那么,为什么它会显示在第三个斜杠中?
Param ::= Unquoted | Quoted
Unquoted ~ [^'"]+
Quoted ::= Quoted_Lexeme action => process_quoted
Quoted_Lexeme ~ DQ | SQ
DQ ~ '"' DQ_Body '"'  DQ_Body ~ [^"]*
SQ ~ ['] SQ_Body [']  SQ_Body ~ [^']*
sub process_quoted {
  my (undef, $s) = @_;
  # remove delimiters from double-quoted string
  return $1 if $s =~ /^"(.*)"$/s;
  # remove delimiters from single-quoted string
  return $1 if $s =~ /^'(.*)'$/s;
  die "String was not delimited with single or double quotes";
}