[antlr-interest] Tree Evaluation with Logical Operators (AND and OR)

Priolo, Scott spriolo at walkerinfo.com
Fri Jan 23 06:16:10 PST 2009


O.k. For the archive...

Problem Solution to logical operators:

When using relational operators (such as <, >, !=, OR, AND, etc...) you
must work with "Boolean" return values.  For each operation in my tree
walker I returned (as suggested by Jim) a 1 or a 0.  I used this pattern
(provided by Oliver)

>>> expression
>>>   : ^((AND|OR) expression expression)
>>>   | ^(('<'|'>'|'='|'!=') expression expression)
>>>   | ^(('+'|'-'|'*'|'/') expression expression)
>>>   | ID
>>>   | literal
>>>   ;

To make this useful to my goal I broke out each operator so that I could
evaluate the expression and return an appropriate return value (1 or 0)

expr returns [int value]
    :   
  	^(AND a=expr b=expr)  {
                    // a and b are recursive and return a value 1 or 0
    				if(Integer.valueOf($a.value)==1 
    					&& Integer.valueOf($b.value)==1)

    					{
    						$value = 1;
    					} else { 
    						$value = 0;
    					}
			 // The OR operator would be the same pattern,
but with ||
    			      } 
    
    |	  ^(GT a=expr b=expr)   {
    			       $value =
(Integer.valueOf($a.value)>Integer.valueOf($b.value))?1:0;
    			       }
    |   ^(GTEQ a=expr b=expr) {

    				$value =
(Integer.valueOf($a.value)>=Integer.valueOf($b.value))?1:0;
    			      }   
    |   ^(LT a=expr b=expr)   {
    				$value = (Integer.valueOf($a.value) <
Integer.valueOf($b.value))?1:0;
    			      }
    |   ^(LTEQ a=expr b=expr) {
    				$value =
(Integer.valueOf($a.value)<=Integer.valueOf($b.value))?1:0;
    			      }
    |   ^(EQ a=expr b=expr)   {
    				$value =
(Integer.valueOf($a.value)==Integer.valueOf($b.value))?1:0;
    			      }
    |   ^(NEQ a=expr b=expr)  {
    				$value =
(Integer.valueOf($a.value)!=Integer.valueOf($b.value))?1:0;
    			      }
    |   ID 
        {
        try {
        	//pull value out of memory map that was loaded prior to
this processing
        	PgmQuestionsEntry q =
(PgmQuestionsEntry)variableMap.get(($ID.text).toLowerCase());
	        if ( q!=null ) {
	        	int idvalue = (int) q.getResponseNumber();
	        	$value = idvalue;  // <-- THIS IS AN IMPORTANT
PART OF THIS WALKER!
        	} else 
                System.err.println("undefined variable "+$ID.text);
	        } catch (Exception e)
            {
        	    e.printStackTrace();
            }
        }
    |   INT  
    	// when token matches an INT pattern convert it to int.
    	{$value = Integer.valueOf($INT.text); }
    ;

To make the "return value" useful to a calling program you'd have to
pass it up the chain to your entry point.  Your calling application
would enjoy the opportunity of evaluating a 1 or a 0 as true or false.

Thanks Jim and Oliver.  You shortened the learning curve for me and I
hope this will serve to shorten the learning curve for the next guy.

Scott.


>
> 2009/1/22 Priolo, Scott <spriolo at walkerinfo.com>:
>   
>> Sorry about that, I'm trying to setup a walker that will know what to
do
>> with "OR" and "AND" operators.  I have the parser setup so that the
AST is
>> nicely formed with expr such as (< a 3).  I'm able to walk and
evaluate
>> these simple expr too. But! when I walk (or (and (< a 3) (< b 3)) (<
c 3))
>> I'm stumped.
>>     
You need to make your rules within an expression return a type, the 
formulation of which depends on what things you can evaluate. If your 
primitive types are all integer, then each stage of your expression can 
return integer and the AND and OR rules can return 0 and 1. Otherwise, 
you will need to create a class with 'operators' such as plus(), 
minus(), and() etc. It will also contain an integer, perhaps a boolean, 
perhaps a String and so on. Before applying your operations, you will 
need to coerce the types according to some orthogonal rules, as in if 
you have ^(AND INT STRING), what does that mean to you - do you convert 
the string to an integer, or does it mean "is not null" for instance, 
and what do want to do with ^(AND INT STRING) vs ^(AND STRING INT) 
(promotion rules, diamonds and so on).


If it is just Integer though, then:

if: ^(IF e=expr ....) { if ($e.intVal != 0) { ....

expr

returns [int intVal]
:
    : i=INT  { intVal = stringtoint($i.text); ... some conversion func
    : ^(AND e1=expr e2=expr) { if (stringtoint($e1.text) !=0 && 
stringtoint($e2.text) != 0) { intVal = 1; }....
 .... and so on.


Jim

List: http://www.antlr.org/mailman/listinfo/antlr-interest
Unsubscribe:
http://www.antlr.org/mailman/options/antlr-interest/your-email-address


More information about the antlr-interest mailing list