首页 > 解决方案 > 歧义规则无法解决流氓歧义

问题描述

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

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

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

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

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

在另一种情况下,测试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 "";
}

标签: rascal

解决方案


我一直在制作这个歧义诊断工具,这就是它为您的语法提供的内容。您似乎发现了更多我们需要记录和编写小检查器的东西。

的良构\是模糊的。

问题是该\运算符只接受文字字符串,例如A \ "a" \ "b"或定义为 like 、 used as的keyword非终结符,而没有其他任何内容。所以也是不允许的,还有间接的非终结符,比如where ; 也不允许。只有最简单的形式。keyword Hello = "a" | "b";A \ HelloA \ ("a" | "b")A \ Hellolexical Hello = Bye; lexical Bye = "if" | "then"

遵循限制的良好形成

!>>禁止运算符右侧的任何非终端的类似规则!>>

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

角色类的名称在我们的待办事项清单上;但它们不会像非终端一样。更像是在解析器生成器时被替换的别名。

整个单词

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

  • 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 ;

推荐阅读