代码之家  ›  专栏  ›  技术社区  ›  eh9

这份储备声明难以理解或有缺陷吗?

  •  0
  • eh9  · 技术社区  · 6 年前

    在使用优先级(反斜杠)声明进行优先级消歧时,我遇到了一个问题。下面是一个独立的示例。生产“ipv4address”是“domain0”的严格子集。不过,在解析url时,您希望虚线四元地址的处理方式不同于域名,因此您希望将“domain0”拆分为两部分;“domain1”是这两部分之一。然而,测试套件在“T3()”中失败,其中Dima1正在接受一个IP地址,它看起来应该被排除在外。

    这是保留声明的一个问题,或者这是当前流氓版本中的一个缺陷吗?我现在在0.10.x不稳定分支上,根据建议,看看是否纠正了另一个问题(与导师)。我还没有检查稳定分支,因为保持它们的安装意味着并行的Eclipse环境,这是我没有动力去做的。

    module grammar_test
    
    import ParseTree;
    
    syntax Domain0 = { Subdomain '.' }+;
    syntax Domain1 = Domain0 \ IPv4Address ;
    lexical Subdomain = [0-9A-Za-z]+ | [0-9A-Za-z]+'-'[a-zA-Z0-9\-]*[a-zA-Z0-9] ;
    lexical IPv4Address = DecimalOctet '.' DecimalOctet '.' DecimalOctet '.' DecimalOctet ; 
    lexical DecimalOctet = [0-9] | [1-9][0-9] | '1'[0-9][0-9] | '2'[0-4][0-9] | '25'[0-5] ;
    
    test bool t1()
    {
        return parseAccept(#IPv4Address, "192.168.0.1");
    }   
    
    test bool t2()
    {
        return parseAccept(#Domain0, "192.168.0.1");
    }   
    
    test bool t3()
    {
        return parseReject(#Domain1, "192.168.0.1");
    }   
    
    bool parseAccept( type[&T<:Tree] begin, str input )
    {
        try
        {
            parse(begin, input, allowAmbiguity=false);
        }
        catch ParseError(loc _):
        {
            return false;
        }
        return true;
    }
    
    bool parseReject( type[&T<:Tree] begin, str input )
    {
        try
        {
            parse(begin, input, allowAmbiguity=false);
        }
        catch ParseError(loc _):
        {
            return true;
        }
        return false;
    }
    

    这个例子是从更大的代码中删去的。我第一次在更大的范围内遇到错误。使用规则“ipv4address domain1”抛出了一个歧义异常,我跟踪到了“domain1”接受不应该接受的东西的行为。奇怪的是,“IPv4Advest.Gt;Dima1”也造成了歧义,但我猜这与当前孤立的例子有着相同的根本原因。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Jurgen Vinju    6 年前

    关键字保留的差异运算符当前仅能正确地工作,如果右手是一个有限的语言,表示为文字关键字的析取。 "if" | "then" | "while" 或定义如下的非终端: lexical X = "if" | "then" | "while". And then you can write a\x`以获得某种效果。

    对于其他类型的非终端,解析器只是生成的,但是 \ 约束无效。你写 Domain0 \ IPv4Address IPV3地址不符合上述假设。

    (我们应该添加一个警告,或者生成一个解析器,它可以实现语言差异的完整语义;但这是另一个时间)。

    无可否认,这样一个强大的差分算子可以用来表示非终端之间的某种优先顺序。唉。

    可能的(草图)解决方案:

    • 第二阶段传递解决方案:使用更一般的语法解析输入 Subdomain 语法,然后模式和匹配重写在一个单一的过程中全部四倍于ipv4address
    • 最大MunCH解决方案:使用下面的限制来适应语法,以实现IPv4地址的急切行为 {Subdomain !>> [.][0-9] "."}+ 或者什么徒劳的事情。