1

我想知道如何在没有针对每个可能排列的具体模式匹配的情况下处理多个选项。

以下是我面临的问题的简化示例:

lexical Int = [0-9]+;
syntax Bool = "True" | "False";
syntax Period = "Day" | "Month" | "Quarter" | "Year";
layout Standard = [\ \t\n\f\r]*; 
syntax Optionals = Int? i Bool? b Period? p;

str printOptionals(Optionals opt){
    str res = "";
    if(!isEmpty("<opt.i>")) { // opt has i is always true (same for opt.i?)
        res += printInt(opt.i);
    }
    if(!isEmpty("<opt.b>")){
        res += printBool(opt.b);
    }
    if(!isEmpty("<opt.p>")) {
        res += printPeriod(opt.period);
    }
    return res;
}

str printInt(Int i) = "<i>";
str printBool(Bool b) = "<b>";
str printPeriod(Period p) = "<p>";

但是,这给出了错误消息:

The called signature: printInt(opt(lex("Int"))), does not match the declared signature: str printInt(sort("Int"));

当我知道它在那里时,我如何摆脱它?

4

3 回答 3

1

github 上的当前 master 具有以下处理选项的功能:它们可以迭代。

例如:

if (Int i <- opt.i) {
    res += printInt(i);
}

如果可选值不存在,<-则将立即生成false,否则循环一次并将存在的值绑定到模式。

于 2014-08-14T10:56:36.677 回答
1

我不确定这是多么理想,但你现在可以这样做:

if (/Int i := opt.i) {
    res += printInt(i);
}

如果它在那里,这Int将从内部提取,但如果没有作为选项之一提供,则匹配将失败。opt.iInt

于 2014-05-13T13:01:38.907 回答
0

一个无类型的解决方案是从解析树中投影出元素:

rascal>opt.i.args[0];
Tree: `1`
Tree: appl(prod(lex("Int"),[iter(\char-class([range(48,57)]))],{}),[appl(regular(iter(\char-class([range(48,57)]))),[char(49)])[@loc=|file://-|(0,1,<1,0>,<1,1>)]])[@loc=|file://-|(0,1,<1,0>,<1,1>)]

但是,然后要将其转移回Int您必须进行模式匹配,如下所示:

rascal>if (Int i := opt.i.args[0]) { printInt(i); }
str: "1"

在这里可以编写一个通用的转换函数来提供帮助:

rascal>&T cast(type[&T] t, value v) { if (&T a := v) return a; throw "cast exception"; }
ok
rascal>printInt(cast(#Int, opt.i.args[0]))
str: "1"

不过,我相信 Rascal 在这里缺少一个功能。像这样的东西将是一个很好的功能请求:

rascal>Int j = opt.i.value;
rascal>opt.i has value
bool: true
于 2014-05-13T18:55:41.970 回答