首页 文章

遏制ANTLR4贪婪(为现有DSL构建ANTLR4语法)

提问于
浏览
0

我已经有了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条规则?贪婪来自 conditionresult 我想 .


UPDATE: 事实证明,跳过空格并不是最好的主意,所以一段时间后我最终得到以下内容:link to gist

感谢280Z28的提示!

1 回答

  • 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
    

    您应该首先制定以下词法分析器规则,然后制定 CHARDIGIT 规则 fragment 规则:

    ID : CHAR+;
    INT : DIGIT+;
    

相关问题