anchor.diff:  		( LPAREN! terms RPAREN!
   			{ ## = #(#[APPL,"APPL"], ##) }	
   		)?
  +	| DOT! ( UCID | LCID ) ( LPAREN! terms RPAREN! )?
  +		{ ## = #(#[TRNSF,"TRNSF"], ##) }	
   	;
   
   terms
  
positive.code: 	: '{'! NESTED_ACTION '}'! ( '?'! { $setType(SEMPRED) } )?
  	;
  
  protected
  NESTED_ACTION
      :
  
negative.code: 	    }
  	| #( INTO build=term )
  		{
              pattern, args = build
              self.writeln("retval = self.factory.make(%r, *args, **kargs)" % pattern)
          }
  	| action
  	;
  
  
  term returns [ret]
  	: i:INT { ret = #i.getText(), [] }
  	| r:REAL { ret = #r.getText(), [] }
  	| s:STR { ret = #s.getText(), [] }
  	| v:LCID { ret = #v.getText(), [] }
  	| w:WILDCARD { ret = "_", ["_"] }
  	| #( LIST t=terms )
  		{ ret = "[%s]" % (t[0]), t[1] }
  	| #( APPL c=cons a=terms )
  		{ ret = "%s(%s)" % (c[0], a[0]), c[1] + a[1] }
  	| #( TRNSF s=id a=terms )
  		{ ret = "_", [s] }
  	;
  
  cons returns [ret]
  	: s:STR { ret = #s.getText(), [] }
  	| c:UCID { ret = #c.getText(), [] }
  	| v:LCID { ret = #v.getText(), [] }
  	| w:WILDCARD { ret = "_", ["_"] }
  	;
  
  terms returns [ret]
  		{ ret = [], [] }
  	: ( t=term { ret[0].append(t[0]); ret[1].extend(t[1]) } )*
  		{ ret = ','.join(ret[0]), ret[1] }
  	;