parsing - Parse apiló la expresión de comparación en Conjunction Tree lógico con antlr3
(1)
Me encontré con un problema cuando intenté analizar una expresión de comparación aritmética apilada:
"1<2<3<4<5"
en un Árbol de Conjunciones lógico:
CONJUNCTION(COMPARISON(1,2,<) COMPARISON(2,3,<) COMPARISON(3,4,<) COMPARISON(4,5,<))
¿Hay alguna forma en las reglas de reescritura de árboles Antlr3 para iterar a través de tokens coincidentes y crear el árbol de resultados de ellos en el idioma de destino (estoy usando Java)? Así que podría crear nodos COMPARACIÓN de elemento x, x-1 de tokens ''suma'' coincidentes. Sé que puedo hacer referencia al último resultado de una regla, pero de esa manera solo obtendría reglas de COMPARACIÓN compiladas, eso no es lo que deseo.
/This is how i approached the problem, sadly it doesn''t do what i would like to do yet of course.
fragment COMPARISON:;
operator
:
(''<''|''>''|''<=''|''>=''|''==''|''!='')
;
comparison
@init{boolean secondpart = false;}
:
e=addition (operator {secondpart=true;} k=addition)*
-> {secondpart}? ^(COMPARISON ^(VALUES addition*) ^(OPERATORS operator*))
-> $e
;
//Right now what this does is:
tree=(COMPARISON (VALUES (INTEGERVALUE (VALUE 1)) (INTEGERVALUE (VALUE 2)) (INTEGERVALUE (VALUE 3)) (INTEGERVALUE (VALUE 4)) (INTEGERVALUE (VALUE 5))) (OPERATORS < < < <))
//The label for the CONJUNCTION TreeNode that i would like to use:
fragment CONJUNCTION:;
Se me ocurrió una desagradable solución a este problema al escribir código de construcción de árbol real de Java:
grammar testgrammarforcomparison;
options {
language = Java;
output = AST;
}
tokens
{
CONJUNCTION;
COMPARISON;
OPERATOR;
ADDITION;
}
WS
:
(''/t'' | ''/f'' | '' '' | ''/r'' | ''/n'' )+
{$channel = HIDDEN;}
;
comparison
@init
{
List<Object> additions = new ArrayList<Object>();
List<Object> operators = new ArrayList<Object>();
boolean secondpart = false;
}
:
(( e=addition {additions.add(e.getTree());} ) ( op=operator k=addition {additions.add(k.getTree()); operators.add(op.getTree()); secondpart = true;} )*)
{
if(secondpart)
{
root_0 = (Object)adaptor.nil();
Object root_1 = (Object)adaptor.nil();
root_1 = (Object)adaptor.becomeRoot(
(Object)adaptor.create(CONJUNCTION, "CONJUNCTION")
, root_1);
Object lastaddition = additions.get(0);
for(int i=1;i<additions.size();i++)
{
Object root_2 = (Object)adaptor.nil();
root_2 = (Object)adaptor.becomeRoot(
(Object)adaptor.create(COMPARISON, "COMPARISON")
, root_2);
adaptor.addChild(root_2, additions.get(i-1));
adaptor.addChild(root_2, operators.get(i-1));
adaptor.addChild(root_2, additions.get(i));
adaptor.addChild(root_1, root_2);
}
adaptor.addChild(root_0, root_1);
}
else
{
root_0 = (Object)adaptor.nil();
adaptor.addChild(root_0, e.getTree());
}
}
;
/** lowercase letters */
fragment LOWCHAR
: ''a''..''z'';
/** uppercase letters */
fragment HIGHCHAR
: ''A''..''Z'';
/** numbers */
fragment DIGIT
: ''0''..''9'';
fragment LETTER
: LOWCHAR
| HIGHCHAR
;
IDENTIFIER
:
LETTER (LETTER|DIGIT)*
;
addition
:
IDENTIFIER ->^(ADDITION IDENTIFIER)
;
operator
:
(''<''|''>'') ->^(OPERATOR ''<''* ''>''*)
;
parse
:
comparison EOF
;
Para la entrada
"DATA1 < DATA2 > DATA3"
Este árbol de salidas como:
Si conocen alguna solución mejor, por favor hábleme de ellos