У меня уже есть 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
, я полагаю.
ОБНОВЛЕНИЕ: оказалось, что пропускать пробелы было не лучшей идеей, поэтому через некоторое время я получил следующее: ссылка на суть
Спасибо 280Z28 за подсказку!