2012-07-04 2 views
2

Как перейти к оценке логического выражения типа VERB1 OR (VERB2 AND VERB3) ИЛИ (VERB4) ", введенного во время выполнения. VERB * являются заполнителями для оценки определенных условий. Например, VERB1 может означать проверку наличия записи в базе данных.Оценить логическое выражение во время выполнения

В выражении «VERB1 ИЛИ (VERB2 И VERB3) ИЛИ (VERB4)», другие глаголы не должны выполняться, если VERB1 верно

EDIT: Пример описан в http://www.alittlemadness.com/2006/06/05/antlr-by-example-part-1-the-language/, кажется, очень похоже на то, что я пытаюсь сделать , Тем не менее, шаг оптимизации (другие глаголы не должны выполняться, если VERB1 истинно), похоже, не существует.

+0

У вас пробовал правила, такие как Drools, http://openrules.com/ и т. д.? Или другой альтернативой является использование Ognl или MVEL или Spring EL (http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/expressions.html). –

+0

Мы кратко рассмотрели Drools, но не другие. Мы чувствовали, что Drools может быть излишним, чтобы представить в нашем проекте и не были ясны, если он решит эту проблему. – dsatish

ответ

1

Если вы можете использовать || и && вместо AND и OR, вы можете просто использовать недостающие методы собственности и the GroovyShell base class setting Groovy, как так:

import org.codehaus.groovy.control.CompilerConfiguration 

// The command to be executes 
def command = "VERB1 || (VERB2 && VERB3) || (VERB4)" 

// Set a base class for the GroovyShell 
new CompilerConfiguration().with { compiler -> 
    compiler.scriptBaseClass = 'VerbHandlingBaseClass' 
    new GroovyShell(this.class.classLoader, new Binding(), compiler).with { shell -> 
    // and evaluate the command 
    shell.evaluate(command) 
    } 
} 

abstract class VerbHandlingBaseClass extends Script { 
    boolean VERB1() { 
    System.out.println('CHECK THE DATABASE, RETURN FALSE') 
    false 
    } 

    boolean VERB2() { 
    System.out.println('WRITE A LOG ENTRY RETURN TRUE') 
    true 
    } 

    boolean VERB3() { 
    System.out.println('VALIDATE SOMETHING, RETURN TRUE') 
    true 
    } 

    boolean VERB4() { 
    System.out.println('THIS WONT BE REACHED, AS VERB2 && VERB3 == true') 
    true 
    } 

    def propertyMissing(String name) { 
    "$name"() 
    } 
} 

Это должно напечатать:

CHECK THE DATABASE, RETURN FALSE 
WRITE A LOG ENTRY RETURN TRUE 
VALIDATE SOMETHING, RETURN TRUE 
+0

Я думаю, что это должно работать для меня. БЛАГОДАРЯ! – dsatish

0

Вы упомянули ANTLR в своих темах: вам понравилось? Вы можете создать полную логическую грамматику в ANTLR, но она становится намного сложнее, когда вы достигаете уровня оценки глаголов.

Если существует небольшой фиксированный набор глаголов, которые могут быть запрошены, вы можете легко создать сопоставление между глаголами и функциями.

Если существует более широкий список глаголов, вы можете использовать отражение для вызова определенных методов для их оценки.

Если ваши глаголы могут включать в себя математические сравнения, все это становится немного сложнее, когда вы создаете математический лексер и парсер.

Без особого вопроса и знаний о том, что вы пробовали в ANTLR Я не уверен, что могу дать вам гораздо больше советов.

EDIT: На основе ваших комментариев я добавлю еще несколько. Вы можете добавить правила синтаксического анализа для вашей грамматики:

boolean_or returns [boolean b] 
    : b1=boolean_and {$b = $b1.b;} 
     (OR b2=boolean_and {$b = $b || $b2.b;})* 
    ; 

boolean_atom returns [boolean b] 
    : 
    ((numeric_comparison)=> b1=numeric_comparison {$b = $b1.b;} 
    | TRUE {$b = true;} | FALSE {$b = false;} 
    | s1=VERB {$b = evalVerb($s1.s);} 
    | LPAREN b1=boolean_expr RPAREN {$b = $b1.b;} 
    ) 

; 

Вот небольшая часть булевой парсер Я в настоящее время использую. Вы можете заполнить пробелы.

И затем вызвать парсер, используя что-то вроде

ANTLRStringStream in = new ANTLRStringStream(booleanString); 
ActionLexer lexer = new ActionLexer(in); 
CommonTokenStream tokens = new CommonTokenStream(lexer); 
BooleanParser parser = new BooleanParser(tokens); 
try { 
    return parser.eval(); 
} catch (Exception e) { 
} 

это не учитывает ваше требование о возвращении рано, но я уверен, что вы можете выяснить, как сделать это.

Возможно, это не лучший способ сделать что-то, но это то, как я работал в прошлом. Надеюсь это поможет.

+0

Я только начал изучать ANTLR. Из моего понимания, определяя грамматику, ANTLR будет генерировать дерево (подобное дереву выражений, показанному в http: // stackoverflow.ком/вопросы/4589951/синтаксическая-ан-арифметическое выражение-строительный-а-дерево-из-она-в-Java). Дерево все еще необходимо оценить - оценщик не предоставляется ANTLR. – dsatish

+0

Кажется, что «оценщик», о котором я говорю, известен как «Tree Parser» в ANGTR lingo – dsatish