2015-06-22 8 views
9

का उपयोग कर नेस्टेड बूलियन एक्सप्रेशन पार्सर मैं एक नेस्टेड बूलियन अभिव्यक्ति का विश्लेषण करने की कोशिश कर रहा हूं और अभिव्यक्ति के भीतर अलग-अलग स्थितियों को अलग-अलग प्राप्त कर रहा हूं। उदाहरण के लिए, यदि इनपुट स्ट्रिंग है:एएनटीएलआर

(ए = ए या बी = बी या सी = सी और ((डी = डी और ई = ई) या (एफ = एफ और जी = जी))

मैं सही क्रम के साथ शर्तों को प्राप्त करना चाहता हूं। यानी,

डी = डी और ई = ई या एफ = एफ और जी = जी और एक = एक या बी = बी या सी = सी

मैं पार्स करने के लिए ANTLR 4 का उपयोग कर रहा इनपुट पाठ और यहाँ मेरी व्याकरण है:

grammar SimpleBoolean; 

rule_set : nestedCondition* EOF; 

AND : 'AND' ; 
OR : 'OR' ; 
NOT : 'NOT'; 

TRUE : 'TRUE' ; 
FALSE : 'FALSE' ; 

GT : '>' ; 
GE : '>=' ; 
LT : '<' ; 
LE : '<=' ; 
EQ : '=' ; 

LPAREN : '(' ; 
RPAREN : ')' ; 

DECIMAL : '-'?[0-9]+('.'[0-9]+)? ; 

IDENTIFIER : [a-zA-Z_][a-zA-Z_0-9]* ; 

WS : [ \r\t\u000C\n]+ -> skip; 

nestedCondition : LPAREN condition+ RPAREN (binary nestedCondition)*; 
condition: predicate (binary predicate)* 
      | predicate (binary component)*; 
component: predicate | multiAttrComp; 
multiAttrComp : LPAREN predicate (and predicate)+ RPAREN; 
predicate : IDENTIFIER comparator IDENTIFIER; 
comparator : GT | GE | LT | LE | EQ ; 
binary: AND | OR ; 
unary: NOT; 
and: AND; 

और यहाँ जावा कोड है कि मैं यह पार्स करने के लिए उपयोग कर रहा हूँ है:

ANTLRInputStream inputStr = new ANTLRInputStream(input); 
SimpleBooleanLexer lexer = new SimpleBooleanLexer(inputStr); 
TokenStream tokens = new CommonTokenStream(lexer); 
SimpleBooleanParser parser = new SimpleBooleanParser(tokens); 
parser.getBuildParseTree(); 
ParseTree tree = parser.rule_set(); 
System.out.println(tree.toStringTree(parser)); 

कहां tput है:

(rule_set (nestedCondition ((condition (predicate A (comparator =) a) (binary OR) (component (predicate B (comparator =) b)) (binary OR) (component (predicate C (comparator =) c)) (binary AND) (component (multiAttrComp ((predicate (D (comparator =) d) (and AND) (predicate E (comparator =) e)))) (binary OR) (component (multiAttrComp ((predicate F (comparator =) f) (and AND) (predicate G (comparator =) g)))))))) <EOF>) 

मैं कैसे सही क्रम में की स्थिति प्राप्त करने के लिए इस पेड़ को पार्स करने के लिए मदद की तलाश कर रहा हूँ? एएनटीएलआर 3 में, हम^और निर्दिष्ट कर सकते हैं! यह तय करने के लिए कि पेड़ कैसे बनाया गया है (यह thread देखें), लेकिन मैंने सीखा कि यह एएनटीएलआर 4 में समर्थित नहीं है।

क्या कोई सुझाव दे सकता है कि मैं एएनटीएलआर द्वारा बनाई गई पारसीट्री का उपयोग करके जावा में सही क्रम में स्ट्रिंग को कैसे पार्स कर सकता हूं ?

+1

@ बार्टकिअर्स क्या आपको इस समस्या को हल करने का कोई विचार है? –

+0

@ बार्टकिअर्स आप सही हैं। 'जीटी | जीई | एलटी | ली | ईक्यू' की सभी समान प्राथमिकता है और उनका मूल्यांकन 'AND | से पहले किया जाना चाहिए OR'। पार्सिंग को ब्रैकेट '()' पर आधारित होना चाहिए। जो मैं खोज रहा हूं वह ऊपर दिए गए कोड में दिखाए गए पारसीट्री का उपयोग करके जावा में स्ट्रिंग को पार्स करने के तरीके पर सहायता करता है। – Sudhi

+0

हमारे मामले में, जब भी दो घटकों के बीच 'AND' होता है, तो यह हमेशा ब्रैकेट'() 'के अंदर होगा। – Sudhi

उत्तर

12

मैं बस सभी अभिव्यक्तियों को एक expression नियम में लपेटूंगा।

grammar SimpleBoolean; 

parse 
: expression EOF 
; 

expression 
: LPAREN expression RPAREN      #parenExpression 
| NOT expression         #notExpression 
| left=expression op=comparator right=expression #comparatorExpression 
| left=expression op=binary right=expression  #binaryExpression 
| bool           #boolExpression 
| IDENTIFIER          #identifierExpression 
| DECIMAL          #decimalExpression 
; 

comparator 
: GT | GE | LT | LE | EQ 
; 

binary 
: AND | OR 
; 

bool 
: TRUE | FALSE 
; 

AND  : 'AND' ; 
OR   : 'OR' ; 
NOT  : 'NOT'; 
TRUE  : 'TRUE' ; 
FALSE  : 'FALSE' ; 
GT   : '>' ; 
GE   : '>=' ; 
LT   : '<' ; 
LE   : '<=' ; 
EQ   : '=' ; 
LPAREN  : '(' ; 
RPAREN  : ')' ; 
DECIMAL : '-'? [0-9]+ ('.' [0-9]+)? ; 
IDENTIFIER : [a-zA-Z_] [a-zA-Z_0-9]* ; 
WS   : [ \r\t\u000C\n]+ -> skip; 

ऊपर व्याकरण का परीक्षण करने के लिए निम्न त्वरित और गंदा परीक्षण का उपयोग करें: से पहले अपने binary अभिव्यक्ति विकल्प यकीन comparator ऑपरेटरों अधिक मज़बूती से बाँध OR से और AND बनाने के लिए comparator भाव विकल्प परिभाषित करने के लिए सुनिश्चित करें कक्षाएं:

public class Main { 

    public static void main(String[] args) throws Exception { 

    Map<String, Object> variables = new HashMap<String, Object>() {{ 
     put("A", true); 
     put("a", true); 
     put("B", false); 
     put("b", false); 
     put("C", 42.0); 
     put("c", 42.0); 
     put("D", -999.0); 
     put("d", -1999.0); 
     put("E", 42.001); 
     put("e", 142.001); 
     put("F", 42.001); 
     put("f", 42.001); 
     put("G", -1.0); 
     put("g", -1.0); 
    }}; 

    String[] expressions = { 
     "1 > 2", 
     "1 >= 1.0", 
     "TRUE = FALSE", 
     "FALSE = FALSE", 
     "A OR B", 
     "B", 
     "A = B", 
     "c = C", 
     "E > D", 
     "B OR (c = B OR (A = A AND c = C AND E > D))", 
     "(A = a OR B = b OR C = c AND ((D = d AND E = e) OR (F = f AND G = g)))" 
    }; 

    for (String expression : expressions) { 
     SimpleBooleanLexer lexer = new SimpleBooleanLexer(new ANTLRInputStream(expression)); 
     SimpleBooleanParser parser = new SimpleBooleanParser(new CommonTokenStream(lexer)); 
     Object result = new EvalVisitor(variables).visit(parser.parse()); 
     System.out.printf("%-70s -> %s\n", expression, result); 
    } 
    } 
} 

class EvalVisitor extends SimpleBooleanBaseVisitor<Object> { 

    private final Map<String, Object> variables; 

    public EvalVisitor(Map<String, Object> variables) { 
    this.variables = variables; 
    } 

    @Override 
    public Object visitParse(SimpleBooleanParser.ParseContext ctx) { 
    return super.visit(ctx.expression()); 
    } 

    @Override 
    public Object visitDecimalExpression(SimpleBooleanParser.DecimalExpressionContext ctx) { 
    return Double.valueOf(ctx.DECIMAL().getText()); 
    } 

    @Override 
    public Object visitIdentifierExpression(SimpleBooleanParser.IdentifierExpressionContext ctx) { 
    return variables.get(ctx.IDENTIFIER().getText()); 
    } 

    @Override 
    public Object visitNotExpression(SimpleBooleanParser.NotExpressionContext ctx) { 
    return !((Boolean)this.visit(ctx.expression())); 
    } 

    @Override 
    public Object visitParenExpression(SimpleBooleanParser.ParenExpressionContext ctx) { 
    return super.visit(ctx.expression()); 
    } 

    @Override 
    public Object visitComparatorExpression(SimpleBooleanParser.ComparatorExpressionContext ctx) { 
    if (ctx.op.EQ() != null) { 
     return this.visit(ctx.left).equals(this.visit(ctx.right)); 
    } 
    else if (ctx.op.LE() != null) { 
     return asDouble(ctx.left) <= asDouble(ctx.right); 
    } 
    else if (ctx.op.GE() != null) { 
     return asDouble(ctx.left) >= asDouble(ctx.right); 
    } 
    else if (ctx.op.LT() != null) { 
     return asDouble(ctx.left) < asDouble(ctx.right); 
    } 
    else if (ctx.op.GT() != null) { 
     return asDouble(ctx.left) > asDouble(ctx.right); 
    } 
    throw new RuntimeException("not implemented: comparator operator " + ctx.op.getText()); 
    } 

    @Override 
    public Object visitBinaryExpression(SimpleBooleanParser.BinaryExpressionContext ctx) { 
    if (ctx.op.AND() != null) { 
     return asBoolean(ctx.left) && asBoolean(ctx.right); 
    } 
    else if (ctx.op.OR() != null) { 
     return asBoolean(ctx.left) || asBoolean(ctx.right); 
    } 
    throw new RuntimeException("not implemented: binary operator " + ctx.op.getText()); 
    } 

    @Override 
    public Object visitBoolExpression(SimpleBooleanParser.BoolExpressionContext ctx) { 
    return Boolean.valueOf(ctx.getText()); 
    } 

    private boolean asBoolean(SimpleBooleanParser.ExpressionContext ctx) { 
    return (boolean)visit(ctx); 
    } 

    private double asDouble(SimpleBooleanParser.ExpressionContext ctx) { 
    return (double)visit(ctx); 
    } 
} 

Main वर्ग चल रहा है निम्न उत्पादन में परिणाम होगा:

012,
1 > 2                 -> false 
1 >= 1.0                -> true 
TRUE = FALSE               -> false 
FALSE = FALSE               -> true 
A OR B                 -> true 
B                  -> false 
A = B                 -> false 
c = C                 -> true 
E > D                 -> true 
B OR (c = B OR (A = A AND c = C AND E > D))       -> true 
(A = a OR B = b OR C = c AND ((D = d AND E = e) OR (F = f AND G = g))) -> true 
+0

धन्यवाद @ BartKiers। मैं कोशिश करूँगा और जल्द ही आपसे संपर्क करूंगा। – Sudhi

+0

यह –

+0

किस प्रकार का काला जादू है मुझे असंगत प्रकारों की तरह त्रुटियां मिल रही हैं: डबल को ऑब्जेक्ट में परिवर्तित नहीं किया जा सकता –

संबंधित मुद्दे