work in progress [might break]
This commit is contained in:
parent
315e67ce05
commit
7d95ec66b6
|
@ -0,0 +1 @@
|
|||
noremap <silent> <F5> :!./make && ./make runtest \| most<CR>
|
11
README.md
11
README.md
|
@ -1 +1,10 @@
|
|||
# xrfragment
|
||||
# usage
|
||||
|
||||
|
||||
# development
|
||||
|
||||
```
|
||||
$ ./make install
|
||||
$ ./make
|
||||
$ ./make runtest
|
||||
```
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
-dce no
|
||||
-cp src
|
||||
|
||||
xrfragment.Query
|
||||
-D shallow-expose
|
||||
--resource stub/stub.js@stub
|
||||
-js dist/xrfragment.js
|
||||
|
||||
--next
|
||||
|
||||
-dce no
|
||||
-cp src
|
||||
|
||||
Test
|
||||
-D shallow-expose
|
||||
-m Test
|
||||
-js test/generated/test.js
|
||||
|
||||
--next
|
||||
|
||||
-dce no
|
||||
-cp src
|
||||
|
||||
xrfragment.Query
|
||||
-lua dist/xrfragment.lua
|
||||
|
||||
--next
|
||||
|
||||
-dce no
|
||||
-cp src
|
||||
|
||||
xrfragment.Query
|
||||
-python dist/xrfragment.py
|
||||
|
||||
--next
|
||||
|
||||
-dce no
|
||||
-cp src
|
||||
|
||||
Test
|
||||
-m Test
|
||||
-python test/generated/test.py
|
||||
|
||||
#--next
|
||||
#
|
||||
#-dce no
|
||||
#-cp src
|
||||
#
|
||||
#xrfragment.Query
|
||||
#-php dist/xrfragment.php5
|
||||
#
|
||||
#--next
|
||||
#
|
||||
#-dce no
|
||||
#-cp src
|
||||
#
|
||||
#xrfragment.Query
|
||||
#-cpp dist/xrfragment.cpp
|
||||
#
|
||||
#--next
|
||||
#
|
||||
#-dce no
|
||||
#-cp src
|
||||
#
|
||||
#xrfragment.Query
|
||||
#-cppia dist/xrfragment.cppia
|
||||
#
|
||||
#--next
|
||||
#
|
||||
#-dce no
|
||||
#-cp src
|
||||
#
|
||||
#xrfragment.Query
|
||||
#-cs dist/xrfragment.csharp
|
||||
#
|
||||
#
|
||||
#--next
|
||||
#
|
||||
#-dce no
|
||||
#-cp src
|
||||
#
|
||||
#xrfragment.Query
|
||||
#-java xrfragment.jdk
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
try(){ set +e; "$@" 2>/dev/null; set -e; }
|
||||
|
||||
install(){
|
||||
which haxe || {
|
||||
echo " 1. install haxe from haxe.org"
|
||||
echo "[2.] download neko for cpp output"
|
||||
echo "[3.] install mono openjdk14 for csharp + java output"
|
||||
}
|
||||
haxelib setup
|
||||
haxelib install hxcpp
|
||||
haxelib install hxjava
|
||||
haxelib install hxcs
|
||||
haxelib install hscript
|
||||
}
|
||||
|
||||
runtest(){
|
||||
set -x
|
||||
which python3 && python3 test/generated/test.py | awk '{ print "py: "$0 } END{ print "\n"}'
|
||||
which node && node test/generated/test.js | awk '{ print "js: "$0 } END{ print "\n"}'
|
||||
}
|
||||
|
||||
test -z $1 && { try rm dist/* ; haxe build.hxml; exit $?; }
|
||||
test -z $1 || "$@"
|
|
@ -0,0 +1,118 @@
|
|||
import xrfragment.Query;
|
||||
|
||||
class Test {
|
||||
|
||||
static public function main():Void {
|
||||
trace("starting tests");
|
||||
|
||||
var Query = xrfragment.Query;
|
||||
|
||||
trace( (new Query("foo or bar")).toObject() );
|
||||
trace( (new Query("class:fopoer or bar foo:bar")).toObject().or[0] );
|
||||
trace( (new Query("-skybox class:foo")).toObject().or[0] );
|
||||
trace( (new Query("foo/flop moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("-foo/flop moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:>4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:>=4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:<=4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:!=4 moo or bar")).toObject().or[0] );
|
||||
|
||||
var q:Dynamic = new Query("price:!=4 moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = !q.qualify("slkklskdf");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
|
||||
q = new Query("price:!=3 moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = q.qualify("slkklskdf");
|
||||
if( !ok ) throw 'non-mentioned node should be allowed';
|
||||
|
||||
q = new Query("moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = !q.qualify("slkklskdf");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
obj = q.toObject();
|
||||
var ok = q.qualify("moo");
|
||||
if( !ok ) throw 'moo should be allowed';
|
||||
var ok = q.qualify("bar");
|
||||
if( !ok ) throw 'bar should be allowed';
|
||||
|
||||
q = new Query("price:>3 moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = q.qualify("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = q.qualify("bar");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = q.qualify("moo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
|
||||
q = new Query("price:>3 price:<10 -bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = q.qualify("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = !q.qualify("bar");
|
||||
if( !ok ) throw 'bar should not be allowed';
|
||||
q.test("price", 20);
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'price 20 should not be allowed';
|
||||
|
||||
q = new Query("-bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = q.qualify("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = !q.qualify("bar");
|
||||
if( !ok ) throw 'bar should not be allowed';
|
||||
|
||||
q = new Query("title:*");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
q.test("foo","bar");
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
q.test("title","bar");
|
||||
var ok = q.qualify("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
|
||||
q = new Query("-bar +bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = q.qualify("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = q.qualify("bar");
|
||||
if( !ok ) throw 'bar should be allowed';
|
||||
|
||||
q = new Query("?discount");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test("?discount","-foo");
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?");
|
||||
q.test("?","-foo");
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?");
|
||||
var ok = q.qualify("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?discount");
|
||||
q.test("?discount","-foo");
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?discount +foo");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test("?discount","-foo");
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
var ok = !q.qualify("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
trace("all tests passed");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
package xrfragment;
|
||||
|
||||
@:expose // <- makes the class reachable from plain JavaScript
|
||||
@:keep // <- avoids accidental removal by dead code elimination
|
||||
|
||||
#if js
|
||||
var ok:Bool = js.Syntax.code('
|
||||
// haxe workarounds
|
||||
|
||||
Array.prototype.contains = Array.prototype.includes
|
||||
|
||||
if (typeof Array.prototype.remove !== "function") {
|
||||
Array.prototype.remove = function (item) {
|
||||
const oldLength = this.length
|
||||
let newLength = 0
|
||||
|
||||
for (let i = 0; i < oldLength; i++) {
|
||||
const entry = this[i]
|
||||
if (entry === item) {
|
||||
let newLength = i++
|
||||
|
||||
while (i !== this.length) {
|
||||
const entry = this[i]
|
||||
if (entry !== item) this[newLength++] = entry
|
||||
i++
|
||||
}
|
||||
|
||||
this.length = newLength
|
||||
for (let i = newLength; i < oldLength; i++) delete this[i]
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
');
|
||||
#end
|
||||
|
||||
class Query {
|
||||
|
||||
private var str:String = "";
|
||||
private var q:Dynamic = {};
|
||||
private var include:Array<String> = new Array();
|
||||
private var exclude:Array<String> = new Array();
|
||||
private var accept:Bool = false;
|
||||
private var preset:String = "";
|
||||
|
||||
public function new(str:String){
|
||||
if( str != null ) this.parse(str);
|
||||
}
|
||||
|
||||
public function toObject() : Dynamic {
|
||||
return this.q;
|
||||
}
|
||||
|
||||
public function qualify( nodename:String ): Bool {
|
||||
if( this.q.copy_all ) this.accept = true;
|
||||
if( this.include.contains(nodename) ) this.accept = true;
|
||||
if( this.exclude.contains(nodename) ) this.accept = false;
|
||||
return this.accept;
|
||||
}
|
||||
|
||||
public function parse(str:String,recurse:Bool = false) : Dynamic {
|
||||
|
||||
var copyAll:Bool = recurse ? this.q.copy_all : str.substr(0,1) == "-" || str.substr(0,1) == "?" || str == "";
|
||||
var isOr:EReg = ~/^or$/;
|
||||
var isProp:EReg = ~/.*:[><=!]?/;
|
||||
var isName:EReg = ~/[^:\/]/;
|
||||
var isExclude:EReg = ~/^-/;
|
||||
var isInclude:EReg = ~/^\+/;
|
||||
var isPreset:EReg = ~/^\?/;
|
||||
|
||||
var token = str.split(" ");
|
||||
var ors = new Array();
|
||||
var q:haxe.DynamicAccess<Dynamic> = {};
|
||||
|
||||
function composeQuery() : Dynamic {
|
||||
q = {};
|
||||
q.set("object", new Array() );
|
||||
q.set("-object", new Array() );
|
||||
ors.push(q);
|
||||
return q;
|
||||
}
|
||||
composeQuery();
|
||||
|
||||
function match(str,prefix = ""){
|
||||
if( isPreset.match(str) && !recurse ){
|
||||
this.preset = str;
|
||||
return;
|
||||
}
|
||||
if( isExclude.match(str) || isInclude.match(str) ){
|
||||
var t = str.substr(1);
|
||||
match(t, str.substr(0,1) );
|
||||
return;
|
||||
}
|
||||
if( isProp.match(str) ){
|
||||
var skip = 0;
|
||||
var type = "=";
|
||||
if( str.indexOf("*") != -1 ) type = "*";
|
||||
if( str.indexOf(">") != -1 ) type = ">";
|
||||
if( str.indexOf("<") != -1 ) type = "<";
|
||||
if( str.indexOf("!=") != -1 ) type = "!=";
|
||||
if( str.indexOf(">=") != -1 ) type = ">=";
|
||||
if( str.indexOf("<=") != -1 ) type = "<=";
|
||||
if( type != "=" ) skip += type.length;
|
||||
var property = str.split(":")[0];
|
||||
var value:haxe.DynamicAccess<Dynamic>;
|
||||
if( q.get(prefix+property) ) value = q.get(prefix+property);
|
||||
else value = {};
|
||||
value[ type ] = str.split(":")[1].substr(skip);
|
||||
q.set(prefix+property,value);
|
||||
return;
|
||||
}
|
||||
if( isName.match(str) ){
|
||||
if( prefix == '-' ){
|
||||
q["-object"].push(str);
|
||||
while( q["object"].contains(str) == true) {
|
||||
q["object"].remove(str);
|
||||
}
|
||||
}else{
|
||||
q["object"].push(str);
|
||||
while( q["-object"].contains(str) == true ){
|
||||
q["-object"].remove(str);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for( i in 0...token.length ) {
|
||||
if( isOr.match(token[i]) ){
|
||||
composeQuery();
|
||||
}else match(token[i]);
|
||||
}
|
||||
for ( i in 0...ors.length ) {
|
||||
var or:Dynamic = ors[i];
|
||||
if( Reflect.field(or,'object') != null ) this.include = this.include.concat( Reflect.field(or,'object') );
|
||||
if( Reflect.field(or,'-object') != null ) this.exclude = this.exclude.concat( Reflect.field(or,'-object') );
|
||||
}
|
||||
this.q = { or: ors, copy_all: copyAll };
|
||||
return this.q;
|
||||
}
|
||||
|
||||
public function test( property:String, ?value:Dynamic ):Void{
|
||||
if( this.preset == property ){
|
||||
this.parse( value, true );
|
||||
}
|
||||
for ( i in 0...this.q.or.length ) {
|
||||
var or:Dynamic = this.q.or[i];
|
||||
var conds:Int = 0;
|
||||
var fails:Int = 0;
|
||||
var pass:Int = 0;
|
||||
|
||||
var when = function(expr:Bool) : Bool {
|
||||
conds+=1;
|
||||
fails+= expr ? 0 : 1;
|
||||
return expr;
|
||||
}
|
||||
|
||||
for ( k in Reflect.fields(or) ){
|
||||
var orval:Dynamic = Reflect.field(or,k);
|
||||
if( k != property ) continue;
|
||||
if( Reflect.field(orval,'=') != null && when( value == Reflect.field(orval,'=') ) ) pass += 1;
|
||||
if( Reflect.field(orval,'*') != null && when( value != null ) ) pass += 1;
|
||||
if( Reflect.field(orval,'>') != null && when( value > Std.parseInt(Reflect.field(orval,'>' )) ) ) pass += 1;
|
||||
if( Reflect.field(orval,'<') != null && when( value < Std.parseInt(Reflect.field(orval,'<' )) ) ) pass += 1;
|
||||
if( Reflect.field(orval,'>=') != null && when( value >= Std.parseInt(Reflect.field(orval,'>=')) ) ) pass += 1;
|
||||
if( Reflect.field(orval,'<=') != null && when( value >= Std.parseInt(Reflect.field(orval,'<=')) ) ) pass += 1;
|
||||
if( Reflect.field(orval,'!=') != null && when( value != Std.parseInt(Reflect.field(orval,'!=')) ) ) pass += 1;
|
||||
}
|
||||
if( this.accept && conds > 0 && fails > 0 ) this.accept = false;
|
||||
if( conds > 0 && pass > 0 && fails == 0 ) this.accept = true;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
|||
|
||||
// in the browser use this instead of require():
|
||||
//
|
||||
// <script src="Query.js"></script>
|
||||
// <script>
|
||||
// var q = new hgltf.Query()
|
||||
// </script>
|
||||
|
||||
var hgltf = require('../Query').hgltf
|
||||
var q = new hgltf.Query()
|
||||
|
||||
|
||||
var res = q.parse("")
|
||||
if( !res.copy_all ) throw 'empty string should always set copy_all to true'
|
||||
|
||||
console.log( q.parse("") )
|
||||
console.log( JSON.stringify(q.parse("foo:*"), null, 2) )
|
||||
return
|
||||
console.log( q.parse("-skybox -plane") )
|
||||
console.log( q.parse("foo or bar") );
|
||||
console.log( q.parse("class:fopoer or bar foo:bar").or[0] );
|
||||
console.log( q.parse("-skybox class:foo").or[0] );
|
||||
console.log( q.parse("foo/flop moo or bar").or[0] );
|
||||
console.log( q.parse("-foo/flop moo or bar").or[0] );
|
||||
console.log( q.parse("price:>4 moo or bar").or[0] );
|
||||
console.log( q.parse("price:>=4 moo or bar").or[0] );
|
||||
console.log( q.parse("price:<=4 moo or bar").or[0] );
|
||||
console.log( q.parse("price:!=4 moo or bar").or[0] );
|
|
@ -0,0 +1 @@
|
|||
require "../Query"
|
|
@ -0,0 +1,14 @@
|
|||
from Query import hgltf_Query
|
||||
|
||||
q = hgltf_Query()
|
||||
|
||||
print( q.parse("foo or bar") )
|
||||
print( q.parse("foo or bar") )
|
||||
print( q.parse("class:fopoer or bar foo:bar") )
|
||||
print( q.parse("-skybox class:foo") )
|
||||
print( q.parse("foo/flop moo or bar") )
|
||||
print( q.parse("-foo/flop moo or bar") )
|
||||
print( q.parse("price:>4 moo or bar") )
|
||||
print( q.parse("price:>=4 moo or bar") )
|
||||
print( q.parse("price:<=4 moo or bar") )
|
||||
print( q.parse("price:!=4 moo or bar") )
|
Loading…
Reference in New Issue