All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.monoid.web.jp.javacc.json.jjt Maven / Gradle / Ivy

There is a newer version: 0.3.2
Show newest version
options
{
  STATIC = false;
  DEBUG_PARSER = false;
  ERROR_REPORTING = true;
  NODE_USES_PARSER = false;
  NODE_FACTORY = "JSONPathCompiler";
  NODE_CLASS = "JSONPathExpr";
}

PARSER_BEGIN(JSONPathCompiler)
package us.monoid.web.jp.javacc;

import us.monoid.json.*;
import java.util.*;

public class JSONPathCompiler {
  
  public static class JSONPathExpr extends AbstractJSONExpr {
    JSONPathExpr(int i) {
      super (i);
    }
    public void dump(String prefix) {
      System.out.println(prefix + toString());
      if (children != null && children.length > 0) {
        System.out.println(prefix + " [");
        for (int i = 0; children != null && i < children.length; ++i) {
          System.out.print(prefix + " (" + (i + 1) + ")");
          SimpleNode c = (SimpleNode) children [i];
          if (c == null) {
            System.out.println("null");
          } else {
            c.dump(prefix + " ");
          }
        }
        System.out.println(prefix + " ]");
      }
    }

    public Object eval(Object o) throws JSONException {
      if (o == null) return null;
      switch (this.id) {
        case JJTIMAGE:
        {
			return this.value;
        }
        case JJTEXPRESSION: {
          if (getChildrenCount() == 0) return null;
          for (int i = 0; o != null && i < getChildrenCount(); ++i) {
            o = at(i).eval(o);
          }
          return o;
        }
        case JJTARRAY: {
          if (this.value instanceof Integer) {
          int index = Integer.class.cast(this.value);
          if (o instanceof JSONArray) {
            JSONArray array = JSONArray.class.cast(o);
            return array.get(index);
     	   } else {
    	    return null;
    	   }
    	 } else { // AST contains a selector expression. evaluate it against all objects in array
 			if (o instanceof JSONArray) {
            	JSONArray array = JSONArray.class.cast(o);
            	// match first strategy. only one item is returned
            	Object result = null;
            	match:
            	for (int i = 0, len = array.length(); i < len; i++) {
            	  Object item = array.get(i);
            	  boolean test = at(0).test(item);
           		  if (test) {
           		    result = item; // evaluation can continue on this item
           		  	break;
           		 }
            	}
            	return result;
        	}  	
    	 }
        }
        case JJTOBJECT: {
          if (o instanceof JSONObject) {
            JSONObject json = JSONObject.class.cast(o);
            return json.get(this.value.toString());
          } else if (o instanceof JSONArray)
          {
            JSONArray array = JSONArray.class.cast(o);
           // return all items
           List matches = new ArrayList();
            Object result = null;
            for (int i = 0, len = array.length(); i < len; i++) {
              Object item = array.get(i);
              if (item instanceof JSONObject)
              {
			     JSONObject obj = (JSONObject)item;
			     if (obj.has(this.value.toString()))
			     {
			       matches.add(obj.get(this.value.toString()));
			     }
              }
           }
           return matches;
          }
          return null;
        }
        
        default : System.err.println("Doesn't handle " + this.id);
        break;
      }
      return null;
    }
  }

  static SimpleNode jjtCreate(int id)
  {
    return new JSONPathExpr(id);
  }

  public static void main(String args []) throws Exception
  {
    try
    {
      java.io.StringReader r = new java.io.StringReader(args [0]);
      JSONPathCompiler app = new JSONPathCompiler(r);
      JSONPathExpr x = JSONPathExpr.class.cast(app.expr());
      x.dump(" ");
      JSONObject json = new JSONObject("{ \"a\": [" +
      "{\"Hello\": \"World\"},{\"Hello\": \"JB\"}]" +
      ", \"b\": null, \"c\": { \"d\": 1234 }}");
      Object o = x.eval(json);
      System.err.println("Compiling " + args [0] + "");
      System.err.println("Eval " + json + "");
      System.err.println("Result is:" + o + "");
    } catch (Exception err) {
      err.printStackTrace();
    }
  }
}

PARSER_END(JSONPathCompiler)

SKIP :
{
  " "
| "\t"
| "\n"
| "\r"
}

TOKEN :
{
  < OPEN_ARRAY : "[" >
| < CLOSE_ARRAY : "]" >
|   < #LETTER : [ "$", "_", "a"-"z", "A"-"Z" ] >
| < CNAME : "'" (~["'"])* "'" >
| < #DIGIT : [ "0"-"9" ] >
| < #DIGIT19 : [ "1"-"9" ] >
| < OTHER : "-" >
| < DOT : "." >
| < OR : "||" >
| < AND : "&&" >
| < NOT : "!" >
| < OP : [ ">", "<", "="] > 
| < INTEGER : ([ "-" ])? (< DIGIT > | < DIGIT19 > (< DIGIT >)* ) >
| < NUMBER : < INTEGER > < FRAC >  | < INTEGER >  | < INTEGER > < FRAC > >
| < FRAC: < DOT > (< DIGIT >)+ >
| < EXP: < EXPONENT > (< DIGIT >)+ >
| < EXPONENT: ["E", "e"] ([ "+", "-" ])? >
| < IDENTIFIER :
    < LETTER >
    (
      < LETTER >
    | < DIGIT >
    | < OTHER >
    )* >

}

JSONPathExpr json() #EXPRESSION :
{
}
{
  expr() < EOF >
   {
    return jjtThis;
  }
}

JSONPathExpr expr() #EXPRESSION :
{}
{
  (
    array()
  | object()
  )
  (
    array()
  | < DOT > object()
  )*
  
  {
    return jjtThis;
  }
}

void array() #ARRAY :
{
  Token i;
}
{
    < OPEN_ARRAY > (i = < INTEGER > 
  {
    jjtThis.value = new Integer(i.image);
  }
  | selector()
  {
    
  }
  ) < CLOSE_ARRAY > 
}


void selector() :
{
}
{
	term() ( < OR > term() )*

}

void term() :
{
}
{
  neg() ( < AND > neg() )*
   
}

void neg() :
{
  Token n = null;
}
{
	[ n = < NOT > ] part()
	{
	  if (n != null) {
	    jjtThis.value = Boolean.FALSE;
	  }	    
	}
}

void part() :
{
}
{
	predicate() | "(" selector() ")"

}

void predicate():
{
  JSONPathExpr leftExpr;
  JSONPathExpr rightExpr = null;
  Token test = null;
}
{
	leftExpr = primaryExpr() ( test = < OP > rightExpr = primaryExpr())?
	{
	  	jjtThis.value = new Predicates.Operator(leftExpr, test.image, rightExpr);
	}	
}

JSONPathExpr primaryExpr() #EXPRESSION:
{
}
{
    (
      expr() |
    literalOrNumber()
  )
    {
    return jjtThis;
  }
}

JSONPathExpr literalOrNumber() #IMAGE:
{
  Token string = null, number = null;
}
{
  (
    string = < CNAME > |
	number = <  NUMBER > |
	number = < INTEGER >
)
 
  {
    if (number != null)
    {
      jjtThis.value = new Double(number.image);
    } else if (string != null)
    {
      jjtThis.value = string.image.substring(1,string.image.length() - 1);
    }
    return jjtThis;
  }
}

void object() #OBJECT :
{
  Token name;
}
{
  (name = < IDENTIFIER >)
  {
    jjtThis.value = name.image;
  }
}