анализатор на прост израз на критерии с antlr3

Искам да създам прост анализатор на изрази на критерии с antlr3

Актуализирано: отделни правила за израз И/ИЛИ за поддържане на различна йерархия И/ИЛИ, но има други проблеми: ако изразът е нещо като: a = 1 и b = 2 и c = 3, дървото трябва да бъде като следното според текущото изпълнение:

       =      =
 (a = 1)(b = 2)(c = 3)
But I want to generate it as follows:
          =       =
    (a = 1)(b = 2)
               (c = 3)
First "and" should be higher priority than another, because I want to parse all the expression as left exp and right exp.

Мисля, че трябва да пренапиша правилото в "подконд", за да направя a = 1 и b = 2 и c = 3 -> (a = 1 и b = 2) и c = 3

но опитах много пъти без успех. Някой има ли идея как да го постигнем? Благодаря.


Моята цел е да анализирам някакъв вид изречение в стил на клауза where в SQL и да създам AST, през което да премина.

Например:

    a = 1 and (b = 2 or c = 3)            //This one can parse correctly.
    a = 1 and ((b = 2 or c = 3) or d = 4) //This one cannot parse correctly, missing last d = 4 in the tree. 
                                          //Tree is not correct.

Текущият ми граматичен файл не може да анализира над сложно условие. Тъй като съм начинаещ за antlr, не съм сигурен как да променя граматиката си, за да постигна по-правилния подход по-горе. Може ли някой да помогне по въпроса? !Всички предложения или коментари са благодарни.

и моята граматика, както следва (Актуализирано според коментарите. Проблемът с предупреждението е разрешен.):

grammar CriteriaExpression;

options {
  output       = AST;
  ASTLabelType = CommonTree;
  language     = Java;
}

tokens {
  AND    = 'and';
  OR     = 'or';
  LPAREN = '(';
  RPAREN = ')';
}

@lexer::header {
package com.antlr;
}

@parser::header {
package com.antlr;
}

eval
:
expression
;

израз : andExp (OR^ andExp)*;

andExp : subcond (AND^ subcond)* ;

subcond: LPAREN израз RPAREN |atom;

atom
  :
  EXPR OPERATOR EXPR
  ;

OPERATOR
  :
  '='| '<>'| '!='| '<='| '!>'| '<'| '>='| '!<'| '>'| 'like'
  ;

EXPR
  :
  ('a'..'z'| 'A'..'Z'| '0'..'9')+
  ;

 WILDCARD
  :
  '%'
  ;

WS
  :
  ('\t'| ' '| '\r'| '\n'| '\u000C')*
   {$channel = HIDDEN;}
  ;

((a=1)) ((a=1))

a = 1 и ((b = 2 или c = 3) или d = 4) a = 1 и ((b  = 2 или c = 3) или d = 4)


person phyerbarte    schedule 20.02.2013    source източник
comment
покажете входящия файл за вашия пример   -  person Aleksei Bulgak    schedule 20.02.2013
comment
Здравей, @Aleksei Bulgak, какъв е средният ти входящ файл? Примерът е само възможна стойност, за която мисля. Истинският входен низ може да бъде много по-сложен и може да бъде смесена комбинация. Благодаря.   -  person phyerbarte    schedule 20.02.2013
comment
вие давате тази връзка в пълно дърво. с дърво   -  person Aleksei Bulgak    schedule 20.02.2013
comment
@Aleksei Bulgak, непълното дърво се генерира от antlrworks 1.4.3 с примера a = 1 и ((b = 2 или c = 3) или d = 4), мисля, че в дървото липсва последната част d= 4 и не съм сигурен как да го поправя.   -  person phyerbarte    schedule 20.02.2013
comment
Вместо да пренаписвате изцяло вече отговорения си въпрос, моля, създайте нов. Или на първоначалния ви въпрос не е отговорено?   -  person Bart Kiers    schedule 22.02.2013
comment
Здравейте @Bart Kiers, първоначалният въпрос вече е отговорен, в момента проблемите са базирани на оригиналния въпрос. Ще създам нов въпрос.   -  person phyerbarte    schedule 22.02.2013


Отговори (2)


Един недостатък във вашата граматика е правилото

expression
  :
  LPAREN* subcond RPAREN* (( AND | OR )^ LPAREN* subcond RPAREN*)
  ;

Тъй като можете да имате произволен брой LPAREN или RPAREN, няма гаранция, че съвпадат. Предлагам да използвате нещо подобно

expression
  : subcond (( AND | OR ) subcond)?
  | subcond
  ;

и за subcond

subcond
  : atom (( AND | OR )^ atom)*
  | LPAREN expression RPAREN
  ;

В идеалния случай трябва също да имате отделни правила за AND и OR изрази, за да имате правилния приоритет във вашето дърво за анализ.

Актуализация: В актуализираната ви граматика отново използвате LPAREN* и RPAREN*, което няма да ви даде правилно балансирани дървета. Трябва да моделирате множество скоби като ((a = 1)) с рекурсия, както описах в моя пример по-горе. Това би дало подобно на дърво

((a = 1))
  ^---^--- ATOM
 ^-----^-- Subcond -> Expression
^-------^- Subcond -> Expression

Така че дървото ще бъде така:

Expression "((a = 1))"
^
Subcond "(a = 1)"
^
Expression "(a = 1)"
^
Subcond "a = 1"
^
ATOM "a = 1"
person tehlexx    schedule 20.02.2013
comment
Здравей, @tehlexx, да, прав си, не можем да гарантираме броя на LPAREN или RPAREN във входния низ. Но мисля, че ключовият момент е, че тази граматика не може да опише приоритета на скобите, нали? Може би греша, актуализирах граматиката си, тя може да генерира пълно дърво със сложния пример: a = 1 и ((b = 2 или c = 3) или d = 4), но не съм сигурен дали приоритетът в това дърво е правилно или не. - person phyerbarte; 20.02.2013
comment
Начинът, по който разбрах въпроса ви, е, че трябва да има *PARENs, които трябва да съвпадат, така че ако има 2 LPARENs, трябва да има точно 2 RPARENs. Горната граматика също трябва да обхваща сценария, при който изобщо няма PARENs, след това ще поеме по директния път expression -> subcond -> ATOM, така че това също трябва да работи. Ключът е да се моделират скобите с рекурсия, а не с PAREN*. - person tehlexx; 20.02.2013
comment
Здравей, @tehlexx, разбрах мнението ти и актуализирах граматиката, мисля, че сега подходът трябва да е правилен. Много благодарен. Генерираното дърво с ((a=1)) изглежда по-дълбоко от описаното от вас, подходът ми отговаря ли на вашето описание сега? Можете ли да помогнете за потвърждение? Благодаря. - person phyerbarte; 20.02.2013
comment
Доколкото мога да преценя, дърветата изглеждат добре! Това, което също трябва да проверите, е дървото за a=1 OR b=2 AND c=3 и a=1 AND b=2 OR c=3. И в двата случая AND възлите трябва да са под OR възлите. Това е важно, тъй като AND обикновено предхожда OR. - person tehlexx; 20.02.2013
comment
Здравейте @tehlexx много благодаря, актуализирах граматиката си според вашето предложение. Сега е поддръжка И предхожда ИЛИ. Но имам нов проблем, тъй като искам да анализирам целия израз на две части ляв exp и десен exp, така че ако изразът е нещо като: a=1 и b=2 и c=3, тогава дървото ще има 3 скока, това ще бъде проблем, когато анализирам дървото, възможно ли е да пренапиша правилото, за да поддържа a=1 и b=2 и c=3 -› (a=1 и b=2) и c=3, още повече ((a=1 и b=2) и c=3) и d=4? Може би не е възможно..благодаря все пак. - person phyerbarte; 22.02.2013
comment
Мисля, че a=1 and b=2 and c=3 е същото като (a=1 and b=2) and c=3 или a=1 and(b=2 and c=3), така че не би трябвало да има значение в какъв ред оценявате дървото за анализ. Все пак не съм сигурен дали разбирам какво имаш предвид правилно, така че повече контекст вероятно ще помогне. Може би е уместно да повдигна нов въпрос. - person tehlexx; 22.02.2013

Може да греша, но мисля, че вашият проблем е свързан с това нещо LPAREN* something RPAREN* можете да напишете идващо по този начин ((нещо) и antlr смятат, че това пише, защото LParent и Rparent не са се свързали един с друг, така че може да използвате нещо подобно

COMPLEX:
    LPARENT (COMPLEX|subcond) RPARENT;

Но ще го повторя, може и да греша

АКТУАЛИЗАЦИЯ

промени това:

subcond
  : 
  //atom (( AND | OR )^ atom)*
  LPAREN* atom RPAREN*
  ;

до това:

subcond
  : 
  LPAREN (subcond|atom) RPAREN
  ;

използвайки това, вече можете да напишете нещо подобно ((a=1))

person Aleksei Bulgak    schedule 20.02.2013
comment
Страхотно!, вашият отговор отвори ума ми. Което може да разреши предупреждението. Но все пак мисля, че приоритетът на дървото за скобите все още не е правилен. - person phyerbarte; 20.02.2013
comment
След актуализиране дървото може да бъде генерирано напълно, но все още не може да опише приоритета на скобите. Това трябва да е друг проблем. - person phyerbarte; 20.02.2013
comment
Благодаря @Aleksei Bulgak, вашата актуализация може да отговаря ((a=1)), но граматиката изглежда не е достатъчно гъвкава. Проверете актуализираната ми граматика, мисля, че е правилна сега. - person phyerbarte; 20.02.2013