diff --git a/dist/xrfragment.js b/dist/xrfragment.js
index 79c1bd7..ff11a21 100644
--- a/dist/xrfragment.js
+++ b/dist/xrfragment.js
@@ -212,6 +212,7 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
Frag_h["prio"] = xrfragment_Type.isInt;
Frag_h["pos"] = xrfragment_Type.isVector;
Frag_h["q"] = xrfragment_Type.isString;
+ var vec = "1,2,3";
if(Object.prototype.hasOwnProperty.call(Frag_h,key)) {
if(Frag_h[key].match(value)) {
var v = new xrfragment_Value();
@@ -230,11 +231,11 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
}
resultMap[key] = v;
} else {
- console.log("src/xrfragment/Parser.hx:34:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")");
+ console.log("src/xrfragment/Parser.hx:47:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")");
return false;
}
} else {
- console.log("src/xrfragment/Parser.hx:35:","[ i ] fragment '" + key + "' does not exist or has no type defined (yet)");
+ console.log("src/xrfragment/Parser.hx:48:","[ i ] fragment '" + key + "' does not exist or has no type defined (yet)");
return false;
}
return true;
diff --git a/doc/RFC.md b/doc/RFC.md
index 6223e00..4267ac5 100644
--- a/doc/RFC.md
+++ b/doc/RFC.md
@@ -1,51 +1,56 @@
+
> version 1.0.0
-
-date: 2023-03-31T19:59:16+0200 (generated by `./make doc`)
-
+date: 2023-04-02T21:18:46+0200
[](https://github.com/coderofsalvation/xrfragment/actions)
-
-
# `://foo.com/my3d.asset#pos=1,0,0&prio=-5`
# URI parser
-
> icanhazcode? yes, see [URI.hx](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/URI.hx)
1. fragment URI starts with `#`
1. fragments are split by `&`
-1. `=` is used to split fragment key/values
+1. store key/values into a associative array or dynamic object
+1. loop thru each fragment
+1. for each fragment split on `=` to separate key/values
1. fragment-values are urlencoded (space becomes `+` using `encodeUriComponent` e.g.)
1. every recognized fragment key/value-pair is added to a central map/associative array/object
# XR Fragments (key/value params)
-
+
> ⛁ = define in 3D asset-file (as custom property or default projection)
> ☇ = mutable, using navigator URI (`document.location.href` e.g.)
| param | type | scope(s) | category | notes |
|---------|---------------|-------|--------------------|---------------------------------|
-| prio | int (-10..1) | ⛁ | Asset loading / linking | \#static allow client to ignore lower-prio objects in the renderloop, to compensate frame-drop/cpu/gpu-overload scenario’soc/notes/prio.md |
+| prio | int (-10..1) | ⛁ | Asset loading / linking | \#static allow client to ignore lower-prio objects in the renderloop, to compensate frame-drop/cpu/gpu-overload scenario’s |
| pos | 3D vector | ⛁ ☇ |HREF navigation/portals | |
| q | string | ⛁ |Query Selector | |
# XR Fragments parser
+
note: community parsers will prolly outperform this initial parser :)
> icanhazcode? yes, see [Parser.hx](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Parser.hx)
-
the gist of it:
+
+1. check if param exist
1. each key has a regex to validate its value-type (see regexes)
-1. `|` is used to split multiple/fallback values
+1. extract the type
+1. use `|` on stringvalues, to split multiple/fallback values
+1. for each multiple/fallback value, guess the type
1. `,` assumes 1D/2D/3D vector-values like x[,y[,z]]
1. parseFloat(..) and parseInt(..) is applied to vector/float and int values
1. anything else will be treated as string-value
1. incompatible value-types will be dropped / not used
+
> the xrfragment specification should stay simple enough
+
> for anyone to write a parser using either regexes or grammar/lexers
+
> therefore expressions/comprehensions are not supported (max wildcard/comparison operators for queries e.g.)
# Parser Value types
@@ -59,7 +64,9 @@ the gist of it:
|float | | [-]x[.xxxx] (ieee)| #prio=-20 |
|array | mixed| \|-separated | #pos=0,0,0\|90,0,0 |
+
> rule for thumb: type-limitations will piggyback JSON limitations (IEEE floatsize e.g.)
+Regexes:
1. hex colors are detected using regex `/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/`
1. integers are detected using regex `/^[0-9]+$/`
@@ -67,6 +74,3 @@ the gist of it:
1. vectors are detected using regex `/[,]/` (but can also be an string referring to an entity-ID in the asset)
1. anything else is string `/.*/`
-# Tests
-
-the spec is tested with [JSON unittests](./../src/spec) consumed by [Test.hx](./../src/Test.hx) to cross-test all languages.
diff --git a/doc/generate.awk b/doc/generate.awk
new file mode 100644
index 0000000..cdf936a
--- /dev/null
+++ b/doc/generate.awk
@@ -0,0 +1,30 @@
+# a no-nonsense source-to-markdown generator which scans for:
+#
+# /**
+# * # foo
+# *
+# * this is markdown $(cat bar.md)
+# */
+#
+# var foo; // comment with 2 leading spaces is markdown too $(date)
+#
+/\$\(/ { cmd=$0;
+ gsub(/^.*\$\(/,"",cmd);
+ gsub(/\).*/,"",cmd);
+ cmd | getline stdout; close(cmd);
+ sub(/\$\(.*\)/,stdout);
+ }
+/\/\*\*/ { doc=1; sub(/^.*\/\*/,""); }
+doc && /\*\// { doc=0;
+ sub(/[[:space:]]*\*\/.*/,"");
+ sub(/^[[:space:]]*\*[[:space:]]?/,"");
+ print
+ }
+doc && /^[[:space:]]*\*/ { sub(/^[[:space:]]*\*[[:space:]]?/,"");
+ print
+ }
+!doc && /\/\/ / { sub(".*// ","");
+ sub("# ","\n# ");
+ sub("> ","\n> ");
+ print
+ }
diff --git a/make b/make
index 7687ffe..a799c86 100755
--- a/make
+++ b/make
@@ -1,6 +1,5 @@
#!/bin/sh
set -e
-VERSION=1.0.0
try(){ set +e; "$@" 2>/dev/null; set -e; }
@@ -32,33 +31,8 @@ tests(){
}
doc(){
- {
- echo ''
- echo ''
- echo "> version $VERSION"
- echo "\ndate: $(date +"%Y-%m-%dT%H:%M:%S%z") (generated by \`./make doc\`)\n"
- echo "[](https://github.com/coderofsalvation/xrfragment/actions)\n"
- {
- cat src/xrfragment/URI.hx
- cat src/xrfragment/Parser.hx
- } | awk '
-
- /\/\/ / {
- gsub(".*// ","",$0);
- gsub("# ","\n# ",$0);
- if( match($0,/^#code /) ){ print "```\n"; system("cat "$2); print "```\n"; next; }
- if( match($0,/^#sh /) ){ $1=""; system($0); next; }
- if( match($0,/#include /) ) {
- o=$0; gsub(/.*#include/,"#include",$0); f=$2; $0=o;
- cmd="cat "f
- cmd | getline text; close(cmd)
- gsub(/#include \w/, text)
- }
- print $0;
- }
-
- '
- } > doc/RFC.md
+ awk -f doc/generate.awk src/xrfragment/URI.hx \
+ src/xrfragment/Parser.hx > doc/RFC.md
}
test -z $1 && { try rm dist/* ; haxe build.hxml; sed -i 's|.*nonlocal .*||g' dist/xrfragment.py; exit $?; }
diff --git a/src/xrfragment/Parser.hx b/src/xrfragment/Parser.hx
index cc5484a..19ad59b 100644
--- a/src/xrfragment/Parser.hx
+++ b/src/xrfragment/Parser.hx
@@ -1,32 +1,45 @@
package xrfragment;
+/**
+ * # XR Fragments (key/value params)
+ *
+ * > ⛁ = define in 3D asset-file (as custom property or default projection)
+ * > ☇ = mutable, using navigator URI (`document.location.href` e.g.)
+ */
+
@:expose // <- makes the class reachable from plain JavaScript
@:keep // <- avoids accidental removal by dead code elimination
-class Parser { // # XR Fragments (key/value params)
- public static var error:String = ""; //
- // > ⛁ = define in 3D asset-file (as custom property or default projection)
- // > ☇ = mutable, using navigator URI (`document.location.href` e.g.)
- @:keep //
+class Parser {
+ public static var error:String = "";
+
+ @:keep
public static function parse(key:String,value:String,resultMap:haxe.DynamicAccess):Bool {
var Frag:Map = new Map(); // | param | type | scope(s) | category | notes |
// |---------|---------------|-------|--------------------|---------------------------------|
- Frag.set("prio", Type.isInt); // | prio | int (-10..1) | ⛁ | Asset loading / linking | #include doc/notes/prio.md |
+ Frag.set("prio", Type.isInt); // | prio | int (-10..1) | ⛁ | Asset loading / linking | $(cat doc/notes/prio.md) |
Frag.set("pos", Type.isVector); // | pos | 3D vector | ⛁ ☇ |HREF navigation/portals | |
Frag.set("q", Type.isString); // | q | string | ⛁ |Query Selector | |
- //
- // # XR Fragments parser
- if( Frag.exists(key) ){ // note: community parsers will prolly outperform this initial parser :)
- if( Frag.get(key).match(value) ){ // > icanhazcode? yes, see [Parser.hx](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Parser.hx)
- var v:Value = new Value(); //
- guessType(v, value); // the gist of it:
- // process multiple/fallback values // 1. each key has a regex to validate its value-type (see regexes)
- if( value.split("|").length > 1 ){ // 1. `|` is used to split multiple/fallback values
+ var vec:String = "1,2,3"; //
+ //if( Type.isVector(vec) ) trace("ja");
+ /**
+ * # XR Fragments parser
+ *
+ * note: community parsers will prolly outperform this initial parser :)
+ * > icanhazcode? yes, see [Parser.hx](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Parser.hx)
+ * the gist of it:
+ */
+ if( Frag.exists(key) ){ // 1. check if param exist
+ if( Frag.get(key).match(value) ){ // 1. each key has a regex to validate its value-type (see regexes)
+ var v:Value = new Value();
+ guessType(v, value); // 1. extract the type
+ // process multiple/fallback values
+ if( value.split("|").length > 1 ){ // 1. use `|` on stringvalues, to split multiple/fallback values
v.args = new Array();
var args:Array = value.split("|");
for( i in 0...args.length){
var x:Value = new Value();
- guessType(x, args[i]);
+ guessType(x, args[i]); // 1. for each multiple/fallback value, guess the type
v.args.push( x );
}
}
@@ -40,14 +53,14 @@ class Parser { // #
@:keep
public static function guessType(v:Value, str:String):Void {
v.string = str;
- if( str.split(",").length > 1){ // 1. `,` assumes 1D/2D/3D vector-values like x[,y[,z]]
- var xyz:Array = str.split(","); // 1. parseFloat(..) and parseInt(..) is applied to vector/float and int values
- if( xyz.length > 0 ) v.x = Std.parseFloat(xyz[0]); // 1. anything else will be treated as string-value
- if( xyz.length > 1 ) v.y = Std.parseFloat(xyz[1]); // 1. incompatible value-types will be dropped / not used
- if( xyz.length > 2 ) v.y = Std.parseFloat(xyz[2]); //
- } // > the xrfragment specification should stay simple enough
- // > for anyone to write a parser using either regexes or grammar/lexers
- if( Type.isColor.match(str) ) v.color = str; // > therefore expressions/comprehensions are not supported (max wildcard/comparison operators for queries e.g.)
+ if( str.split(",").length > 1){ /// 1. `,` assumes 1D/2D/3D vector-values like x[,y[,z]]
+ var xyz:Array = str.split(","); /// 1. parseFloat(..) and parseInt(..) is applied to vector/float and int values
+ if( xyz.length > 0 ) v.x = Std.parseFloat(xyz[0]); /// 1. anything else will be treated as string-value
+ if( xyz.length > 1 ) v.y = Std.parseFloat(xyz[1]); /// 1. incompatible value-types will be dropped / not used
+ if( xyz.length > 2 ) v.y = Std.parseFloat(xyz[2]); ///
+ } /// > the xrfragment specification should stay simple enough
+ /// > for anyone to write a parser using either regexes or grammar/lexers
+ if( Type.isColor.match(str) ) v.color = str; /// > therefore expressions/comprehensions are not supported (max wildcard/comparison operators for queries e.g.)
if( Type.isFloat.match(str) ) v.float = Std.parseFloat(str);
if( Type.isInt.match(str) ) v.int = Std.parseInt(str);
}
@@ -58,8 +71,8 @@ class Parser { // #
// | type | info | format | example |
class Value { // |------|------|--------|----------------------------------|
public var x:Float; // |vector| x,y,z| comma-separated | #pos=1,2,3 |
- public var y:Float; //
- public var z:Float; //
+ public var y:Float;
+ public var z:Float;
public var color:String; // |string| color| FFFFFF (hex) | #fog=5m,FFAACC |
public var string:String; // |string| | | #q=-sun |
public var int:Int; // |int | | [-]x[xxxxx] | #price:>=100 |
@@ -68,7 +81,7 @@ class Value { // |
public function new(){} //
// > rule for thumb: type-limitations will piggyback JSON limitations (IEEE floatsize e.g.)
}
- // Regexes:
+ // Regexes:
class Type { //
static public var isColor:EReg = ~/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; // 1. hex colors are detected using regex `/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/`
static public var isInt:EReg = ~/^[0-9]+$/; // 1. integers are detected using regex `/^[0-9]+$/`
@@ -77,6 +90,6 @@ class Type { //
static public var isString:EReg = ~/.*/; // 1. anything else is string `/.*/`
}
-// # Tests
-//
-// the spec is tested with [JSON unittests](./../src/spec) consumed by [Test.hx](./../src/Test.hx) to cross-test all languages.
+/// # Tests
+///
+/// the spec is tested with [JSON unittests](./../src/spec) consumed by [Test.hx](./../src/Test.hx) to cross-test all languages.
diff --git a/src/xrfragment/URI.hx b/src/xrfragment/URI.hx
index 150fbcf..3a441c8 100644
--- a/src/xrfragment/URI.hx
+++ b/src/xrfragment/URI.hx
@@ -2,19 +2,30 @@ package xrfragment;
import xrfragment.Parser;
+/**
+ *
+ *
+ * > version 1.0.0
+ * date: $(date +"%Y-%m-%dT%H:%M:%S%z") (generated by \`./make doc\`)
+ * [](https://github.com/coderofsalvation/xrfragment/actions)
+ *
+ * # `://foo.com/my3d.asset#pos=1,0,0&prio=-5`
+ *
+ * # URI parser
+ * > icanhazcode? yes, see [URI.hx](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/URI.hx)
+ */
+
@:expose // <- makes the class reachable from plain JavaScript
@:keep // <- avoids accidental removal by dead code elimination
- //
- // # `://foo.com/my3d.asset#pos=1,0,0&prio=-5`
class URI {
- @:keep // # URI parser
- public static function parse(qs:String):haxe.DynamicAccess { //
- var fragment:Array = qs.split("#"); // > icanhazcode? yes, see [URI.hx](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/URI.hx)
- var splitArray:Array = fragment[1].split('&'); //
- var resultMap:haxe.DynamicAccess = {}; // 1. fragment URI starts with `#`
- for (i in 0...splitArray.length) { // 1. fragments are split by `&`
+ @:keep
+ public static function parse(qs:String):haxe.DynamicAccess {
+ var fragment:Array = qs.split("#"); // 1. fragment URI starts with `#`
+ var splitArray:Array = fragment[1].split('&'); // 1. fragments are split by `&`
+ var resultMap:haxe.DynamicAccess = {}; // 1. store key/values into a associative array or dynamic object
+ for (i in 0...splitArray.length) { // 1. loop thru each fragment
- var splitByEqual = splitArray[i].split('='); // 1. `=` is used to split fragment key/values
+ var splitByEqual = splitArray[i].split('='); // 1. for each fragment split on `=` to separate key/values
var regexPlus = ~/\+/g; // 1. fragment-values are urlencoded (space becomes `+` using `encodeUriComponent` e.g.)
var key:String = splitByEqual[0];
diff --git a/test/generated/test.js b/test/generated/test.js
index 9b5574a..b0ec805 100644
--- a/test/generated/test.js
+++ b/test/generated/test.js
@@ -285,6 +285,7 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
Frag_h["prio"] = xrfragment_Type.isInt;
Frag_h["pos"] = xrfragment_Type.isVector;
Frag_h["q"] = xrfragment_Type.isString;
+ var vec = "1,2,3";
if(Object.prototype.hasOwnProperty.call(Frag_h,key)) {
if(Frag_h[key].match(value)) {
var v = new xrfragment_Value();
@@ -303,11 +304,11 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
}
resultMap[key] = v;
} else {
- console.log("src/xrfragment/Parser.hx:34:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")");
+ console.log("src/xrfragment/Parser.hx:47:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")");
return false;
}
} else {
- console.log("src/xrfragment/Parser.hx:35:","[ i ] fragment '" + key + "' does not exist or has no type defined (yet)");
+ console.log("src/xrfragment/Parser.hx:48:","[ i ] fragment '" + key + "' does not exist or has no type defined (yet)");
return false;
}
return true;
diff --git a/test/generated/test.py b/test/generated/test.py
index c1480e3..a6a83e8 100644
--- a/test/generated/test.py
+++ b/test/generated/test.py
@@ -1371,6 +1371,7 @@ class xrfragment_Parser:
Frag.h["prio"] = xrfragment_Type.isInt
Frag.h["pos"] = xrfragment_Type.isVector
Frag.h["q"] = xrfragment_Type.isString
+ vec = "1,2,3"
if (key in Frag.h):
_this = Frag.h.get(key,None)
_this.matchObj = python_lib_Re.search(_this.pattern,value)
@@ -1580,8 +1581,8 @@ class xrfragment_Query:
fails = 0
qualify = 0
def _hx_local_2(expr):
- nonlocal conds
nonlocal fails
+ nonlocal conds
conds = (conds + 1)
fails = (fails + (0 if expr else 1))
return expr