perl - 在语法中分离 G0 和 G1 规则的问题

标签 perl parsing tokenize marpa

我试图让看起来非常基本的 Marpa 语法起作用。我使用的代码如下:

use strict;
use warnings;
use Marpa::R2;
use Data::Dumper;
my $grammar = Marpa::R2::Scanless::G->new(
    {
        source => \(<<'END_OF_SOURCE'),
            :start ::= ExprSingle
            ExprSingle ::= Expr AndExpr

            Expr ~ word

            AndExpr ~ word*
            word ~ [\w]+

            :discard ~ ws
            ws ~ [\s]+
END_OF_SOURCE
    }
);
my $reader = Marpa::R2::Scanless::R->new(
    {
        grammar => $grammar,
    }
);
my $input = 'foo';
$reader->read(\$input);
my $value = $reader->value;
print Dumper $value;

这打印 $VAR1 = \'foo'; .所以它识别一个词就好了。但我想让它识别一串单词
my $input='foo bar'

现在脚本打印:
Error in SLIF G1 read: Parse exhausted, but lexemes remain, at position 4

我想这是因为ExprSingle使用 ~ (match) 运算符,使其成为标记级别 G0 的一部分,而不是结构级别 G1; :discard规则允许 G1 规则之间有空格,而不是 G0 规则。所以我像这样改变语法:
ExprSingle ::= Expr AndExpr

现在没有打印警告,但结果值是 undef而不是包含 'foo' 的东西和 'bar' .老实说,我不确定这意味着什么,因为之前失败的解析引发了实际错误。

我尝试更改语法以进一步分离我认为的 G0 和 G1 规则,但仍然没有运气:
:start ::= ExprSingle
ExprSingle ::= Expr AndExpr

Expr ::= token

AndExpr ::= token*
token ~ word
word ~ [\w]+

:discard ~ ws
ws ~ [\s]+

最终值仍然是undef . trace_terminals显示 'foo' 和 'bar' 都被接受为 token 。我需要做什么来修复这个语法(我的意思是得到一个包含字符串 'foo' 和 'bar' 而不仅仅是 undef 的值)?

最佳答案

默认情况下,规则返回 undef 值,因此在您的情况下,从 $reader->value() 返回\undef 意味着您的解析成功。也就是说,返回 undef 意味着失败,而返回\undef 意味着成功,其中解析评估为 undef。

从更有用的语义开始的一个好的、快速的方法是添加以下行:

:default::= action =>::array

这会导致解析生成 AST。

关于perl - 在语法中分离 G0 和 G1 规则的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17156718/

相关文章:

perl - NPP.EXEC 和 perl --> 保存输出?

c++ - 有效地从字符串中读取括号中的两个逗号分隔的 float ,而不受全局语言环境的影响

java - 如何在Java中创建一个包含带引号的字符串的字符串?

html - 在 PERL 中使用 SSH 运行 bash 命令

perl - 如何在实现 net-snmp 代理时清除 perl 脚本错误?

c# - 用于解析来自 html 代码的链接的正则表达式

c - 如何使用 sscanf 解析输入行?

android - 使用两个分隔符 "|"分割乐趣不起作用

java.io.StreamTokenizer 在遇到下划线时生成空标记

perl - 如何在perl中等待异步文件