流氓歧义没有通过消歧规则解决
Rascal ambiguity not resolved by disambiguation rules
我正在尝试消除歧义,与几天前 的思路相同。在上一个问题中,语言实现中存在未记录的限制;我想知道这里是否发生了类似的事情。
测试 [tuvw]1
都抛出歧义异常(顺便说一句:你是如何捕捉到这些异常的?[编辑:已回答])。所有这些看起来都应该通过。请注意,它们必须明确才能通过。优先规则 Scheme
和保留规则 UnknownScheme[23]
似乎都没有消除歧义。可能与我不理解的遵循规则有一些互动;这可能是另一个限制或缺陷。怎么了?
我在不稳定的分支上。版本(来自 Eclipse):0.10.0.201806220838
编辑。
我修改了示例代码以更清楚地突出显示正在发生的事情。我删除了一些冗余测试和运行正常的测试。我扩展了一些可能冗长的诊断。我更改了上面的说明以匹配。更新结果如下。
看起来这里有两种不同的东西在起作用。 "http"
在测试 s1[ab]
中被 KnownScheme
和 UnknownScheme
接受(正确)。它似乎表现得好像 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 ;
我正在尝试消除歧义,与几天前
测试 [tuvw]1
都抛出歧义异常(顺便说一句:你是如何捕捉到这些异常的?[编辑:已回答])。所有这些看起来都应该通过。请注意,它们必须明确才能通过。优先规则 Scheme
和保留规则 UnknownScheme[23]
似乎都没有消除歧义。可能与我不理解的遵循规则有一些互动;这可能是另一个限制或缺陷。怎么了?
我在不稳定的分支上。版本(来自 Eclipse):0.10.0.201806220838
编辑。 我修改了示例代码以更清楚地突出显示正在发生的事情。我删除了一些冗余测试和运行正常的测试。我扩展了一些可能冗长的诊断。我更改了上面的说明以匹配。更新结果如下。
看起来这里有两种不同的东西在起作用。 "http"
在测试 s1[ab]
中被 KnownScheme
和 UnknownScheme
接受(正确)。它似乎表现得好像 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 ;