2013-02-20 2 views
2

Я хочу создать простое выражение критериев парсера с antlr3простых критерии анализатор выражений с antlr3

Обновлено: отдельное И ИЛИ выражение правила поддержки и/или другая иерархия, но есть и другие проблемы: , если выражение это что-то вроде: а = 1 и Ь = 2 и с = 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. 

Я думаю, что нужно переписать правила в «subcond» Сделать a = 1 и b = 2 и c = 3 -> (a = 1 и b = 2) и c = 3

но попробовал много раз, не повезло. Кто-нибудь понял, как его достичь? Благодарю.

Моя цель - разобрать какой-то SQL-предложение предложения предложения where и построить 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 (ИЛИ^andExp) * ;

andExp : субкондуктор (AND^подкодер) * ;

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;} 
    ; 

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

а = 1 и ((Ь = 2 или с = 3) или г = 4) a = 1 and ((b = 2 or c = 3) or d = 4)

+0

показать входящий файл для примера –

+0

Привет, @Aleksei Булгак, каков ваш средний входящий файл?Пример - это просто возможное значение, о котором я думаю. Реальная входная строка может быть намного сложнее и может быть комбинацией комбинаций. Благодарю. – phyerbarte

+0

вы передаете эту ссылку в полном дереве. с деревом –

ответ

2

Один недостаток в вашей грамматике есть правило

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

Поскольку вы можете иметь любое количество LPAREN или RPAREN, нет никакой гарантии, что они совпадают. Я предлагаю использовать somehting как

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" 
+0

Привет, @tehlexx, да, вы правы, мы не можем гарантировать количество LPAREN или RPAREN во входной строке. Но я думаю, что ключевым моментом является то, что эта грамматика не может описать приоритет скобок, не так ли? Возможно, я ошибаюсь, я обновил свою грамматику, он может сгенерировать полное дерево сложным примером: a = 1 и ((b = 2 или c = 3) или d = 4), но я не уверен, что приоритет в этом дереве правильно или нет. – phyerbarte

+0

То, как я понял ваш вопрос, заключается в том, что должен быть установлен '* PAREN', поэтому, если есть 2' LPAREN', должно быть ровно 2 'RPAREN'. Вышеприведенная грамматика должна также охватывать сценарий, в котором нет «PAREN's», тогда он будет принимать прямое выражение «выражение -> подкод -> ATOM», поэтому это также должно работать. Ключ состоит в том, чтобы моделировать круглые скобки с рекурсией, а не с 'PAREN *'. – tehlexx

+0

Привет, @tehlexx, я получил вашу точку зрения и обновленную грамматику, я думаю, что теперь подход должен быть правильным. Очень благодарен. Сгенерированное дерево с ((a = 1)) кажется глубже, чем описано, мой подход соответствует вашему описанию сейчас? Можете ли вы помочь подтвердить? Благодарю. – phyerbarte

2

Может быть я неправильно, но я думаю, что проблема связана с этой вещью LPAREN* something RPAREN* вы можете написать что-то вроде этого ((что-то) и antlr подумайте, что эта запись, потому что LParent и Rparent не связаны друг с другом, могут использовать что-то вроде этого

COMPLEX: 
    LPARENT (COMPLEX|subcond) RPARENT; 

Но я скажу это снова, может быть, я ошибаюсь

UPDATE

изменить это:

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

к этому:

subcond 
    : 
    LPAREN (subcond|atom) RPAREN 
    ; 

с помощью этого теперь вы можете написать что-то вроде этого ((a=1))

+0

Отлично !, ваш ответ откроет мой разум. Что может разрешить предупреждение. Но все же я считаю, что приоритет дерева для круглых скобок все еще не правильный. – phyerbarte

+0

да в моем примере я не добавил AND ИЛИ –

+0

После обновления дерево может быть сгенерировано полностью, но по-прежнему не может описывать приоритет скобок. Это должна быть другая проблема. – phyerbarte

Смежные вопросы