这份储备声明是否难以理解或有缺陷?
Is this reserve declaration hard to understand or defective?
我在使用保留(反斜杠)声明来消除优先级歧义时遇到问题。下面是一个独立的例子。产生式 'Ipv4Address' 是 'Domain0' 的严格子集。但是,在解析 URL 时,您希望以不同于域名的方式处理点分四组地址,因此您希望将 'Domain0' 分成两部分; 'Domain1' 是这两部分之一。但是,包含的测试套件在 't3()' 处失败,其中 'Domain1' 正在接受一个 IP 地址,看起来应该将其排除在外。
这是reserve声明的问题,还是当前版本Rascal的缺陷?我目前在 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" 正在接受不应该接受的行为。奇怪的是 "IPv4Address > Domain1" 也引发了歧义,但我猜这与当前的孤立示例具有相同的根本原因。
关键字保留的差异运算符当前仅在右侧是表示为字面关键字的析取的有限语言(如 "if" | "then" | "while"
或定义如下的非终端)时才能正常工作:lexical X = "if" | "then" | "while". And then you can write
A \ X` 一些效果。
对于其他类型的非终端,解析器只是生成但 \
约束没有效果。您写了 Domain0 \ IPv4Address
并且 IPv3Address 不符合上述假设。
(我们应该对此添加警告或生成一个可以实现语言差异的完整语义的解析器;但那是另一次)。
不可否认,这样一个强大的差异运算符可以用来表达非终结符之间的某种偏好顺序。唉。
可能的(草图)解决方案:
- 阶段两遍解决方案:使用更通用的
Subdomain
语法解析输入,然后在一次传递所有四元组中进行模式和匹配重写到 IPv4Address
- 最大咀嚼解决方案:使用遵循限制来调整语法以实现 IPv4Address 的急切行为,例如
{Subdomain !>> [.][0-9] "."}+
或类似的东西。
我在使用保留(反斜杠)声明来消除优先级歧义时遇到问题。下面是一个独立的例子。产生式 'Ipv4Address' 是 'Domain0' 的严格子集。但是,在解析 URL 时,您希望以不同于域名的方式处理点分四组地址,因此您希望将 'Domain0' 分成两部分; 'Domain1' 是这两部分之一。但是,包含的测试套件在 't3()' 处失败,其中 'Domain1' 正在接受一个 IP 地址,看起来应该将其排除在外。
这是reserve声明的问题,还是当前版本Rascal的缺陷?我目前在 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" 正在接受不应该接受的行为。奇怪的是 "IPv4Address > Domain1" 也引发了歧义,但我猜这与当前的孤立示例具有相同的根本原因。
关键字保留的差异运算符当前仅在右侧是表示为字面关键字的析取的有限语言(如 "if" | "then" | "while"
或定义如下的非终端)时才能正常工作:lexical X = "if" | "then" | "while". And then you can write
A \ X` 一些效果。
对于其他类型的非终端,解析器只是生成但 \
约束没有效果。您写了 Domain0 \ IPv4Address
并且 IPv3Address 不符合上述假设。
(我们应该对此添加警告或生成一个可以实现语言差异的完整语义的解析器;但那是另一次)。
不可否认,这样一个强大的差异运算符可以用来表达非终结符之间的某种偏好顺序。唉。
可能的(草图)解决方案:
- 阶段两遍解决方案:使用更通用的
Subdomain
语法解析输入,然后在一次传递所有四元组中进行模式和匹配重写到 IPv4Address - 最大咀嚼解决方案:使用遵循限制来调整语法以实现 IPv4Address 的急切行为,例如
{Subdomain !>> [.][0-9] "."}+
或类似的东西。