Pregunta

Estoy tratando de escribir una gramática para nuestro motor de reglas personalizado que usa ANTLR (para analizar) y Pentaho Kettle (para ejecutar las reglas)

Las entradas válidas para el analizador serían del tipo:
(<Attribute_name> <Relational_Operator> <Value>) AND/OR (<Attribute_name> <Relational_Operator> <Value>)
es decir, persona_phone = 123456789

Aquí está mi gramática:

grammar RuleGrammar;
options{
language=Java;
}

prog                : condition;

condition
                                :  LHSOPERAND RELATIONOPERATOR RHSOPERAND
                                ;

LHSOPERAND
                                :  STRINGVALUE
                                ;

RHSOPERAND
                                :  NUMBERVALUE    |
                                   STRINGVALUE
                                ;


RELATIONOPERATOR
                                :   '>'    |
                                     '=>'  |
                                     '<'   |
                                     '<='  |
                                     '='   |
                                     '<>'
                                ;

fragment NUMBERVALUE
                              : '0'..'9'+
                              ;

fragment STRINGVALUE
                              :  ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_')*
                              ;


fragment LOGICALOPERATOR
                              :  'AND' |
                                 'OR'  |
                                 'NOT'
                              ;

El problema que me enfrento es comparar contra el valor de la cadena, es decir, persona_name = 1 pasaría la gramática, pero el valor PERSON_NAME=BATMAN No funciona. Estoy usando Antlrworks y en la depuración para PERSON_NAME=BATMAN, Yo tengo un MismatchTokenException para el valor RHS.

¿Alguien puede guiarme a donde me estoy equivocando?

¿Fue útil?

Solución

BATMAN está siendo tokenizado como un LHSOPERAND simbólico. Debe darse cuenta de que el Lexer no tiene en cuenta lo que el analizador "necesita" en un momento particular. El Lexer simplemente intenta coincidir tanto como sea posible, y en el caso 2 (o más) las reglas coinciden con la misma cantidad de caracteres (LHSOPERAND y RHSOPERAND En su caso), la regla definida primero "ganará", que es la LHSOPERAND regla.

EDITAR

Míralo así: primero el Lexer recibe la corriente de caracteres que convierte en una corriente de tokens. Después de que se hayan creado todas las fichas, el analizador recibe estos tokens de los que intenta dar sentido. Los tokens son no creado durante el análisis (en reglas de analizador), pero antes.

Una demostración rápida de cómo tu pudo hazlo:

grammar RuleGrammar;

prog
 : condition EOF
 ;

condition
 : logical
 ;

logical
 : relational ((AND | OR) relational)*
 ;

relational
 : STRINGVALUE ((GT | GTEQ | LT | LTEQ | EQ | NEQ) term)?
 ;

term
 : STRINGVALUE
 | NUMBERVALUE
 | '(' condition ')'
 ;

GT          : '>';
GTEQ        : '>=';
LT          : '<';
LTEQ        : '<=';
EQ          : '=';
NEQ         : '<>';
NUMBERVALUE : '0'..'9'+;
AND         : 'AND';
OR          : 'OR';
STRINGVALUE : ('a'..'z' | 'A'..'Z' | '_')+;
SPACE       : ' ' {skip();};

(tenga en cuenta que EQ y NEQ no son realmente operadores relacionales ...)

APADA DE PANSING como:

PERSON_NAME = BATMAN OR age <> 42

ahora daría como resultado el siguiente análisis:

enter image description here

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top