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;

この文法は「あまりにも」貪欲で、処理されるルールは 1 つだけです。つまり、解析を聞くと

@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思います。


更新: 空白をスキップするのは最善のアイデアではないことが判明したため、しばらくすると次のようになりました: link to gist

ヒントをくれた 280Z28 に感謝します!

4

1 に答える 1

2

.*?パーサー ルールでを使用する代わりに、 を使用して~'}'*、それらのルールがルールの末尾を超えて読み取ろうとしないようにしてください。

また、レクサーでは空白をスキップしますが、パーサー ルールでは and を使用しますCHAR+DIGIT+これは、以下が同等であることを意味します。

  1. rule temp[1].future
  2. rule t e m p [ 1 ] . f u t u r e

それを超えると、in other cases3 つではなく 1 つのトークンを作成したため、以下は同等ではありません。

true  in other cases
true  in  other cases

おそらく、次のレクサー ルールを作成することから始めてから、CHARand DIGITrulesfragmentルールを作成する必要があります。

ID : CHAR+;
INT : DIGIT+;
于 2013-07-18T11:20:44.197 に答える