流氓歧义没有通过消歧规则解决

Rascal ambiguity not resolved by disambiguation rules

我正在尝试消除歧义,与几天前 的思路相同。在上一个问题中,语言实现中存在未记录的限制;我想知道这里是否发生了类似的事情。

测试 [tuvw]1 都抛出歧义异常(顺便说一句:你是如何捕捉到这些异常的?[编辑:已回答])。所有这些看起来都应该通过。请注意,它们必须明确才能通过。优先规则 Scheme 和保留规则 UnknownScheme[23] 似乎都没有消除歧义。可能与我不理解的遵循规则有一些互动;这可能是另一个限制或缺陷。怎么了?

我在不稳定的分支上。版本(来自 Eclipse):0.10.0.201806220838

编辑。 我修改了示例代码以更清楚地突出显示正在发生的事情。我删除了一些冗余测试和运行正常的测试。我扩展了一些可能冗长的诊断。我更改了上面的说明以匹配。更新结果如下。

看起来这里有两种不同的东西在起作用。 "http" 在测试 s1[ab] 中被 KnownSchemeUnknownScheme 接受(正确)。它似乎表现得好像 Scheme 中的优先级声明只是不起作用,就好像 > 被替换为 |.

在另一种情况下,测试 s1[cde] 失败,但 s1f 通过。这看起来更像是一个缺陷。显然,可以保留一个关键字,但不能超过一个。由于各种保留声明都失败了,因此在放入替代项时会出现歧义也就不足为奇了。

module ssce

import analysis::grammars::Ambiguity;
import IO;

lexical Scheme = AnyScheme ; 
lexical AnyScheme = KnownScheme > UnknownScheme ;
lexical AnySchemeChar = [a-z*];
lexical KnownScheme = KnownSchemes !>> AnySchemeChar ;  
lexical KnownSchemes = "http" | "https" | "http*" | "javascript" ;
lexical UnknownScheme = UnknownFixedScheme | UnknownWildScheme ;
lexical UnknownFixedScheme = [a-z]+ !>> AnySchemeChar ;
lexical UnknownWildScheme = [a-z]* '*' AnySchemeChar* !>> AnySchemeChar ;

lexical Scheme2 = UnknownScheme2 | KnownScheme ;
lexical UnknownScheme2 = UnknownScheme \ KnownSchemes ;
lexical Scheme3 = UnknownScheme3 | KnownScheme ;
lexical UnknownScheme3 = AnySchemeChar+ \ KnownSchemes ;
lexical Scheme4 = UnknownScheme4 | KnownScheme ;
lexical UnknownScheme4 = AnySchemeChar+ \ ("http"|"https") ;
lexical Scheme5 = UnknownScheme5 | KnownScheme ;
lexical UnknownScheme5 = AnySchemeChar+ \ "http" ;

test bool t1() { return parseAccept( #Scheme, "http" ); }
test bool u1() { return parseAccept( #Scheme2, "http" ); }
test bool v1() { return parseAccept( #Scheme3, "http" ); }
test bool w1() { return parseAccept( #Scheme4, "http" ); }
test bool x1() { return parseAccept( #Scheme5, "http" ); }
test bool s1a() { return parseAccept( #KnownScheme, "http" ); }
test bool s1b() { return parseAccept( #UnknownScheme, "http" ); }
test bool s1c() { return parseReject( #UnknownScheme2, "http" ); }
test bool s1d() { return parseReject( #UnknownScheme3, "http" ); }
test bool s1e() { return parseReject( #UnknownScheme4, "http" ); }
test bool s1f() { return parseReject( #UnknownScheme5, "http" ); }

bool verbose = false;

bool parseAccept( type[&T<:Tree] begin, str input )
{
    try
    {
        parse(begin, input, allowAmbiguity=false);
    }
    catch ParseError(loc _):
    {
        return false;
    }
    catch Ambiguity(loc l, str a, str b):
    {
        if (verbose)
        {
            println("[Ambiguity] " + a + ", " + b);
            Tree tt = parse(begin, input, allowAmbiguity=true) ;
            iprintln(tt);
            list[Message] m = diagnose(tt) ;
            println( ToString(m) );
        }
        fail;
    }
    return true;
}

bool parseReject( type[&T<:Tree] begin, str input )
{
    try
    {
        parse(begin, input, allowAmbiguity=false);
    }
    catch ParseError(loc _):
    {
        return true;
    }
    return false;
}

str ToString( list[Message] msgs ) =
    ( ToString( msgs[0] ) | it + "\n" + ToString(m) | m <- msgs[1..]  );

str ToString( Message msg)
{
    switch(msg)
    {
        case error(str s, loc _): return "error: " + s;
        case warning(str s, loc _): return "warning: " + s;
        case info(str s, loc _): return "info: " + s;
    }
    return "";
}

我一直在制作这个歧义诊断工具,下面是它为您的语法设计的工具。您似乎发现了更多我们需要记录和编写小跳棋的东西。

\ 的格式是否正确是模糊的。

问题是 \ 运算符只接受文字字符串,例如 A \ "a" \ "b" 或定义为 keyword Hello = "a" | "b";keyword 非终结符,用作 A \ Hello, 仅此而已。所以 A \ ("a" | "b") 也是不允许的,还有间接的非终端,比如 A \ Hello where lexical Hello = Bye; lexical Bye = "if" | "then";也不允许。只有最简单的形式。

跟随限制的格式正确

!>> 的类似规则不允许 !>> 运算符右侧的任何非终结符。

所以 [a-z]+ !>> [a-z][a-z]+ !>> "*",但 不是 [a-z]+ \ myCharClass 其中 lexical myCharClass = [a-z];

角色的名字-类 在我们的 todoy 列表中;但它们不会像非终端。更像是将在解析器生成器时替换的别名。

整个单词

关键字保留只有在从整个单词中减去句子时才有效。有时你必须对非终端进行分组才能做到这一点:

  • lexical Ex = ([a-z]+ "*") \ "https*" 而不是 lexical Ex = [a-z]+ "*" \ "https*")

后者会尝试从"*"语言中减去"https*"语言。第一个作品。

不区分大小写

  • 'if'lexical 'if' = [iI][fF];
  • 定义
  • "if"lexical "if" = [i][f];
  • 定义
  • '*'lexical '*' = [*];
  • 定义
  • "*"lexical "*" = [*];
  • 定义

新语法

我使用随机生成器生成了所有我能找到的歧义,并通过添加关键字保留逐步解决它们:

lexical Scheme = AnyScheme ; 
lexical AnyScheme = KnownScheme > UnknownScheme ;
lexical AnySchemeChar = [a-z*];
lexical KnownScheme = KnownSchemes !>> AnySchemeChar ;  
keyword KnownSchemes = "http" | "https" | "http*" | "javascript" ;
lexical UnknownScheme = UnknownFixedScheme | UnknownWildScheme ;
lexical UnknownFixedScheme = [a-z]+ !>> AnySchemeChar \ KnownSchemes ;
lexical UnknownWildScheme = ([a-z]* '*' AnySchemeChar*) !>> AnySchemeChar  \ KnownSchemes ;