我正在寻找一种方法来防止在不期望这些KEYWORDS的地方进行KEYWORDS匹配。
看看下面的语法。 “ APPLY ”和“ OUTPUT ”都是关键字。 ' OUTPUT '的参数包含任何字符。
一切正常但如果此参数包含单词 APPLY ,则会引发错误(外部输入APPLY期待RULE_END)。
有没有办法解决这个问题? 感谢。
示例文字
APPLY, 'an id' $
OUTPUT, A text $
OUTPUT, A text with the word APPLY $
DSL
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
statement+=Statement*;
Statement:
ApplyStatement | OutputStatement;
OutputStatement:
'OUTPUT' ',' out+=EXTENDLABEL* end=END;
ApplyStatement:
'APPLY' ',' id=LABELIDENTIFIER end=END;
terminal fragment LETTER:
'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T'
| 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' |
'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
terminal LABELIDENTIFIER:
"'"->"'";
terminal EXTENDLABEL:
(LETTER) (LETTER)*;
terminal END:
'$' !('\n' | '\r')*;
答案 0 :(得分:0)
我看到了一些可以解决问题的方法。首先,您可以逃避出现的关键字,例如Xbase语言使用'^'字符作为转义字符;如果由于任何原因编写关键字时出现问题,可以在前面加上“^”,这样就可以了。同样,如果您将字符串放在特定符号中,例如撇号,它会有很大帮助。当然,这些解决方案需要改变您自己的语言,您可能会或可能不会这样做。
您也可以使用数据类型规则替换EXTENDLABEL终端。这为解决冲突提供了更大的灵活性;在最坏的情况下,您可以添加语言关键字作为选项我通过切线related case in the Eclipse forums建议了这条路线。
答案 1 :(得分:0)
另一个解决方案是在解析器使用它之前更改令牌的ID。令牌由词法分析器提供,您的解析器将在输入中使用这些令牌来生成AST。因此,我们的想法是在将标记传递给解析器之前更改标记。
要做到这一点,你需要声明自己的解析器:
@Override
public Class<? extends IParser> bindIParser() {
return ModelParser.class;
}
注意:您的解析器将扩展您生成的语法解析器。
然后你需要覆盖以下方法来介绍你自己的TokenSource:
override protected XtextTokenStream createTokenStream(TokenSource tokenSource) {
return new TokenSource(tokenSource, getTokenDefProvider());
}
您拥有令牌源需要扩展'XtextTokenStream'。
需要覆盖方法'LT'后如下:
override LT(int k) {
var Token token = super.LT(k)
if(token != null && token.text != null) token.tokenOverride(k);
token
}
然后你只需要更改ID:
def void tokenOverride(Token token, int index){
switch (token.text){
case "APPLY" : {
overrideType(t_parameter, InternalModelParser.RULE_ID);
}
}
}
def void overrideType(Token token, int i) {
token.type = i
}
注意:不要忘记在更改令牌ID之前添加条件,在此示例中,所有令牌“APPLY”将成为ID。
当然,在交换机内部,您可以使用令牌“应用”的ID代替令牌的文本。