Parse stacked comparison expression into logical Conjunction Tree with antlr3

痞子三分冷 提交于 2019-12-06 12:45:56

问题


I have run into a problem, when i tried to parse a stacked arithmetic comparison expression:

"1<2<3<4<5" 

into a logical Tree of Conjunctions:

CONJUNCTION(COMPARISON(1,2,<) COMPARISON(2,3,<) COMPARISON(3,4,<) COMPARISON(4,5,<))

Is there a way in Antlr3 Tree Rewrite rules to iterate through matched tokens and create the result Tree from them in the target language (I'm using java)? So i could make COMPARISON nodes from element x, x-1 of matched 'addition' tokens. I know i can reference the last result of a rule but that way i'd only get nested COMPARISON rules, that's not what i wish for.

/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:;  

回答1:


I came up with a nasty solution to this problem by writing actual tree building java code:

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
;

For input

"DATA1 < DATA2 > DATA3" 

This outputs tree such as:

If you guys know any better solutions, please tell me about them



来源:https://stackoverflow.com/questions/20938550/parse-stacked-comparison-expression-into-logical-conjunction-tree-with-antlr3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!