我已经有了DSL,并希望为它构建ANTLR4语法。
这是DSL的一个例子:
rule isC {
true when O_M in [5, 6, 17, 34]
false in other cases
}
rule isContract {
true when O_C in ['XX','XY','YY']
false in other cases
}
rule isFixed {
true when F3 ==~ '.*/.*/.*-F.*/.*'
false in other cases
}
rule temp[1].future {
false when O_OF in ['C','P']
true in other cases
}
rule temp[0].scale {
10 when O_M == 5 && O_C in ['YX']
1 in other cases
}
如何简单地使用已经变得混乱的正则表达式来解析DSL - 因此需要语法。
它的工作方式如下:它提取左侧(when
之前)和右侧部分,它们由Groovy进行评估。
我仍然想让它由Groovy评估,但是使用语法组织解析过程。所以,从本质上讲,我需要的是使用某种通配符来提取这些左右部分。
我不幸地想不出怎么做。以下是我到目前为止的情况:
grammar RuleDSL;
rules: basic_rule+ EOF;
basic_rule: 'rule' rule_name '{' condition_expr+ '}';
name: CHAR+;
list_index: '[' DIGIT+ ']';
name_expr: name list_index*;
rule_name: name_expr ('.' name_expr)*;
condition_expr: when_condition_expr | otherwise_condition_expr;
condition: .*?;
result: .*?;
when_condition_expr: result WHEN condition;
otherwise_condition_expr: result IN_OTHER_CASES;
WHEN: 'when';
IN_OTHER_CASES: 'in other cases';
DIGIT: '0'..'9';
CHAR: 'a'..'z' | 'A'..'Z';
SYMBOL: '?' | '!' | '&' | '.' | ',' | '(' | ')' | '[' | ']' | '\\' | '/' | '%'
| '*' | '-' | '+' | '=' | '<' | '>' | '_' | '|' | '"' | '\'' | '~';
// Whitespace and comments
WS: [ \t\r\n\u000C]+ -> skip;
COMMENT: '/*' .*? '*/' -> skip;
这个语法“太”贪婪,只处理一个规则。我的意思是,如果我用
解析@Override
public void enterBasic_rule(Basic_ruleContext ctx) {
System.out.println("ENTERING RULE");
}
@Override
public void exitBasic_rule(Basic_ruleContext ctx) {
System.out.println(ctx.getText());
System.out.println("LEAVING RULE");
}
我有以下输出
ENTERING RULE
-- tons of text
LEAVING RULE
我怎样才能减少贪心,所以如果我解析这个给定的输入,我会得到5个规则?贪婪来自condition
和result
我想。
更新 事实证明,跳过空格并不是最好的主意,所以过了一段时间我得到了以下内容:link to gist
感谢280Z28的提示!
答案 0 :(得分:2)
不要在解析器规则中使用.*?
,而是尝试使用~'}'*
来确保这些规则不会尝试读取规则的结尾。
此外,您跳过词法分析器中的空格,但在解析器规则中使用CHAR+
和DIGIT+
。这意味着以下内容是等效的:
rule temp[1].future
rule t e m p [ 1 ] . f u t u r e
除此之外,您使in other cases
成为单个令牌而不是3,因此以下不等于:
true in other cases
true in other cases
您应该首先制定以下词法分析器规则,然后制定CHAR
和DIGIT
规则fragment
规则:
ID : CHAR+;
INT : DIGIT+;