@holoscript/core 8.0.7 → 8.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/holoscript.cjs +5 -1
- package/dist/GLTFPipeline-L76YTXKA.js +15 -0
- package/dist/GLTFPipeline-ZWJN7GI6.cjs +36 -0
- package/dist/HoloCompositionParser-K76KTEEE.js +12 -0
- package/dist/HoloCompositionParser-UZH6Y4HO.cjs +45 -0
- package/dist/HoloScriptCodeParser-2D4ERFUZ.js +6 -0
- package/dist/HoloScriptCodeParser-UDRLDA7I.cjs +23 -0
- package/dist/HoloScriptPlusParser-FTMCGWXD.js +13 -0
- package/dist/HoloScriptPlusParser-LQR5GIKF.cjs +30 -0
- package/dist/HoloScriptRuntime-UTRLJI5L.js +12 -0
- package/dist/HoloScriptRuntime-YBYXJHJN.cjs +21 -0
- package/dist/SceneIRCompiler-63KA3M2F.js +17 -0
- package/dist/SceneIRCompiler-KWUFHZ4O.cjs +42 -0
- package/dist/{USDZExporter-AUHZODOF.cjs → USDZExporter-ML4UMIGC.cjs} +3 -3
- package/dist/{USDZExporter-GXB4AUSG.js → USDZExporter-ZFKLQ76G.js} +3 -3
- package/dist/agents/index.cjs +1 -1
- package/dist/agents/index.js +1 -1
- package/dist/audit/AuditLogger.d.ts +106 -0
- package/dist/audit/AuditQueryBuilder.d.ts +79 -0
- package/dist/audit/ComplianceReporter.d.ts +90 -0
- package/dist/audit/index.d.ts +13 -0
- package/dist/{chunk-FGMDMJM7.js → chunk-2BYAUHBO.js} +3 -3
- package/dist/{chunk-EDPYCLRC.cjs → chunk-2E6PP5UE.cjs} +83 -59
- package/dist/{chunk-GASCWJK5.js → chunk-2EGGAZT3.js} +65 -287
- package/dist/{chunk-SIEXCILW.js → chunk-2I3XAGMF.js} +3 -3
- package/dist/{chunk-OS533P33.cjs → chunk-2KKOYZYI.cjs} +1074 -1655
- package/dist/chunk-2MQKNDNH.js +51 -0
- package/dist/{chunk-7DMMMBCY.cjs → chunk-2X3IPCBK.cjs} +10 -10
- package/dist/chunk-2ZOTBO25.cjs +202 -0
- package/dist/chunk-356N4NPM.cjs +152 -0
- package/dist/{chunk-X3GJPRVK.cjs → chunk-36NPLOI4.cjs} +92 -81
- package/dist/{chunk-SLU6UPJI.cjs → chunk-37HHY7RH.cjs} +5 -5
- package/dist/{chunk-YDPEHCCI.cjs → chunk-3CDDRUER.cjs} +3 -118
- package/dist/chunk-3F7ZZWIN.js +1651 -0
- package/dist/chunk-3ILD7TKP.cjs +187 -0
- package/dist/{chunk-X27QRG4C.cjs → chunk-3IUHTGDD.cjs} +153 -41
- package/dist/{chunk-PXNZ6TME.js → chunk-4376VHNJ.js} +60 -36
- package/dist/{chunk-YKGPCZEE.cjs → chunk-4FIBOJW6.cjs} +10 -10
- package/dist/chunk-4Q7RKQQI.cjs +14195 -0
- package/dist/{chunk-YCM6QQRT.cjs → chunk-566ZB4LZ.cjs} +180 -8
- package/dist/{chunk-2Y3V22SG.js → chunk-5CURIYGT.js} +3 -3
- package/dist/{chunk-QBWNJXNR.js → chunk-5FYMCVBY.js} +5 -5
- package/dist/{chunk-ZA34AN3R.js → chunk-5LVFTGKH.js} +841 -12
- package/dist/chunk-63AUAIL6.js +48 -0
- package/dist/chunk-655FATJU.js +110 -0
- package/dist/{chunk-TQ377OLB.cjs → chunk-65S62L4D.cjs} +28 -22
- package/dist/chunk-6NTAZN5Z.cjs +502 -0
- package/dist/chunk-6TRX6AR2.js +9376 -0
- package/dist/chunk-6ZCCLKS2.cjs +51 -0
- package/dist/{chunk-MDR235RZ.js → chunk-734OB5SK.js} +721 -8
- package/dist/{chunk-Q2Q34NF3.js → chunk-77QI552M.js} +6 -6
- package/dist/{chunk-WKX5AMOY.js → chunk-7I74JWPW.js} +3 -3
- package/dist/{chunk-5FSKKMR7.cjs → chunk-7IDJDMPU.cjs} +232 -4
- package/dist/chunk-7VBKRGIZ.cjs +847 -0
- package/dist/{chunk-KCPHASCO.js → chunk-AATYYLYK.js} +5 -5
- package/dist/{chunk-WFKVS2K4.cjs → chunk-AUZRKIHQ.cjs} +1101 -55
- package/dist/{chunk-DTGBOSEM.cjs → chunk-AWXFEAQL.cjs} +12 -12
- package/dist/{chunk-THCK6ECW.js → chunk-B3CWTCK2.js} +231 -3
- package/dist/chunk-BCP4E7MD.cjs +997 -0
- package/dist/chunk-BG7RPYJP.js +91 -0
- package/dist/{chunk-VF257YKO.js → chunk-BP4KTMLY.js} +117 -5
- package/dist/{chunk-YN6IETRZ.js → chunk-BQJ3YBF3.js} +6424 -987
- package/dist/{chunk-KOUAQL2B.cjs → chunk-CANAL6CT.cjs} +1569 -168
- package/dist/{chunk-FDSGHPAK.js → chunk-CBSDJF3B.js} +3 -3
- package/dist/{chunk-FEWUHQNM.cjs → chunk-CFVK26P4.cjs} +4 -4
- package/dist/{chunk-M7K4LE66.cjs → chunk-CI33NINL.cjs} +4 -4
- package/dist/{chunk-2OWDB4FB.js → chunk-CKV5NYAE.js} +6 -6
- package/dist/{chunk-LPS5AMQD.cjs → chunk-CM4NHXVO.cjs} +24 -24
- package/dist/chunk-D3HSRXYB.js +115 -0
- package/dist/{chunk-FNHJRI32.js → chunk-DBH3D2MU.js} +1561 -160
- package/dist/{chunk-GW3LKD5C.js → chunk-DJNH4HFW.js} +3 -3
- package/dist/{chunk-2GCNOI2U.cjs → chunk-DN6F4DHH.cjs} +9 -3
- package/dist/chunk-DQRJ5RJG.js +432 -0
- package/dist/{chunk-C7ZBSV2Q.js → chunk-DUG3OQAS.js} +106 -43
- package/dist/chunk-ECUYJOJ2.cjs +199 -0
- package/dist/chunk-EEMTCAK7.js +182 -0
- package/dist/{chunk-3SKLAUDD.cjs → chunk-EI3J6LTW.cjs} +359 -581
- package/dist/{chunk-SSSN7VAM.js → chunk-EM2OGPYE.js} +4 -4
- package/dist/{chunk-56VOWURB.cjs → chunk-ENZCIQZC.cjs} +522 -453
- package/dist/chunk-ESBXUYOC.cjs +836 -0
- package/dist/{chunk-L5U4W6JC.js → chunk-ESSEF6U2.js} +4 -4
- package/dist/chunk-ET3AN4W3.js +824 -0
- package/dist/chunk-EXKSFGSX.cjs +14 -14
- package/dist/{chunk-I76GIKN7.cjs → chunk-F3YT6GUF.cjs} +17 -17
- package/dist/{chunk-WRWEX5ZF.js → chunk-F75DZBBI.js} +3 -3
- package/dist/{chunk-4JGRWHZJ.js → chunk-FG6PYGIZ.js} +12 -6
- package/dist/chunk-FGGJQRLZ.js +14 -14
- package/dist/{chunk-SXOSDZD6.js → chunk-FWCHPCD4.js} +128 -10
- package/dist/{chunk-XW6IXEQH.cjs → chunk-G35CAQ7I.cjs} +5 -5
- package/dist/{chunk-7VMGP2FW.js → chunk-G6KACNMO.js} +132 -188
- package/dist/{chunk-FJPADH77.cjs → chunk-GAWJJAGT.cjs} +6 -6
- package/dist/chunk-GGR7QUKK.cjs +4724 -0
- package/dist/chunk-GIBF4BHH.js +14098 -0
- package/dist/{chunk-AWB7QYY6.cjs → chunk-GILYQ5VH.cjs} +6 -6
- package/dist/{chunk-FWVYAMNW.cjs → chunk-GKFCHGCM.cjs} +4 -4
- package/dist/{chunk-Y3ZFVUUU.js → chunk-GLEJ2TLS.js} +3 -3
- package/dist/{chunk-3GWWJT7L.js → chunk-GP3OKSKT.js} +13 -13
- package/dist/chunk-GTIPOEHN.js +196 -0
- package/dist/{chunk-LMJ5EBV7.cjs → chunk-GZPUA2TL.cjs} +16 -15
- package/dist/{chunk-IELX2OKI.js → chunk-H4LJ4HEA.js} +3 -115
- package/dist/{chunk-ACVWFGBI.cjs → chunk-HCX4SMFK.cjs} +3 -3
- package/dist/{chunk-HYNTS5CP.js → chunk-HHRZ6STP.js} +24 -2
- package/dist/chunk-HIDEIEFG.js +48 -0
- package/dist/{chunk-W6RW64BB.cjs → chunk-HSWBIDZM.cjs} +228 -5
- package/dist/{chunk-GSOUNWEL.js → chunk-HVX7QQYK.js} +1035 -1616
- package/dist/{chunk-TRCGG42I.cjs → chunk-IFW5IW4L.cjs} +6502 -1019
- package/dist/{chunk-F5LKJ6F5.cjs → chunk-IJU6AS67.cjs} +32 -28
- package/dist/{chunk-TVANHNJ7.js → chunk-IK6Z2HNC.js} +173 -3
- package/dist/{chunk-QGMUTVVH.cjs → chunk-IS7NTKY5.cjs} +20 -20
- package/dist/{chunk-YFVQWSNJ.js → chunk-IXWGYWH6.js} +3 -3
- package/dist/chunk-J2DAS2PL.js +148 -0
- package/dist/chunk-JBQXZIWB.js +148 -0
- package/dist/chunk-JBYBMBMW.js +261 -0
- package/dist/{chunk-LWUOUCYL.js → chunk-JEJ7TT54.js} +5 -5
- package/dist/{chunk-DUCB6LGL.js → chunk-JOTCTHN5.js} +211 -5
- package/dist/{chunk-47RUFYKR.js → chunk-K56UVEXV.js} +3 -3
- package/dist/{chunk-XSFNHP2E.js → chunk-KB26H447.js} +3 -3
- package/dist/{chunk-3NGDZZR4.js → chunk-KEYG7HGY.js} +430 -37
- package/dist/{chunk-DY72BMU5.js → chunk-KFVNCW4Q.js} +4 -4
- package/dist/chunk-KPGC7SK2.js +192 -0
- package/dist/chunk-KROXXBK5.cjs +53 -0
- package/dist/{chunk-ZPZAVHXL.cjs → chunk-LB3ZZMKT.cjs} +137 -19
- package/dist/chunk-LDYZWNJW.cjs +1654 -0
- package/dist/{chunk-ULMSSHCJ.cjs → chunk-LMB555QB.cjs} +405 -38
- package/dist/{chunk-CBJY23VL.js → chunk-MD4IVS42.js} +3 -3
- package/dist/{chunk-VMLKSV26.js → chunk-MDDWEBCX.js} +226 -3
- package/dist/chunk-MUWH4QK5.cjs +94 -0
- package/dist/{chunk-T6W3Z3SH.cjs → chunk-N2ILK7BF.cjs} +4 -4
- package/dist/{chunk-6EX3I5P4.cjs → chunk-N74QRJGP.cjs} +6 -6
- package/dist/chunk-NFFHLX37.cjs +132 -0
- package/dist/chunk-NJSYWX7H.js +190 -0
- package/dist/{chunk-SH5PPVK7.cjs → chunk-NQN5LFN4.cjs} +165 -221
- package/dist/chunk-NTQRFOPP.cjs +56 -0
- package/dist/{chunk-YFWRJW4B.js → chunk-NWMJPTVL.js} +51 -55
- package/dist/{chunk-63ZGNR2T.cjs → chunk-OC6GV5QH.cjs} +42 -42
- package/dist/{chunk-7E7GCQCK.js → chunk-OG3MBHM3.js} +9 -3
- package/dist/chunk-OMNHTCS4.cjs +264 -0
- package/dist/chunk-OQXB6NNC.cjs +117 -0
- package/dist/{chunk-Y57W2CT5.cjs → chunk-OV46CCA2.cjs} +51 -55
- package/dist/{chunk-6PRZIHGL.cjs → chunk-OV6HHKLE.cjs} +21 -266
- package/dist/{chunk-C37BHB7N.cjs → chunk-P26YYPOO.cjs} +5 -5
- package/dist/{chunk-2BZHWUSR.cjs → chunk-P7JEKJTZ.cjs} +16 -16
- package/dist/{chunk-NGBXXZLL.cjs → chunk-PDXX5UI4.cjs} +45 -45
- package/dist/{chunk-FHQFPYV4.js → chunk-PJFTTSKE.js} +8 -7
- package/dist/{chunk-GVFJ6T4S.cjs → chunk-PVODJEJ7.cjs} +721 -8
- package/dist/{chunk-ZZ7RO2UQ.js → chunk-Q265VZJ4.js} +3 -3
- package/dist/{chunk-E7JP3BS3.cjs → chunk-Q47JEE2C.cjs} +4 -4
- package/dist/chunk-QBY7LRN2.js +281 -0
- package/dist/{chunk-Z6PMDS4G.js → chunk-QDQWKSU3.js} +1090 -53
- package/dist/{chunk-GH6C2QGW.cjs → chunk-QEDMOGF3.cjs} +857 -16
- package/dist/{chunk-5WUNN6ZN.cjs → chunk-QHSAVOOL.cjs} +24 -2
- package/dist/chunk-QJNCDVYM.cjs +137 -0
- package/dist/chunk-QM7FJB5W.js +4717 -0
- package/dist/chunk-QQFB4RT2.cjs +448 -0
- package/dist/chunk-QSYBHQAD.cjs +196 -0
- package/dist/{chunk-UGXHYIWT.cjs → chunk-QUJ3ZB55.cjs} +28 -28
- package/dist/{chunk-2YSNA2F2.cjs → chunk-QVJMDVYZ.cjs} +5 -5
- package/dist/chunk-RAJMAX6D.js +131 -0
- package/dist/{chunk-VVKVQZI6.js → chunk-RAN3ECAS.js} +3 -3
- package/dist/chunk-RKGUZBOC.js +79 -0
- package/dist/{chunk-HLFDZ35S.cjs → chunk-RRQIAJLQ.cjs} +8 -8
- package/dist/{chunk-PABONWKI.js → chunk-RXQNRZ5F.js} +3 -3
- package/dist/{chunk-7ZHYEITD.cjs → chunk-S4O7CFHQ.cjs} +10 -11
- package/dist/chunk-SE7ANBGN.js +128 -0
- package/dist/{chunk-X2AVEAZM.cjs → chunk-SJIRCTIS.cjs} +176 -2
- package/dist/{chunk-WXQ57LAO.js → chunk-SQXAZHDG.js} +4 -4
- package/dist/chunk-SR73L5ZP.cjs +84 -0
- package/dist/{chunk-OABEO6HH.js → chunk-SZOLTWWD.js} +2349 -214
- package/dist/{chunk-5JEU52DW.js → chunk-TPZ3BN2D.js} +3 -3
- package/dist/{chunk-QFU53KRH.js → chunk-TSTFYGGX.js} +4 -5
- package/dist/{chunk-EBS32AJI.cjs → chunk-TZCFKZ6Z.cjs} +5 -5
- package/dist/chunk-UCVZXQ63.js +724 -0
- package/dist/chunk-UGQ3QNV6.js +992 -0
- package/dist/chunk-UNMVGZVW.js +142 -0
- package/dist/{chunk-TEVX443G.js → chunk-UTUD6GJI.js} +178 -6
- package/dist/chunk-UXBYA7DV.cjs +155 -0
- package/dist/chunk-V6GXFSK7.cjs +443 -0
- package/dist/chunk-VHORVGCG.cjs +761 -0
- package/dist/{chunk-B4EKV6HQ.js → chunk-VKCTYLDN.js} +500 -442
- package/dist/{chunk-O3MGZDCT.cjs → chunk-VTEXJOSD.cjs} +63 -63
- package/dist/chunk-VVAAZITA.cjs +287 -0
- package/dist/{chunk-V7AKE5VT.cjs → chunk-W2GA3EQB.cjs} +435 -42
- package/dist/chunk-W4GABFCR.js +37 -0
- package/dist/chunk-WKEK4NCA.js +490 -0
- package/dist/{chunk-5A4TCHOC.cjs → chunk-WNYXT4TE.cjs} +4 -4
- package/dist/{chunk-S762UEV5.js → chunk-WTH23ISI.js} +6 -6
- package/dist/{chunk-BTKZGHAV.js → chunk-WWNCM473.js} +10 -6
- package/dist/{chunk-7X5PNIQJ.js → chunk-X3YFRH6K.js} +27 -25
- package/dist/{chunk-4YNYPHH3.cjs → chunk-X75H75UY.cjs} +2351 -213
- package/dist/{chunk-LYJJI7ZK.cjs → chunk-XCUDDFKC.cjs} +216 -9
- package/dist/chunk-YAO4HPJL.cjs +120 -0
- package/dist/chunk-YKY2JBER.cjs +9443 -0
- package/dist/chunk-YP5CHEYU.cjs +154 -0
- package/dist/{chunk-WRNEH5MO.js → chunk-YW3I2FQL.js} +18 -7
- package/dist/{chunk-BRNUPDHJ.js → chunk-Z557DVYN.js} +386 -19
- package/dist/{chunk-VSACG2AR.js → chunk-Z6LZUYZF.js} +21 -264
- package/dist/chunk-ZHPMP447.cjs +43 -0
- package/dist/{chunk-LODTHGST.cjs → chunk-ZK7KX5CD.cjs} +133 -70
- package/dist/{chunk-CCPSNT6B.cjs → chunk-ZRPALBQB.cjs} +5 -5
- package/dist/chunk-ZVFHPMC5.js +824 -0
- package/dist/chunk-ZVQMKUGJ.js +443 -0
- package/dist/cli/holoscript-runner.cjs +86 -48
- package/dist/cli/holoscript-runner.js +54 -16
- package/dist/codebase/index.cjs +1 -1
- package/dist/codebase/index.js +1 -1
- package/dist/compiler/agent-inference.cjs +11 -11
- package/dist/compiler/agent-inference.js +9 -6
- package/dist/compiler/android-xr.cjs +13 -12
- package/dist/compiler/android-xr.js +11 -10
- package/dist/compiler/android.cjs +12 -12
- package/dist/compiler/android.js +10 -10
- package/dist/compiler/business-quest.cjs +10 -10
- package/dist/compiler/business-quest.js +2 -2
- package/dist/compiler/coco.cjs +1 -1
- package/dist/compiler/coco.js +1 -1
- package/dist/compiler/context.cjs +9 -9
- package/dist/compiler/context.js +6 -6
- package/dist/compiler/daimon-seed.cjs +36 -0
- package/dist/compiler/daimon-seed.js +12 -0
- package/dist/compiler/domain-block-utils.cjs +205 -156
- package/dist/compiler/domain-block-utils.js +8 -7
- package/dist/compiler/dtdl.cjs +10 -10
- package/dist/compiler/dtdl.js +7 -7
- package/dist/compiler/gltf-pipeline.cjs +9 -9
- package/dist/compiler/gltf-pipeline.js +2 -2
- package/dist/compiler/godot.cjs +10 -9
- package/dist/compiler/godot.js +9 -8
- package/dist/compiler/incremental.cjs +11 -11
- package/dist/compiler/incremental.js +6 -6
- package/dist/compiler/index.cjs +2585 -3273
- package/dist/compiler/index.d.ts +149 -35
- package/dist/compiler/index.js +2197 -3102
- package/dist/compiler/ios.cjs +11 -11
- package/dist/compiler/ios.js +9 -9
- package/dist/compiler/llm-provider-capabilities.cjs +9 -9
- package/dist/compiler/llm-provider-capabilities.js +6 -6
- package/dist/compiler/nodetoy.cjs +1 -1
- package/dist/compiler/nodetoy.js +1 -1
- package/dist/compiler/openxr.cjs +11 -10
- package/dist/compiler/openxr.js +10 -9
- package/dist/compiler/remotion.cjs +1 -1
- package/dist/compiler/remotion.js +1 -1
- package/dist/compiler/reproducibility.cjs +1 -1
- package/dist/compiler/reproducibility.js +1 -1
- package/dist/compiler/sdf.cjs +11 -10
- package/dist/compiler/sdf.js +9 -8
- package/dist/compiler/semantic-scene.cjs +7 -7
- package/dist/compiler/semantic-scene.js +2 -2
- package/dist/compiler/state.cjs +9 -9
- package/dist/compiler/state.js +7 -7
- package/dist/compiler/trait-composition.cjs +11 -11
- package/dist/compiler/trait-composition.js +7 -7
- package/dist/compiler/traits/ProvenanceSemiring.d.ts +167 -0
- package/dist/compiler/traits/Semiring.d.ts +26 -0
- package/dist/compiler/unity.cjs +11 -10
- package/dist/compiler/unity.js +10 -9
- package/dist/compiler/unreal.cjs +12 -11
- package/dist/compiler/unreal.js +10 -9
- package/dist/compiler/urdf.cjs +18 -17
- package/dist/compiler/urdf.js +9 -8
- package/dist/compiler/usd-physics.cjs +11 -10
- package/dist/compiler/usd-physics.js +8 -7
- package/dist/compiler/visionos.cjs +11 -10
- package/dist/compiler/visionos.js +10 -9
- package/dist/compiler/vrchat.cjs +11 -10
- package/dist/compiler/vrchat.js +9 -8
- package/dist/compiler/wasm.cjs +14 -13
- package/dist/compiler/wasm.js +9 -8
- package/dist/compiler/webgpu.cjs +10 -9
- package/dist/compiler/webgpu.js +9 -8
- package/dist/constants.cjs +398 -0
- package/dist/constants.js +9 -0
- package/dist/coordinators/index.cjs +4 -1
- package/dist/coordinators/index.js +4 -1
- package/dist/debugger.cjs +11 -9
- package/dist/debugger.js +9 -7
- package/dist/{dist-ACXG6IH5.cjs → dist-GRMOP2UL.cjs} +341 -65
- package/dist/{dist-VD4L6V7Q.js → dist-ZBUKU2JG.js} +333 -63
- package/dist/entries/interop.cjs +23 -23
- package/dist/entries/interop.js +3 -3
- package/dist/entries/scripting.cjs +12 -11
- package/dist/entries/scripting.js +8 -7
- package/dist/evolution/index.cjs +66 -0
- package/dist/evolution/index.d.ts +162 -0
- package/dist/evolution/index.js +17 -0
- package/dist/hololand/index.cjs +41 -37
- package/dist/hololand/index.js +3 -3
- package/dist/index.cjs +12394 -3224
- package/dist/index.d.ts +260 -18
- package/dist/index.js +10755 -2182
- package/dist/keyword-registry/PluginKeywordRegistry.d.ts +138 -0
- package/dist/keyword-registry/index.cjs +29 -0
- package/dist/keyword-registry/index.d.ts +1 -0
- package/dist/keyword-registry/index.js +4 -0
- package/dist/math/tropical-spmv.cjs +11 -11
- package/dist/math/tropical-spmv.d.ts +1 -0
- package/dist/math/tropical-spmv.js +2 -2
- package/dist/math/tropicalSpmv.d.ts +43 -0
- package/dist/math/vec3.cjs +1 -1
- package/dist/math/vec3.js +1 -1
- package/dist/matter/StagedMatter.d.ts +82 -0
- package/dist/matter/index.cjs +17 -0
- package/dist/matter/index.d.ts +1 -0
- package/dist/matter/index.js +4 -0
- package/dist/{ml-dsa-Z7JDKW4L.js → ml-dsa-J6VKVT4K.js} +3 -3
- package/dist/{ml-dsa-FSKBTE3W.cjs → ml-dsa-MTIK4ZUQ.cjs} +23 -23
- package/dist/paper-0c-spike/index.cjs +1 -1
- package/dist/paper-0c-spike/index.js +1 -1
- package/dist/parameter-envelope/ParameterEnvelope.d.ts +128 -0
- package/dist/parameter-envelope/index.cjs +17 -0
- package/dist/parameter-envelope/index.d.ts +2 -0
- package/dist/parameter-envelope/index.js +4 -0
- package/dist/parser/HoloCompositionTypes.d.ts +2013 -0
- package/dist/parser/PipelineParser.d.ts +162 -0
- package/dist/parser.cjs +36 -20
- package/dist/parser.js +13 -9
- package/dist/plugin-manifest/ManifestAutoLoader.d.ts +35 -0
- package/dist/plugin-manifest/PluginManifest.d.ts +156 -0
- package/dist/plugin-manifest/index.cjs +25 -0
- package/dist/plugin-manifest/index.d.ts +2 -0
- package/dist/plugin-manifest/index.js +4 -0
- package/dist/plugin-solver-contract/PluginSolverContract.d.ts +288 -0
- package/dist/plugin-solver-contract/index.cjs +41 -0
- package/dist/plugin-solver-contract/index.d.ts +1 -0
- package/dist/plugin-solver-contract/index.js +4 -0
- package/dist/policy/ContentPolicyGate.d.ts +51 -0
- package/dist/policy/PolicyPack.d.ts +120 -0
- package/dist/policy/blocklist.d.ts +32 -0
- package/dist/policy/defaults.d.ts +44 -0
- package/dist/policy/index.cjs +106 -0
- package/dist/policy/index.d.ts +17 -0
- package/dist/policy/index.js +5 -0
- package/dist/policy/jsonLogic.d.ts +31 -0
- package/dist/policy/types.d.ts +174 -0
- package/dist/proof-composition/ProofCompositionLaw.d.ts +93 -0
- package/dist/proof-composition/index.cjs +25 -0
- package/dist/proof-composition/index.d.ts +1 -0
- package/dist/proof-composition/index.js +4 -0
- package/dist/receipts/hash-policy.d.ts +85 -0
- package/dist/reconstruction/index.cjs +75 -47
- package/dist/reconstruction/index.js +5 -5
- package/dist/runtime/plugin-trait-registrar.d.ts +36 -0
- package/dist/runtime.cjs +81 -79
- package/dist/runtime.js +9 -7
- package/dist/scene-presets-EDKYZ5GW.js +4 -0
- package/dist/scene-presets-NCW2CFRS.cjs +17 -0
- package/dist/self-improvement/index.cjs +1 -1
- package/dist/self-improvement/index.js +1 -1
- package/dist/{src-PT2FERDV.cjs → src-G3D7ZATQ.cjs} +545 -21
- package/dist/{src-J6CM4AUR.js → src-UXYA7HM6.js} +539 -16
- package/dist/storage/index.cjs +10 -10
- package/dist/storage/index.js +3 -3
- package/dist/testing.cjs +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/index.cjs +3631 -0
- package/dist/tools/index.js +3581 -0
- package/dist/traitDocs/traitDocs.cjs +9 -9
- package/dist/traitDocs/traitDocs.d.ts +1 -0
- package/dist/traitDocs/traitDocs.js +3 -3
- package/dist/traits/ControlLoopTrait.d.ts +154 -0
- package/dist/traits/KinematicChainTrait.d.ts +116 -0
- package/dist/traits/SensorSamplingTrait.d.ts +154 -0
- package/dist/traits/TraitTypes.d.ts +270 -0
- package/dist/traits/TransactionTrait.d.ts +121 -0
- package/dist/traits/botanical-lotus.cjs +54 -50
- package/dist/traits/botanical-lotus.js +2 -5
- package/dist/traits/control-loop.cjs +21 -0
- package/dist/traits/control-loop.d.ts +1 -0
- package/dist/traits/control-loop.js +4 -0
- package/dist/traits/engines/cloth-verlet.d.ts +65 -0
- package/dist/traits/engines/index.cjs +19 -19
- package/dist/traits/engines/index.d.ts +15 -275
- package/dist/traits/engines/index.js +3 -3
- package/dist/traits/engines/motion-data-schema.d.ts +119 -0
- package/dist/traits/engines/motion-matching.d.ts +102 -0
- package/dist/traits/engines/noise.d.ts +25 -0
- package/dist/traits/engines/onnx-adapter.d.ts +173 -0
- package/dist/traits/engines/onnx-motion-matching.d.ts +163 -0
- package/dist/traits/engines/pfnn-network.d.ts +92 -0
- package/dist/traits/engines/synthetic-walk-cycle.d.ts +38 -0
- package/dist/traits/engines/tensor-ops.d.ts +15 -0
- package/dist/traits/index.cjs +2789 -1259
- package/dist/traits/index.d.ts +35 -0
- package/dist/traits/index.js +1692 -411
- package/dist/traits/kinematic-chain.cjs +25 -0
- package/dist/traits/kinematic-chain.d.ts +1 -0
- package/dist/traits/kinematic-chain.js +4 -0
- package/dist/traits/sensor-sampling.cjs +33 -0
- package/dist/traits/sensor-sampling.d.ts +1 -0
- package/dist/traits/sensor-sampling.js +4 -0
- package/dist/traits/simulation-solver-factory.cjs +1 -1
- package/dist/traits/simulation-solver-factory.js +1 -1
- package/dist/traits/transaction.cjs +29 -0
- package/dist/traits/transaction.d.ts +1 -0
- package/dist/traits/transaction.js +4 -0
- package/dist/traits/webcam-gaze.cjs +1 -1
- package/dist/traits/webcam-gaze.js +1 -1
- package/dist/type-checker.cjs +7 -6
- package/dist/type-checker.js +5 -4
- package/dist/types/AdvancedTypeSystem.d.ts +489 -0
- package/dist/types/HoloScriptPlus.d.ts +810 -0
- package/dist/types/base.d.ts +248 -0
- package/dist/types.d.ts +799 -0
- package/dist/world/index.cjs +3 -4
- package/dist/world/index.js +3 -4
- package/dist/world-model/index.cjs +1 -1
- package/dist/world-model/index.js +1 -1
- package/dist/wot/index.cjs +1 -1
- package/dist/wot/index.js +1 -1
- package/package.json +80 -13
- package/dist/GLTFPipeline-3EJLL3TS.cjs +0 -38
- package/dist/GLTFPipeline-3OWJV2VK.js +0 -17
- package/dist/HoloScriptPlusParser-ADWRY5OS.cjs +0 -698
- package/dist/HoloScriptPlusParser-JLJDXHSC.js +0 -693
- package/dist/HoloScriptPlusParser-QCGFPWIL.cjs +0 -27
- package/dist/HoloScriptPlusParser-WENAFEFV.js +0 -10
- package/dist/HoloScriptRuntime-GGRVEU4T.cjs +0 -19
- package/dist/HoloScriptRuntime-GJK6VJPH.js +0 -10
- package/dist/chunk-22Q5A6RV.js +0 -979
- package/dist/chunk-4C57PR42.js +0 -468
- package/dist/chunk-4W5G5QVL.cjs +0 -847
- package/dist/chunk-5ET6L4NS.js +0 -487
- package/dist/chunk-C4GSLCHE.cjs +0 -7153
- package/dist/chunk-F2G6CWFT.js +0 -7089
- package/dist/chunk-G6PNEASF.cjs +0 -814
- package/dist/chunk-GTA4Q3A3.js +0 -1491
- package/dist/chunk-HCCQLAA4.cjs +0 -74
- package/dist/chunk-HFSVMKM3.cjs +0 -72
- package/dist/chunk-KAIVDEIG.cjs +0 -4539
- package/dist/chunk-KQU64CIX.cjs +0 -1508
- package/dist/chunk-MSYSQ2AJ.js +0 -4533
- package/dist/chunk-NHJLP37F.js +0 -70
- package/dist/chunk-NHYRRAGI.cjs +0 -490
- package/dist/chunk-OIQYIIO3.cjs +0 -473
- package/dist/chunk-OL46QLBJ.js +0 -61
- package/dist/chunk-SKZPC5AG.cjs +0 -984
- package/dist/chunk-SLHLXUMO.js +0 -445
- package/dist/chunk-UOIGFQXC.cjs +0 -9750
- package/dist/chunk-UOL6Y5TD.cjs +0 -759
- package/dist/chunk-UVFI7XIR.cjs +0 -452
- package/dist/chunk-VEPGBETF.js +0 -844
- package/dist/chunk-XQ5MWMP2.js +0 -756
- package/dist/chunk-XT6JY5W5.js +0 -9684
- package/dist/chunk-YRRAUB35.js +0 -811
- package/dist/compiler/GasOptimizationAnalyzer.d.ts +0 -73
- package/dist/compiler/NFTMarketplaceCompiler.d.ts +0 -23
- package/dist/compiler/ar.cjs +0 -23
- package/dist/compiler/ar.js +0 -11
- package/dist/compiler/babylon.cjs +0 -21
- package/dist/compiler/babylon.js +0 -15
- package/dist/compiler/multi-layer.cjs +0 -24
- package/dist/compiler/multi-layer.js +0 -15
- package/dist/compiler/playcanvas.cjs +0 -19
- package/dist/compiler/playcanvas.js +0 -13
- package/dist/compiler/r3f.cjs +0 -39
- package/dist/compiler/r3f.d.ts +0 -22
- package/dist/compiler/r3f.js +0 -17
- package/dist/compiler/vrr.cjs +0 -24
- package/dist/compiler/vrr.js +0 -12
- package/dist/parser/NFTMarketplaceTypes.d.ts +0 -191
- package/dist/playwright-3AT3AKTV.cjs +0 -98673
- package/dist/playwright-VZPDVUEQ.js +0 -98660
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parsePipeline } from './chunk-SYTRBGDS.js';
|
|
2
|
+
import { ErrorRecovery } from './chunk-Z6LZUYZF.js';
|
|
2
3
|
|
|
3
4
|
// src/parser/TypoDetector.ts
|
|
4
5
|
var TypoDetector = class {
|
|
@@ -170,6 +171,17 @@ var KEYWORDS = {
|
|
|
170
171
|
waypoints: "WAYPOINTS",
|
|
171
172
|
constraint: "CONSTRAINT",
|
|
172
173
|
terrain: "TERRAIN",
|
|
174
|
+
// MMO/AAA game constructs (v6.2)
|
|
175
|
+
loot_table: "LOOT_TABLE",
|
|
176
|
+
world_chunk: "WORLD_CHUNK",
|
|
177
|
+
spawn_point: "SPAWN_POINT",
|
|
178
|
+
game_trigger: "GAME_TRIGGER",
|
|
179
|
+
movement_path: "MOVEMENT_PATH",
|
|
180
|
+
reaction_trigger: "REACTION_TRIGGER",
|
|
181
|
+
world_layer: "WORLD_LAYER",
|
|
182
|
+
dungeon_instance: "DUNGEON_INSTANCE",
|
|
183
|
+
world_shard: "WORLD_SHARD",
|
|
184
|
+
real_estate: "REAL_ESTATE",
|
|
173
185
|
// IoT / Digital Twin
|
|
174
186
|
sensor: "IOT_SENSOR",
|
|
175
187
|
device: "IOT_DEVICE",
|
|
@@ -250,6 +262,10 @@ var KEYWORDS = {
|
|
|
250
262
|
bridge: "WEB3_CONTRACT",
|
|
251
263
|
// Perception & simulation layer (v4.2 — March 2026)
|
|
252
264
|
material: "MATERIAL",
|
|
265
|
+
material_graph: "MATERIAL_GRAPH",
|
|
266
|
+
light_field: "LIGHT_FIELD",
|
|
267
|
+
nav_field: "NAV_FIELD",
|
|
268
|
+
physics_contract: "PHYSICS_CONTRACT",
|
|
253
269
|
pbr_material: "PBR_MATERIAL",
|
|
254
270
|
unlit_material: "UNLIT_MATERIAL",
|
|
255
271
|
shader: "SHADER",
|
|
@@ -271,6 +287,7 @@ var KEYWORDS = {
|
|
|
271
287
|
particles: "PARTICLES",
|
|
272
288
|
emitter: "EMITTER",
|
|
273
289
|
vfx: "VFX",
|
|
290
|
+
particle_field: "PARTICLE_FIELD",
|
|
274
291
|
post_processing: "POST_PROCESSING",
|
|
275
292
|
post_fx: "POST_FX",
|
|
276
293
|
render_pipeline: "POST_PROCESSING",
|
|
@@ -286,6 +303,7 @@ var KEYWORDS = {
|
|
|
286
303
|
climate: "WEATHER",
|
|
287
304
|
simulation: "SIMULATION",
|
|
288
305
|
procedural: "PROCEDURAL",
|
|
306
|
+
pcg_graph: "PCG_GRAPH",
|
|
289
307
|
generate: "PROCEDURAL",
|
|
290
308
|
scatter: "SCATTER",
|
|
291
309
|
distribute: "SCATTER",
|
|
@@ -329,6 +347,11 @@ var KEYWORDS = {
|
|
|
329
347
|
payment_gate: "PAYMENT_GATE",
|
|
330
348
|
subscription: "SUBSCRIPTION",
|
|
331
349
|
tip_jar: "TIP_JAR",
|
|
350
|
+
// SimulationContract block (v6.3 — NORTH_STAR thesis: simulation IS the proof)
|
|
351
|
+
sim_contract: "HOLO_CONTRACT",
|
|
352
|
+
// Pub/sub messaging primitives (v6.4)
|
|
353
|
+
topic: "HOLO_TOPIC",
|
|
354
|
+
channel: "HOLO_CHANNEL",
|
|
332
355
|
// v6 Universal domains (v5.4 — Domains Unified)
|
|
333
356
|
service: "SERVICE_BLOCK",
|
|
334
357
|
endpoint: "ENDPOINT_BLOCK",
|
|
@@ -760,6 +783,7 @@ var KEYWORDS_AS_IDENTIFIERS = [
|
|
|
760
783
|
"EFFECTS",
|
|
761
784
|
"CAMERA",
|
|
762
785
|
"BIND",
|
|
786
|
+
"CONNECT",
|
|
763
787
|
"TIMELINE",
|
|
764
788
|
"AUDIO",
|
|
765
789
|
"ZONE",
|
|
@@ -792,7 +816,9 @@ var KEYWORDS_AS_IDENTIFIERS = [
|
|
|
792
816
|
"COMPOSITION",
|
|
793
817
|
"SPATIAL_GROUP",
|
|
794
818
|
"SPATIAL_AGENT",
|
|
795
|
-
"SPATIAL_CONTAINER"
|
|
819
|
+
"SPATIAL_CONTAINER",
|
|
820
|
+
"HOLO_TOPIC",
|
|
821
|
+
"HOLO_CHANNEL"
|
|
796
822
|
];
|
|
797
823
|
function isKeywordAsIdentifierType(api, type) {
|
|
798
824
|
if (api.DOMAIN_TOKENS.has(type)) return true;
|
|
@@ -1048,7 +1074,6 @@ function parseObjectExpression(api) {
|
|
|
1048
1074
|
|
|
1049
1075
|
// src/parser/HoloCompositionParser.ts
|
|
1050
1076
|
var _HoloCompositionParser = class _HoloCompositionParser {
|
|
1051
|
-
// Track parsing context for better errors
|
|
1052
1077
|
constructor(options = {}) {
|
|
1053
1078
|
this.tokens = [];
|
|
1054
1079
|
this.pos = 0;
|
|
@@ -1061,6 +1086,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1061
1086
|
strict: false,
|
|
1062
1087
|
...options
|
|
1063
1088
|
};
|
|
1089
|
+
this.errorRecovery = new ErrorRecovery(this.options.knownTraits);
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* The error-recovery engine for this parser, seeded with the injected
|
|
1093
|
+
* `knownTraits` union when one was supplied via parser options. Exposed so
|
|
1094
|
+
* tooling (and tests) can verify the trait-vocabulary seam is wired through.
|
|
1095
|
+
*/
|
|
1096
|
+
getErrorRecovery() {
|
|
1097
|
+
return this.errorRecovery;
|
|
1064
1098
|
}
|
|
1065
1099
|
/** Instance accessor for the static DOMAIN_TOKENS set — satisfies ExpressionParserApi. */
|
|
1066
1100
|
get DOMAIN_TOKENS() {
|
|
@@ -1135,7 +1169,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1135
1169
|
domainBlocks: [],
|
|
1136
1170
|
// v4.5 additions — CRSEC norm lifecycle
|
|
1137
1171
|
norms: [],
|
|
1138
|
-
metanorms: []
|
|
1172
|
+
metanorms: [],
|
|
1173
|
+
// v6.2 additions — MMO/AAA game constructs
|
|
1174
|
+
spawnPoints: [],
|
|
1175
|
+
triggers: [],
|
|
1176
|
+
lootTables: [],
|
|
1177
|
+
worldChunks: [],
|
|
1178
|
+
worldLayers: [],
|
|
1179
|
+
dungeonInstances: [],
|
|
1180
|
+
worldShards: [],
|
|
1181
|
+
movementPaths: [],
|
|
1182
|
+
reactionTriggers: [],
|
|
1183
|
+
policyPacks: []
|
|
1139
1184
|
};
|
|
1140
1185
|
while (!this.isAtEnd()) {
|
|
1141
1186
|
try {
|
|
@@ -1179,8 +1224,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1179
1224
|
} else if (decoratorName === "state") {
|
|
1180
1225
|
composition.state = this.parseStateBody();
|
|
1181
1226
|
} else if (decoratorName === "state_machine") {
|
|
1227
|
+
const name = this.parseOptionalStateMachineName("implicit");
|
|
1182
1228
|
if (this.check("LBRACE")) {
|
|
1183
|
-
composition.stateMachines.push(this.parseStateMachineFromDecorator());
|
|
1229
|
+
composition.stateMachines.push(this.parseStateMachineFromDecorator(name));
|
|
1184
1230
|
}
|
|
1185
1231
|
} else {
|
|
1186
1232
|
composition.traits = composition.traits || [];
|
|
@@ -1210,7 +1256,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1210
1256
|
composition.logic = this.parseLogic();
|
|
1211
1257
|
} else if (this.check("TIMELINE")) {
|
|
1212
1258
|
composition.timelines.push(this.parseTimeline());
|
|
1213
|
-
} else if (this.check("STATE")) {
|
|
1259
|
+
} else if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
1214
1260
|
composition.state = this.parseState();
|
|
1215
1261
|
} else if (this.check("IMPORT")) {
|
|
1216
1262
|
composition.imports.push(this.parseImport());
|
|
@@ -1245,8 +1291,53 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1245
1291
|
composition.norms.push(this.parseNormBlock());
|
|
1246
1292
|
} else if (this.check("METANORM")) {
|
|
1247
1293
|
composition.metanorms.push(this.parseMetanormBlock());
|
|
1294
|
+
} else if (this.check("HOLO_CONTRACT")) {
|
|
1295
|
+
composition.contract = this.parseContractBlock();
|
|
1296
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "policy_pack") {
|
|
1297
|
+
composition.policyPacks.push(this.parsePolicyPackBlock());
|
|
1298
|
+
} else if (this.check("HOLO_TOPIC")) {
|
|
1299
|
+
if (!composition.topics) composition.topics = [];
|
|
1300
|
+
composition.topics.push(this.parseTopicBlock());
|
|
1301
|
+
} else if (this.check("HOLO_CHANNEL")) {
|
|
1302
|
+
if (!composition.channels) composition.channels = [];
|
|
1303
|
+
composition.channels.push(this.parseChannelBlock());
|
|
1304
|
+
} else if (this.check("CONNECT")) {
|
|
1305
|
+
if (!composition.connections) composition.connections = [];
|
|
1306
|
+
composition.connections.push(this.parseConnectionStmt());
|
|
1307
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "shareplay") {
|
|
1308
|
+
composition.metadata = {
|
|
1309
|
+
...composition.metadata ?? {},
|
|
1310
|
+
shareplay: this.parseSharePlayBlock()
|
|
1311
|
+
};
|
|
1312
|
+
} else if (this.isLooseOnHandlerStart()) {
|
|
1313
|
+
this.skipLooseOnHandler();
|
|
1314
|
+
} else if (this.check("LOOT_TABLE")) {
|
|
1315
|
+
composition.lootTables.push(this.parseLootTable());
|
|
1316
|
+
} else if (this.check("WORLD_CHUNK")) {
|
|
1317
|
+
composition.worldChunks.push(this.parseWorldChunk());
|
|
1318
|
+
} else if (this.check("SPAWN_POINT")) {
|
|
1319
|
+
composition.spawnPoints.push(this.parseSpawnPoint());
|
|
1320
|
+
} else if (this.check("GAME_TRIGGER")) {
|
|
1321
|
+
composition.triggers.push(this.parseGameTrigger());
|
|
1322
|
+
} else if (this.check("MOVEMENT_PATH")) {
|
|
1323
|
+
composition.movementPaths.push(this.parseMovementPath());
|
|
1324
|
+
} else if (this.check("REACTION_TRIGGER")) {
|
|
1325
|
+
composition.reactionTriggers.push(this.parseReactionTrigger());
|
|
1326
|
+
} else if (this.check("WORLD_LAYER")) {
|
|
1327
|
+
composition.worldLayers.push(this.parseWorldLayer());
|
|
1328
|
+
} else if (this.check("DUNGEON_INSTANCE")) {
|
|
1329
|
+
composition.dungeonInstances.push(this.parseDungeonInstance());
|
|
1330
|
+
} else if (this.check("WORLD_SHARD")) {
|
|
1331
|
+
composition.worldShards.push(this.parseWorldShard());
|
|
1332
|
+
} else if (this.check("REAL_ESTATE")) {
|
|
1333
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1334
|
+
} else if (this.check("SCENE")) {
|
|
1335
|
+
if (!composition.scenes) composition.scenes = [];
|
|
1336
|
+
composition.scenes.push(this.parseScene());
|
|
1248
1337
|
} else if (this.isDomainBlockToken()) {
|
|
1249
1338
|
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1339
|
+
} else if (this.isLooseDomainBlockStart() || this.isLooseNamedDomainBlockStart()) {
|
|
1340
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1250
1341
|
} else if (this.check("MODULE")) {
|
|
1251
1342
|
this.advance();
|
|
1252
1343
|
if (this.check("STRING")) this.expectString();
|
|
@@ -1302,12 +1393,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1302
1393
|
this.expect("LBRACE");
|
|
1303
1394
|
this.skipNewlines();
|
|
1304
1395
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1305
|
-
this.
|
|
1396
|
+
this.skipBlockMemberSeparators();
|
|
1306
1397
|
if (this.check("RBRACE")) break;
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1398
|
+
if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
1399
|
+
const key = this.parsePropertyKey();
|
|
1400
|
+
const value = this.parseBlockTraitConfig();
|
|
1401
|
+
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1402
|
+
} else {
|
|
1403
|
+
const key = this.parsePropertyKey();
|
|
1404
|
+
this.expect("COLON");
|
|
1405
|
+
const value = this.parseValue();
|
|
1406
|
+
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1407
|
+
}
|
|
1311
1408
|
this.skipNewlines();
|
|
1312
1409
|
}
|
|
1313
1410
|
this.expect("RBRACE");
|
|
@@ -1337,15 +1434,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1337
1434
|
this.expect("LBRACE");
|
|
1338
1435
|
this.skipNewlines();
|
|
1339
1436
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1340
|
-
this.
|
|
1437
|
+
this.skipBlockMemberSeparators();
|
|
1341
1438
|
if (this.check("RBRACE")) break;
|
|
1342
1439
|
if (this.check("AT")) {
|
|
1343
1440
|
this.advance();
|
|
1344
1441
|
const traitName = this.expectIdentifier();
|
|
1345
1442
|
const config = this.parseOptionalTraitConfig();
|
|
1346
1443
|
traits.push({ type: "ObjectTrait", name: traitName, config });
|
|
1347
|
-
} else if (this.
|
|
1348
|
-
const key = this.
|
|
1444
|
+
} else if (this.isPropertyName()) {
|
|
1445
|
+
const key = this.parsePropertyKey();
|
|
1349
1446
|
if (this.check("COLON")) {
|
|
1350
1447
|
this.advance();
|
|
1351
1448
|
properties.push({ type: "ObjectProperty", key, value: this.parseValue() });
|
|
@@ -1433,13 +1530,31 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1433
1530
|
domainBlocks: [],
|
|
1434
1531
|
// v4.5 additions — CRSEC norm lifecycle
|
|
1435
1532
|
norms: [],
|
|
1436
|
-
metanorms: []
|
|
1533
|
+
metanorms: [],
|
|
1534
|
+
// v6.2 additions — MMO/AAA game constructs
|
|
1535
|
+
spawnPoints: [],
|
|
1536
|
+
triggers: [],
|
|
1537
|
+
lootTables: [],
|
|
1538
|
+
worldChunks: [],
|
|
1539
|
+
worldLayers: [],
|
|
1540
|
+
dungeonInstances: [],
|
|
1541
|
+
worldShards: [],
|
|
1542
|
+
movementPaths: [],
|
|
1543
|
+
reactionTriggers: [],
|
|
1544
|
+
policyPacks: []
|
|
1437
1545
|
};
|
|
1438
1546
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1439
1547
|
try {
|
|
1440
|
-
this.
|
|
1548
|
+
this.skipBlockMemberSeparators();
|
|
1441
1549
|
if (this.check("RBRACE")) break;
|
|
1442
|
-
if (this.check("
|
|
1550
|
+
if (this.peek(1).type === "COLON" && (this.isPropertyName() || this.check("METADATA_BLOCK"))) {
|
|
1551
|
+
const key = this.advance().value;
|
|
1552
|
+
this.advance();
|
|
1553
|
+
const value = !this.check("RBRACE") && !this.isAtEnd() ? this.parseValue() : null;
|
|
1554
|
+
if (key === "metadata" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
1555
|
+
composition.metadata = { ...composition.metadata ?? {}, ...value };
|
|
1556
|
+
}
|
|
1557
|
+
} else if (this.check("IMPORT")) {
|
|
1443
1558
|
composition.imports.push(this.parseImport());
|
|
1444
1559
|
} else if (this.check("THEME")) {
|
|
1445
1560
|
composition.theme = this.parseTheme();
|
|
@@ -1448,7 +1563,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1448
1563
|
} else if (this.check("SCENE")) {
|
|
1449
1564
|
if (!composition.scenes) composition.scenes = [];
|
|
1450
1565
|
composition.scenes.push(this.parseScene());
|
|
1451
|
-
} else if (this.check("STATE")) {
|
|
1566
|
+
} else if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
1452
1567
|
composition.state = this.parseState();
|
|
1453
1568
|
} else if (this.check("METADATA_BLOCK")) {
|
|
1454
1569
|
this.advance();
|
|
@@ -1520,8 +1635,48 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1520
1635
|
composition.norms.push(this.parseNormBlock());
|
|
1521
1636
|
} else if (this.check("METANORM")) {
|
|
1522
1637
|
composition.metanorms.push(this.parseMetanormBlock());
|
|
1638
|
+
} else if (this.check("HOLO_CONTRACT")) {
|
|
1639
|
+
composition.contract = this.parseContractBlock();
|
|
1640
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "policy_pack") {
|
|
1641
|
+
composition.policyPacks.push(this.parsePolicyPackBlock());
|
|
1642
|
+
} else if (this.check("HOLO_TOPIC")) {
|
|
1643
|
+
if (!composition.topics) composition.topics = [];
|
|
1644
|
+
composition.topics.push(this.parseTopicBlock());
|
|
1645
|
+
} else if (this.check("HOLO_CHANNEL")) {
|
|
1646
|
+
if (!composition.channels) composition.channels = [];
|
|
1647
|
+
composition.channels.push(this.parseChannelBlock());
|
|
1648
|
+
} else if (this.check("CONNECT")) {
|
|
1649
|
+
if (!composition.connections) composition.connections = [];
|
|
1650
|
+
composition.connections.push(this.parseConnectionStmt());
|
|
1651
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "shareplay") {
|
|
1652
|
+
composition.metadata = {
|
|
1653
|
+
...composition.metadata ?? {},
|
|
1654
|
+
shareplay: this.parseSharePlayBlock()
|
|
1655
|
+
};
|
|
1656
|
+
} else if (this.check("LOOT_TABLE")) {
|
|
1657
|
+
composition.lootTables.push(this.parseLootTable());
|
|
1658
|
+
} else if (this.check("WORLD_CHUNK")) {
|
|
1659
|
+
composition.worldChunks.push(this.parseWorldChunk());
|
|
1660
|
+
} else if (this.check("SPAWN_POINT")) {
|
|
1661
|
+
composition.spawnPoints.push(this.parseSpawnPoint());
|
|
1662
|
+
} else if (this.check("GAME_TRIGGER")) {
|
|
1663
|
+
composition.triggers.push(this.parseGameTrigger());
|
|
1664
|
+
} else if (this.check("MOVEMENT_PATH")) {
|
|
1665
|
+
composition.movementPaths.push(this.parseMovementPath());
|
|
1666
|
+
} else if (this.check("REACTION_TRIGGER")) {
|
|
1667
|
+
composition.reactionTriggers.push(this.parseReactionTrigger());
|
|
1668
|
+
} else if (this.check("WORLD_LAYER")) {
|
|
1669
|
+
composition.worldLayers.push(this.parseWorldLayer());
|
|
1670
|
+
} else if (this.check("DUNGEON_INSTANCE")) {
|
|
1671
|
+
composition.dungeonInstances.push(this.parseDungeonInstance());
|
|
1672
|
+
} else if (this.check("WORLD_SHARD")) {
|
|
1673
|
+
composition.worldShards.push(this.parseWorldShard());
|
|
1674
|
+
} else if (this.check("REAL_ESTATE")) {
|
|
1675
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1523
1676
|
} else if (this.isDomainBlockToken()) {
|
|
1524
1677
|
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1678
|
+
} else if (this.isLooseDomainBlockStart() || this.isLooseNamedDomainBlockStart()) {
|
|
1679
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1525
1680
|
} else if (this.check("MODULE")) {
|
|
1526
1681
|
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1527
1682
|
} else if (this.check("AT")) {
|
|
@@ -1562,8 +1717,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1562
1717
|
} else if (decoratorName === "world" || decoratorName === "environment") {
|
|
1563
1718
|
composition.environment = this.parseEnvironmentBody();
|
|
1564
1719
|
} else if (decoratorName === "state_machine") {
|
|
1720
|
+
const name2 = this.parseOptionalStateMachineName("implicit");
|
|
1565
1721
|
if (this.check("LBRACE")) {
|
|
1566
|
-
composition.stateMachines.push(this.parseStateMachineFromDecorator());
|
|
1722
|
+
composition.stateMachines.push(this.parseStateMachineFromDecorator(name2));
|
|
1567
1723
|
}
|
|
1568
1724
|
} else {
|
|
1569
1725
|
composition.traits = composition.traits || [];
|
|
@@ -1574,6 +1730,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1574
1730
|
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
1575
1731
|
composition.actions = composition.actions || [];
|
|
1576
1732
|
composition.actions.push(this.parseAction());
|
|
1733
|
+
} else if (this.check("FUNCTION")) {
|
|
1734
|
+
this.skipFunctionDeclaration();
|
|
1577
1735
|
} else if (this.check("USING")) {
|
|
1578
1736
|
this.advance();
|
|
1579
1737
|
if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
|
|
@@ -1581,27 +1739,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1581
1739
|
this.advance();
|
|
1582
1740
|
if (this.check("IDENTIFIER")) this.advance();
|
|
1583
1741
|
}
|
|
1584
|
-
} else if (this.
|
|
1585
|
-
|
|
1586
|
-
this.advance();
|
|
1587
|
-
this.advance();
|
|
1588
|
-
while (this.check("DOT")) {
|
|
1589
|
-
this.advance();
|
|
1590
|
-
if (this.check("IDENTIFIER")) this.advance();
|
|
1591
|
-
}
|
|
1592
|
-
let parameters = [];
|
|
1593
|
-
if (this.check("LPAREN")) {
|
|
1594
|
-
parameters = this.parseParameterList();
|
|
1595
|
-
}
|
|
1596
|
-
if (this.check("LBRACE")) this.skipBlock();
|
|
1597
|
-
composition.eventHandlers = composition.eventHandlers || [];
|
|
1598
|
-
composition.eventHandlers.push({
|
|
1599
|
-
type: "EventHandler",
|
|
1600
|
-
event: eventName,
|
|
1601
|
-
parameters,
|
|
1602
|
-
body: []
|
|
1603
|
-
// Skipped body
|
|
1604
|
-
});
|
|
1742
|
+
} else if (this.isLooseOnHandlerStart()) {
|
|
1743
|
+
this.skipLooseOnHandler();
|
|
1605
1744
|
} else if (this.check("COLON")) {
|
|
1606
1745
|
this.advance();
|
|
1607
1746
|
if (!this.check("RBRACE") && !this.isAtEnd()) this.parseValue();
|
|
@@ -1630,6 +1769,10 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1630
1769
|
if (this.check("COLON")) {
|
|
1631
1770
|
this.advance();
|
|
1632
1771
|
if (!this.check("RBRACE") && !this.isAtEnd()) this.parseValue();
|
|
1772
|
+
} else if (this.check("LBRACKET")) {
|
|
1773
|
+
this.advance();
|
|
1774
|
+
while (!this.check("RBRACKET") && !this.isAtEnd()) this.advance();
|
|
1775
|
+
if (this.check("RBRACKET")) this.advance();
|
|
1633
1776
|
} else {
|
|
1634
1777
|
if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
|
|
1635
1778
|
if (this.check("LPAREN")) this.skipParens();
|
|
@@ -1778,7 +1921,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1778
1921
|
this.skipNewlines();
|
|
1779
1922
|
const properties = [];
|
|
1780
1923
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1781
|
-
this.
|
|
1924
|
+
this.skipBlockMemberSeparators();
|
|
1782
1925
|
if (this.check("RBRACE")) break;
|
|
1783
1926
|
if (this.check("PARTICLES") || this.check("PARTICLE_SYSTEM")) {
|
|
1784
1927
|
const ps = this.parseParticleSystem();
|
|
@@ -1787,15 +1930,16 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1787
1930
|
key: ps.name,
|
|
1788
1931
|
value: ps
|
|
1789
1932
|
});
|
|
1933
|
+
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
1934
|
+
const key = this.parsePropertyKey();
|
|
1935
|
+
const value = this.parseBlockTraitConfig();
|
|
1936
|
+
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1790
1937
|
} else {
|
|
1791
|
-
const key = this.
|
|
1938
|
+
const key = this.parsePropertyKey();
|
|
1792
1939
|
this.expect("COLON");
|
|
1793
1940
|
const value = this.parseValue();
|
|
1794
1941
|
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1795
1942
|
}
|
|
1796
|
-
if (this.check("SEMICOLON")) {
|
|
1797
|
-
this.advance();
|
|
1798
|
-
}
|
|
1799
1943
|
this.skipNewlines();
|
|
1800
1944
|
}
|
|
1801
1945
|
this.expect("RBRACE");
|
|
@@ -1825,14 +1969,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1825
1969
|
let environment;
|
|
1826
1970
|
const objects = [];
|
|
1827
1971
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1828
|
-
this.
|
|
1972
|
+
this.skipBlockMemberSeparators();
|
|
1829
1973
|
if (this.check("RBRACE")) break;
|
|
1830
1974
|
if (this.check("ENVIRONMENT")) {
|
|
1831
1975
|
environment = this.parseEnvironment();
|
|
1832
1976
|
} else if (this.check("OBJECT")) {
|
|
1833
1977
|
objects.push(this.parseObject());
|
|
1978
|
+
} else if (this.check("LBRACE")) {
|
|
1979
|
+
this.skipBlock();
|
|
1834
1980
|
} else {
|
|
1835
1981
|
this.advance();
|
|
1982
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
|
|
1983
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
1984
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
1836
1985
|
}
|
|
1837
1986
|
}
|
|
1838
1987
|
this.expect("RBRACE");
|
|
@@ -1856,7 +2005,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1856
2005
|
this.skipNewlines();
|
|
1857
2006
|
const properties = {};
|
|
1858
2007
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1859
|
-
this.
|
|
2008
|
+
this.skipBlockMemberSeparators();
|
|
1860
2009
|
if (this.check("RBRACE")) break;
|
|
1861
2010
|
const key = this.expectIdentifier();
|
|
1862
2011
|
this.expect("COLON");
|
|
@@ -1894,24 +2043,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1894
2043
|
this.advance();
|
|
1895
2044
|
}
|
|
1896
2045
|
}
|
|
2046
|
+
const inlineTraitProperties = [];
|
|
2047
|
+
while (this.check("AT")) {
|
|
2048
|
+
inlineTraitProperties.push(this.parseTraitAsLightProperty(true));
|
|
2049
|
+
}
|
|
1897
2050
|
this.expect("LBRACE");
|
|
1898
2051
|
this.skipNewlines();
|
|
1899
|
-
const properties = [];
|
|
2052
|
+
const properties = [...inlineTraitProperties];
|
|
1900
2053
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1901
|
-
this.
|
|
2054
|
+
this.skipBlockMemberSeparators();
|
|
1902
2055
|
if (this.check("RBRACE")) break;
|
|
1903
2056
|
if (this.check("AT")) {
|
|
1904
|
-
this.
|
|
1905
|
-
const traitName = this.parseTraitName();
|
|
1906
|
-
const cfg = this.parseOptionalTraitConfig();
|
|
1907
|
-
const cfgKeys = Object.keys(cfg);
|
|
1908
|
-
let traitValue;
|
|
1909
|
-
if (cfgKeys.length === 0) traitValue = true;
|
|
1910
|
-
else if (cfgKeys.every((k) => /^_arg\d+$/.test(k))) {
|
|
1911
|
-
const arr = cfgKeys.sort().map((k) => cfg[k]);
|
|
1912
|
-
traitValue = arr.length === 1 ? arr[0] : arr;
|
|
1913
|
-
} else traitValue = cfg;
|
|
1914
|
-
properties.push({ type: "LightProperty", key: traitName, value: traitValue });
|
|
2057
|
+
properties.push(this.parseTraitAsLightProperty());
|
|
1915
2058
|
this.skipNewlines();
|
|
1916
2059
|
continue;
|
|
1917
2060
|
}
|
|
@@ -1947,6 +2090,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1947
2090
|
properties
|
|
1948
2091
|
};
|
|
1949
2092
|
}
|
|
2093
|
+
parseTraitAsLightProperty(requireBodyAfterBareBrace = false) {
|
|
2094
|
+
this.expect("AT");
|
|
2095
|
+
const traitName = this.parseTraitName();
|
|
2096
|
+
const cfg = this.parseOptionalTraitConfig(requireBodyAfterBareBrace);
|
|
2097
|
+
const cfgKeys = Object.keys(cfg);
|
|
2098
|
+
let traitValue;
|
|
2099
|
+
if (cfgKeys.length === 0) traitValue = true;
|
|
2100
|
+
else if (cfgKeys.every((k) => /^_arg\d+$/.test(k))) {
|
|
2101
|
+
const arr = cfgKeys.sort().map((k) => cfg[k]);
|
|
2102
|
+
traitValue = arr.length === 1 ? arr[0] : arr;
|
|
2103
|
+
} else traitValue = cfg;
|
|
2104
|
+
return { type: "LightProperty", key: traitName, value: traitValue };
|
|
2105
|
+
}
|
|
1950
2106
|
// ===========================================================================
|
|
1951
2107
|
// EFFECTS (post-processing block)
|
|
1952
2108
|
// ===========================================================================
|
|
@@ -1957,14 +2113,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1957
2113
|
this.skipNewlines();
|
|
1958
2114
|
const effects = [];
|
|
1959
2115
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1960
|
-
this.
|
|
2116
|
+
this.skipBlockMemberSeparators();
|
|
1961
2117
|
if (this.check("RBRACE")) break;
|
|
1962
2118
|
const effectType = this.expectIdentifier();
|
|
1963
2119
|
this.expect("LBRACE");
|
|
1964
2120
|
this.skipNewlines();
|
|
1965
2121
|
const properties = {};
|
|
1966
2122
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1967
|
-
this.
|
|
2123
|
+
this.skipBlockMemberSeparators();
|
|
1968
2124
|
if (this.check("RBRACE")) break;
|
|
1969
2125
|
const key = this.expectIdentifier();
|
|
1970
2126
|
this.expect("COLON");
|
|
@@ -2006,7 +2162,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2006
2162
|
this.skipNewlines();
|
|
2007
2163
|
const properties = [];
|
|
2008
2164
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2009
|
-
this.
|
|
2165
|
+
this.skipBlockMemberSeparators();
|
|
2010
2166
|
if (this.check("RBRACE")) break;
|
|
2011
2167
|
if (this.check("AT")) {
|
|
2012
2168
|
this.advance();
|
|
@@ -2047,7 +2203,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2047
2203
|
let autoplay;
|
|
2048
2204
|
let loop;
|
|
2049
2205
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2050
|
-
this.
|
|
2206
|
+
this.skipBlockMemberSeparators();
|
|
2051
2207
|
if (this.check("RBRACE")) break;
|
|
2052
2208
|
if (this.check("IDENTIFIER") && (this.current().value === "autoplay" || this.current().value === "loop")) {
|
|
2053
2209
|
const key = this.advance().value;
|
|
@@ -2086,7 +2242,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2086
2242
|
this.skipNewlines();
|
|
2087
2243
|
const properties = {};
|
|
2088
2244
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2089
|
-
this.
|
|
2245
|
+
this.skipBlockMemberSeparators();
|
|
2090
2246
|
if (this.check("RBRACE")) break;
|
|
2091
2247
|
const key = this.expectIdentifier();
|
|
2092
2248
|
this.expect("COLON");
|
|
@@ -2131,7 +2287,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2131
2287
|
this.skipNewlines();
|
|
2132
2288
|
const properties = [];
|
|
2133
2289
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2134
|
-
this.
|
|
2290
|
+
this.skipBlockMemberSeparators();
|
|
2135
2291
|
if (this.check("RBRACE")) break;
|
|
2136
2292
|
if (this.check("AT")) {
|
|
2137
2293
|
this.advance();
|
|
@@ -2170,7 +2326,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2170
2326
|
const properties = [];
|
|
2171
2327
|
const handlers = [];
|
|
2172
2328
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2173
|
-
this.
|
|
2329
|
+
this.skipBlockMemberSeparators();
|
|
2174
2330
|
if (this.check("RBRACE")) break;
|
|
2175
2331
|
if (this.check("IDENTIFIER") && this.current().value.startsWith("on_")) {
|
|
2176
2332
|
const event = this.advance().value;
|
|
@@ -2210,7 +2366,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2210
2366
|
this.skipNewlines();
|
|
2211
2367
|
const elements = [];
|
|
2212
2368
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2213
|
-
this.
|
|
2369
|
+
this.skipBlockMemberSeparators();
|
|
2214
2370
|
if (this.check("RBRACE")) break;
|
|
2215
2371
|
if (this.check("ELEMENT")) {
|
|
2216
2372
|
elements.push(this.parseUIElement());
|
|
@@ -2235,7 +2391,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2235
2391
|
this.skipNewlines();
|
|
2236
2392
|
const properties = [];
|
|
2237
2393
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2238
|
-
this.
|
|
2394
|
+
this.skipBlockMemberSeparators();
|
|
2239
2395
|
if (this.check("RBRACE")) break;
|
|
2240
2396
|
const key = this.expectIdentifier();
|
|
2241
2397
|
this.expect("COLON");
|
|
@@ -2262,7 +2418,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2262
2418
|
this.skipNewlines();
|
|
2263
2419
|
const properties = [];
|
|
2264
2420
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2265
|
-
this.
|
|
2421
|
+
this.skipBlockMemberSeparators();
|
|
2266
2422
|
if (this.check("RBRACE")) break;
|
|
2267
2423
|
const key = this.expectIdentifier();
|
|
2268
2424
|
this.expect("COLON");
|
|
@@ -2396,7 +2552,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2396
2552
|
this.skipNewlines();
|
|
2397
2553
|
const properties = [];
|
|
2398
2554
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2399
|
-
this.
|
|
2555
|
+
this.skipBlockMemberSeparators();
|
|
2400
2556
|
if (this.check("RBRACE")) break;
|
|
2401
2557
|
const key = this.expectIdentifier();
|
|
2402
2558
|
this.expect("COLON");
|
|
@@ -2431,11 +2587,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2431
2587
|
// Initialize directives
|
|
2432
2588
|
};
|
|
2433
2589
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2434
|
-
this.
|
|
2590
|
+
this.skipBlockMemberSeparators();
|
|
2435
2591
|
if (this.check("RBRACE")) break;
|
|
2436
|
-
if (this.check("STATE")) {
|
|
2592
|
+
if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
2437
2593
|
template.state = this.parseState();
|
|
2438
|
-
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
2594
|
+
} else if (this.check("ACTION") && this.peek(1).type !== "COLON" || this.check("ASYNC")) {
|
|
2439
2595
|
const action = this.parseAction();
|
|
2440
2596
|
template.actions.push(action);
|
|
2441
2597
|
template.directives.push({
|
|
@@ -2500,7 +2656,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2500
2656
|
body: []
|
|
2501
2657
|
});
|
|
2502
2658
|
} else if (this.isPropertyName() && this.peek(1).type === "LPAREN") {
|
|
2503
|
-
const methodName = this.
|
|
2659
|
+
const methodName = this.parsePropertyKey();
|
|
2504
2660
|
this.skipParens();
|
|
2505
2661
|
if (this.check("LBRACE")) {
|
|
2506
2662
|
this.skipBlock();
|
|
@@ -2512,7 +2668,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2512
2668
|
});
|
|
2513
2669
|
}
|
|
2514
2670
|
} else if (this.isPropertyName() && (this.peek(1).type === "IDENTIFIER" || this.peek(1).type === "STRING")) {
|
|
2515
|
-
const blockType = this.
|
|
2671
|
+
const blockType = this.parsePropertyKey();
|
|
2516
2672
|
const blockName = this.check("STRING") ? this.advance().value : this.expectIdentifier();
|
|
2517
2673
|
if (this.check("LPAREN")) {
|
|
2518
2674
|
this.skipParens();
|
|
@@ -2527,7 +2683,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2527
2683
|
});
|
|
2528
2684
|
}
|
|
2529
2685
|
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
2530
|
-
const blockType = this.
|
|
2686
|
+
const blockType = this.parsePropertyKey();
|
|
2531
2687
|
if (this.check("LBRACE")) {
|
|
2532
2688
|
this.skipBlock();
|
|
2533
2689
|
template.directives.push({
|
|
@@ -2538,12 +2694,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2538
2694
|
});
|
|
2539
2695
|
}
|
|
2540
2696
|
} else {
|
|
2541
|
-
const key = this.
|
|
2697
|
+
const key = this.parsePropertyKey();
|
|
2542
2698
|
this.expect("COLON");
|
|
2543
2699
|
const value = this.parseValue();
|
|
2544
2700
|
template.properties.push({ type: "TemplateProperty", key, value });
|
|
2545
2701
|
}
|
|
2546
|
-
this.
|
|
2702
|
+
this.skipBlockMemberSeparators();
|
|
2547
2703
|
}
|
|
2548
2704
|
this.expect("RBRACE");
|
|
2549
2705
|
template.loc = { start: startLoc, end: this.currentLocation() };
|
|
@@ -2563,8 +2719,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2563
2719
|
let name = "";
|
|
2564
2720
|
if (this.check("STRING")) {
|
|
2565
2721
|
name = this.expectString();
|
|
2566
|
-
} else if (this.
|
|
2567
|
-
name = this.
|
|
2722
|
+
} else if (this.isObjectNameToken()) {
|
|
2723
|
+
name = this.advance().value;
|
|
2568
2724
|
} else if (typeOverride === "behavior" && this.check("LBRACE")) {
|
|
2569
2725
|
name = "behavior";
|
|
2570
2726
|
} else {
|
|
@@ -2598,14 +2754,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2598
2754
|
const directives = [];
|
|
2599
2755
|
let state;
|
|
2600
2756
|
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
2601
|
-
this.
|
|
2757
|
+
this.skipBlockMemberSeparators();
|
|
2602
2758
|
if (this.check("RBRACE")) break;
|
|
2603
|
-
if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") || this.current().type.startsWith("UI_")) {
|
|
2759
|
+
if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") && this.peek(1).type !== "COLON" || this.current().type.startsWith("UI_")) {
|
|
2604
2760
|
const nestedType = this.check("OBJECT") ? void 0 : this.current().value.toLowerCase();
|
|
2605
2761
|
children.push(this.parseObject(nestedType));
|
|
2606
2762
|
} else if (this.check("SUB_ORB")) {
|
|
2607
2763
|
subOrbs.push(this.parseSubOrb());
|
|
2608
|
-
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
2764
|
+
} else if (this.check("ACTION") && this.peek(1).type !== "COLON" || this.check("ASYNC")) {
|
|
2609
2765
|
const action = this.parseAction();
|
|
2610
2766
|
directives.push({
|
|
2611
2767
|
type: "method",
|
|
@@ -2656,7 +2812,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2656
2812
|
config: config2,
|
|
2657
2813
|
platformConstraint: constraint
|
|
2658
2814
|
});
|
|
2659
|
-
} else if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") || this.current().type.startsWith("UI_")) {
|
|
2815
|
+
} else if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") && this.peek(1).type !== "COLON" || this.current().type.startsWith("UI_")) {
|
|
2660
2816
|
const nestedType = this.check("OBJECT") ? void 0 : this.current().value.toLowerCase();
|
|
2661
2817
|
const child = this.parseObject(nestedType);
|
|
2662
2818
|
child.platformConstraint = constraint;
|
|
@@ -2669,7 +2825,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2669
2825
|
const trait = { type: "ObjectTrait", name: traitName, config };
|
|
2670
2826
|
traits.push(trait);
|
|
2671
2827
|
directives.push({ type: "trait", name: traitName, config });
|
|
2672
|
-
} else if (this.check("STATE")) {
|
|
2828
|
+
} else if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
2673
2829
|
state = this.parseState();
|
|
2674
2830
|
} else if (this.isDomainBlockToken() && this.peek(1).type !== "COLON") {
|
|
2675
2831
|
const domainBlock = this.parseDomainBlock();
|
|
@@ -2681,7 +2837,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2681
2837
|
const physicsValue = this.parseValue();
|
|
2682
2838
|
properties.push({ type: "ObjectProperty", key, value: physicsValue });
|
|
2683
2839
|
} else if (this.isPropertyName()) {
|
|
2684
|
-
const key = this.
|
|
2840
|
+
const key = this.parsePropertyKey();
|
|
2685
2841
|
if (this.check("COLON")) {
|
|
2686
2842
|
this.advance();
|
|
2687
2843
|
if (this.check("LBRACE")) {
|
|
@@ -2715,7 +2871,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2715
2871
|
if (this.check("LPAREN")) this.skipParens();
|
|
2716
2872
|
let parsedBody = "";
|
|
2717
2873
|
if (this.check("LBRACE")) {
|
|
2718
|
-
|
|
2874
|
+
if (key === "on" || key.startsWith("on_") || /^on[A-Z]/.test(key)) {
|
|
2875
|
+
this.skipBlock();
|
|
2876
|
+
} else {
|
|
2877
|
+
parsedBody = this.parseBlockTraitConfig();
|
|
2878
|
+
}
|
|
2719
2879
|
}
|
|
2720
2880
|
directives.push({ type: key, name: blockName, parameters: [], body: parsedBody });
|
|
2721
2881
|
} else if (this.check("LBRACE")) {
|
|
@@ -2863,6 +3023,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2863
3023
|
this.expect("LBRACE");
|
|
2864
3024
|
this.skipNewlines();
|
|
2865
3025
|
const objects = [];
|
|
3026
|
+
const lights = [];
|
|
2866
3027
|
const groups = [];
|
|
2867
3028
|
const body = [];
|
|
2868
3029
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
@@ -2870,6 +3031,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2870
3031
|
if (this.check("RBRACE")) break;
|
|
2871
3032
|
if (this.check("OBJECT")) {
|
|
2872
3033
|
objects.push(this.parseObject());
|
|
3034
|
+
} else if (this.check("LIGHT")) {
|
|
3035
|
+
lights.push(this.parseLight());
|
|
2873
3036
|
} else if (this.check("SPATIAL_GROUP")) {
|
|
2874
3037
|
groups.push(this.parseSpatialGroup());
|
|
2875
3038
|
} else if (this.check("TEMPLATE")) {
|
|
@@ -2922,6 +3085,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2922
3085
|
name,
|
|
2923
3086
|
properties,
|
|
2924
3087
|
objects,
|
|
3088
|
+
lights: lights.length > 0 ? lights : void 0,
|
|
2925
3089
|
groups: groups.length > 0 ? groups : void 0,
|
|
2926
3090
|
body: body.length > 0 ? body : void 0
|
|
2927
3091
|
};
|
|
@@ -2941,6 +3105,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2941
3105
|
if (this.check("RBRACE")) break;
|
|
2942
3106
|
if (this.check("ACTION") || this.check("ASYNC")) {
|
|
2943
3107
|
actions.push(this.parseAction());
|
|
3108
|
+
} else if (this.check("FUNCTION")) {
|
|
3109
|
+
this.skipFunctionDeclaration();
|
|
3110
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on" && (this.peek(1).type === "STRING" || this.peek(1).type === "IDENTIFIER")) {
|
|
3111
|
+
this.advance();
|
|
3112
|
+
const event = this.advance().value;
|
|
3113
|
+
const parameters = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
3114
|
+
if (this.check("LBRACE")) {
|
|
3115
|
+
this.skipBlock();
|
|
3116
|
+
handlers.push({ type: "EventHandler", event, parameters, body: [] });
|
|
3117
|
+
} else {
|
|
3118
|
+
handlers.push({ type: "EventHandler", event, parameters, body: [] });
|
|
3119
|
+
}
|
|
2944
3120
|
} else if (this.check("IDENTIFIER")) {
|
|
2945
3121
|
const name = this.advance().value;
|
|
2946
3122
|
if (this.check("IDENTIFIER")) {
|
|
@@ -3321,6 +3497,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3321
3497
|
isKeywordAsIdentifier() {
|
|
3322
3498
|
return isKeywordAsIdentifier(this._exprApi);
|
|
3323
3499
|
}
|
|
3500
|
+
isObjectNameToken() {
|
|
3501
|
+
const type = this.current().type;
|
|
3502
|
+
if (type === "IDENTIFIER") return true;
|
|
3503
|
+
if (type === "OBJECT") return false;
|
|
3504
|
+
return this.isKeywordAsIdentifierType(type);
|
|
3505
|
+
}
|
|
3324
3506
|
// ===========================================================================
|
|
3325
3507
|
// VALUES
|
|
3326
3508
|
// ===========================================================================
|
|
@@ -3348,14 +3530,22 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3348
3530
|
return this.parseBindValue();
|
|
3349
3531
|
}
|
|
3350
3532
|
if (this.match("AT")) {
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
}
|
|
3533
|
+
const traitName = this.parseTraitName();
|
|
3534
|
+
if (traitName) return `@${traitName}`;
|
|
3354
3535
|
this.error(`Expected trait name after '@', got ${this.current().type}`);
|
|
3355
3536
|
return null;
|
|
3356
3537
|
}
|
|
3357
|
-
if (this.match("
|
|
3358
|
-
return this.
|
|
3538
|
+
if (this.match("HASH")) {
|
|
3539
|
+
return this.parseHashLiteral();
|
|
3540
|
+
}
|
|
3541
|
+
if (this.check("ENUM")) {
|
|
3542
|
+
return this.parseEnumTypeSpec();
|
|
3543
|
+
}
|
|
3544
|
+
if (this.check("FUNCTION")) {
|
|
3545
|
+
return this.parseFunctionValue();
|
|
3546
|
+
}
|
|
3547
|
+
if (this.isBarewordPathToken()) {
|
|
3548
|
+
return this.parseBarewordPathValue();
|
|
3359
3549
|
}
|
|
3360
3550
|
if (this.match("LBRACKET")) {
|
|
3361
3551
|
return this.parseArrayValue();
|
|
@@ -3363,13 +3553,148 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3363
3553
|
if (this.match("LBRACE")) {
|
|
3364
3554
|
return this.parseObjectValue();
|
|
3365
3555
|
}
|
|
3366
|
-
if (_HoloCompositionParser.DOMAIN_TOKENS.has(this.current().type) || this.isKeywordAsIdentifierType(this.current().type)) {
|
|
3367
|
-
return this.advance().value;
|
|
3368
|
-
}
|
|
3369
3556
|
this.error(`Expected value, got ${this.current().type}`);
|
|
3370
3557
|
this.advance();
|
|
3371
3558
|
return null;
|
|
3372
3559
|
}
|
|
3560
|
+
/**
|
|
3561
|
+
* Parse an `enum(...)` type-spec expression, e.g.:
|
|
3562
|
+
* enum("button" | "slider" | "checkbox")
|
|
3563
|
+
*
|
|
3564
|
+
* Returns the canonical string representation so trait loaders and schema
|
|
3565
|
+
* emitters can read it as a type annotation. Called from parseValue() when
|
|
3566
|
+
* the current token is ENUM (the keyword `enum` tokenized as 'ENUM' rather
|
|
3567
|
+
* than 'IDENTIFIER').
|
|
3568
|
+
*
|
|
3569
|
+
* The opening `enum` token is consumed here. The caller should check for a
|
|
3570
|
+
* trailing `= defaultValue` if the context supports it (e.g. parseObjectValue).
|
|
3571
|
+
*/
|
|
3572
|
+
parseEnumTypeSpec() {
|
|
3573
|
+
this.advance();
|
|
3574
|
+
let spec = "enum";
|
|
3575
|
+
if (this.check("LPAREN")) {
|
|
3576
|
+
spec += this.parseParenthesizedLiteral();
|
|
3577
|
+
}
|
|
3578
|
+
return spec;
|
|
3579
|
+
}
|
|
3580
|
+
parseFunctionValue() {
|
|
3581
|
+
this.expect("FUNCTION");
|
|
3582
|
+
let name = "";
|
|
3583
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) {
|
|
3584
|
+
name = this.advance().value;
|
|
3585
|
+
}
|
|
3586
|
+
const params = this.check("LPAREN") ? this.collectFunctionParameterNames() : [];
|
|
3587
|
+
if (this.check("LBRACE")) {
|
|
3588
|
+
this.skipBlock();
|
|
3589
|
+
}
|
|
3590
|
+
return {
|
|
3591
|
+
type: "FunctionValue",
|
|
3592
|
+
name,
|
|
3593
|
+
params
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
skipFunctionDeclaration() {
|
|
3597
|
+
this.expect("FUNCTION");
|
|
3598
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) {
|
|
3599
|
+
this.advance();
|
|
3600
|
+
}
|
|
3601
|
+
if (this.check("LPAREN")) {
|
|
3602
|
+
this.skipParens();
|
|
3603
|
+
}
|
|
3604
|
+
if (this.check("LBRACE")) {
|
|
3605
|
+
this.skipBlock();
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
collectFunctionParameterNames() {
|
|
3609
|
+
const params = [];
|
|
3610
|
+
if (!this.check("LPAREN")) return params;
|
|
3611
|
+
this.advance();
|
|
3612
|
+
let parenDepth = 1;
|
|
3613
|
+
while (parenDepth > 0 && !this.isAtEnd()) {
|
|
3614
|
+
if (this.check("LPAREN")) {
|
|
3615
|
+
parenDepth++;
|
|
3616
|
+
this.advance();
|
|
3617
|
+
continue;
|
|
3618
|
+
}
|
|
3619
|
+
if (this.check("RPAREN")) {
|
|
3620
|
+
parenDepth--;
|
|
3621
|
+
this.advance();
|
|
3622
|
+
continue;
|
|
3623
|
+
}
|
|
3624
|
+
if (parenDepth === 1 && this.check("IDENTIFIER")) {
|
|
3625
|
+
params.push(this.advance().value);
|
|
3626
|
+
continue;
|
|
3627
|
+
}
|
|
3628
|
+
this.advance();
|
|
3629
|
+
}
|
|
3630
|
+
return params;
|
|
3631
|
+
}
|
|
3632
|
+
isBarewordPathToken(token = this.current()) {
|
|
3633
|
+
const type = token.type;
|
|
3634
|
+
return type === "IDENTIFIER" || type === "STATE" || _HoloCompositionParser.DOMAIN_TOKENS.has(type) || this.isKeywordAsIdentifierType(type);
|
|
3635
|
+
}
|
|
3636
|
+
parseBarewordPathValue() {
|
|
3637
|
+
let value = this.advance().value;
|
|
3638
|
+
while (this.match("DOT")) {
|
|
3639
|
+
if (!this.isBarewordPathToken()) {
|
|
3640
|
+
this.error(`Expected identifier after '.', got ${this.current().type}`);
|
|
3641
|
+
break;
|
|
3642
|
+
}
|
|
3643
|
+
value += `.${this.advance().value}`;
|
|
3644
|
+
}
|
|
3645
|
+
while (this.check("COLON") && this.isBarewordPathToken(this.peek(1))) {
|
|
3646
|
+
this.advance();
|
|
3647
|
+
value += `:${this.advance().value}`;
|
|
3648
|
+
}
|
|
3649
|
+
if (this.match("LESS")) {
|
|
3650
|
+
value += "<";
|
|
3651
|
+
let depth = 1;
|
|
3652
|
+
while (depth > 0 && !this.isAtEnd()) {
|
|
3653
|
+
if (this.check("LESS")) {
|
|
3654
|
+
depth++;
|
|
3655
|
+
value += this.advance().value;
|
|
3656
|
+
continue;
|
|
3657
|
+
}
|
|
3658
|
+
if (this.check("GREATER")) {
|
|
3659
|
+
depth--;
|
|
3660
|
+
this.advance();
|
|
3661
|
+
value += ">";
|
|
3662
|
+
if (depth === 0) break;
|
|
3663
|
+
continue;
|
|
3664
|
+
}
|
|
3665
|
+
value += this.advance().value;
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
if (this.check("LPAREN")) {
|
|
3669
|
+
value += this.parseParenthesizedLiteral();
|
|
3670
|
+
}
|
|
3671
|
+
return value;
|
|
3672
|
+
}
|
|
3673
|
+
parseHashLiteral() {
|
|
3674
|
+
let value = "#";
|
|
3675
|
+
while (!this.isAtEnd()) {
|
|
3676
|
+
if (this.check("IDENTIFIER") || this.check("NUMBER") || this.check("MINUS") || this.check("DOT")) {
|
|
3677
|
+
value += this.advance().value;
|
|
3678
|
+
continue;
|
|
3679
|
+
}
|
|
3680
|
+
break;
|
|
3681
|
+
}
|
|
3682
|
+
return value;
|
|
3683
|
+
}
|
|
3684
|
+
parseParenthesizedLiteral() {
|
|
3685
|
+
let value = "";
|
|
3686
|
+
if (!this.check("LPAREN")) return value;
|
|
3687
|
+
let depth = 0;
|
|
3688
|
+
while (!this.isAtEnd()) {
|
|
3689
|
+
const token = this.current();
|
|
3690
|
+
if (token.type === "LPAREN") depth++;
|
|
3691
|
+
if (token.type === "RPAREN") depth--;
|
|
3692
|
+
value += token.type === "STRING" ? `"${token.value}"` : token.value;
|
|
3693
|
+
this.advance();
|
|
3694
|
+
if (depth === 0) break;
|
|
3695
|
+
}
|
|
3696
|
+
return value;
|
|
3697
|
+
}
|
|
3373
3698
|
parseBindValue() {
|
|
3374
3699
|
this.expect("BIND");
|
|
3375
3700
|
this.expect("LPAREN");
|
|
@@ -3395,9 +3720,10 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3395
3720
|
const elements = [];
|
|
3396
3721
|
while (!this.check("RBRACKET") && !this.isAtEnd()) {
|
|
3397
3722
|
this.skipNewlines();
|
|
3723
|
+
if (this.check("RBRACKET")) break;
|
|
3398
3724
|
elements.push(this.parseValue());
|
|
3399
3725
|
this.skipNewlines();
|
|
3400
|
-
|
|
3726
|
+
this.match("COMMA");
|
|
3401
3727
|
this.skipNewlines();
|
|
3402
3728
|
}
|
|
3403
3729
|
this.skipNewlines();
|
|
@@ -3408,13 +3734,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3408
3734
|
this.skipNewlines();
|
|
3409
3735
|
const obj = {};
|
|
3410
3736
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3411
|
-
this.
|
|
3737
|
+
this.skipBlockMemberSeparators();
|
|
3412
3738
|
if (this.check("RBRACE")) break;
|
|
3413
|
-
this.
|
|
3414
|
-
|
|
3415
|
-
const key = this.expectIdentifier();
|
|
3739
|
+
if (this.isPropertyAssignmentStart()) {
|
|
3740
|
+
const key = this.parsePropertyKey();
|
|
3416
3741
|
this.expect("COLON");
|
|
3417
3742
|
obj[key] = this.parseValue();
|
|
3743
|
+
if (this.match("EQUALS")) {
|
|
3744
|
+
this.parseValue();
|
|
3745
|
+
}
|
|
3418
3746
|
} else if (this.check("RBRACE")) {
|
|
3419
3747
|
break;
|
|
3420
3748
|
} else {
|
|
@@ -3497,7 +3825,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3497
3825
|
this.skipNewlines();
|
|
3498
3826
|
const properties = [];
|
|
3499
3827
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3500
|
-
this.
|
|
3828
|
+
this.skipBlockMemberSeparators();
|
|
3501
3829
|
if (this.check("RBRACE")) break;
|
|
3502
3830
|
const key = this.expectIdentifier();
|
|
3503
3831
|
this.expect("COLON");
|
|
@@ -3538,6 +3866,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3538
3866
|
"QUEST",
|
|
3539
3867
|
"ABILITY",
|
|
3540
3868
|
"DIALOGUE",
|
|
3869
|
+
"BEHAVIOR",
|
|
3541
3870
|
"SHAPE",
|
|
3542
3871
|
"IMPORT",
|
|
3543
3872
|
"USING",
|
|
@@ -3556,10 +3885,42 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3556
3885
|
"WAYPOINTS",
|
|
3557
3886
|
"CONSTRAINT",
|
|
3558
3887
|
"TERRAIN",
|
|
3559
|
-
"PARTICLES"
|
|
3888
|
+
"PARTICLES",
|
|
3889
|
+
"METADATA_BLOCK",
|
|
3890
|
+
"HOLO_TOPIC",
|
|
3891
|
+
"HOLO_CHANNEL",
|
|
3892
|
+
"CONNECT",
|
|
3893
|
+
"BIND"
|
|
3560
3894
|
];
|
|
3561
3895
|
return validPropertyKeywords.includes(type);
|
|
3562
3896
|
}
|
|
3897
|
+
isPropertyNameToken(token) {
|
|
3898
|
+
return token.type === "IDENTIFIER" || _HoloCompositionParser.DOMAIN_TOKENS.has(token.type) || this.isKeywordAsIdentifierType(token.type);
|
|
3899
|
+
}
|
|
3900
|
+
isPropertyAssignmentStart() {
|
|
3901
|
+
if (!this.isPropertyName()) return false;
|
|
3902
|
+
let index = this.pos + 1;
|
|
3903
|
+
if (this.tokens[index]?.type === "QUESTION") index++;
|
|
3904
|
+
while (this.tokens[index]?.type === "DOT" && this.isPropertyNameToken(this.tokens[index + 1])) {
|
|
3905
|
+
index += 2;
|
|
3906
|
+
if (this.tokens[index]?.type === "QUESTION") index++;
|
|
3907
|
+
}
|
|
3908
|
+
return this.tokens[index]?.type === "COLON";
|
|
3909
|
+
}
|
|
3910
|
+
parsePropertyKey() {
|
|
3911
|
+
const parts = [];
|
|
3912
|
+
parts.push(this.isPropertyName() ? this.advance().value : this.expectIdentifier());
|
|
3913
|
+
while (this.match("DOT")) {
|
|
3914
|
+
if (!this.isPropertyName()) {
|
|
3915
|
+
this.error(`Expected identifier after '.', got ${this.current().type}`);
|
|
3916
|
+
break;
|
|
3917
|
+
}
|
|
3918
|
+
parts.push(this.advance().value);
|
|
3919
|
+
}
|
|
3920
|
+
let key = parts.join(".");
|
|
3921
|
+
if (this.match("QUESTION")) key += "?";
|
|
3922
|
+
return key;
|
|
3923
|
+
}
|
|
3563
3924
|
/**
|
|
3564
3925
|
* Parse primitive#id or primitive #id { } syntax
|
|
3565
3926
|
* Examples:
|
|
@@ -3597,15 +3958,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3597
3958
|
this.expect("LBRACE");
|
|
3598
3959
|
this.skipNewlines();
|
|
3599
3960
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3600
|
-
this.
|
|
3961
|
+
this.skipBlockMemberSeparators();
|
|
3601
3962
|
if (this.check("RBRACE")) break;
|
|
3602
3963
|
if (this.check("AT")) {
|
|
3603
3964
|
this.advance();
|
|
3604
3965
|
const name = this.parseTraitName();
|
|
3605
3966
|
const config = this.parseOptionalTraitConfig();
|
|
3606
3967
|
traits.push({ type: "ObjectTrait", name, config });
|
|
3607
|
-
} else if (this.
|
|
3608
|
-
const key = this.
|
|
3968
|
+
} else if (this.isPropertyName()) {
|
|
3969
|
+
const key = this.parsePropertyKey();
|
|
3609
3970
|
if (this.check("COLON")) {
|
|
3610
3971
|
this.advance();
|
|
3611
3972
|
properties.push({ type: "ObjectProperty", key, value: this.parseValue() });
|
|
@@ -3741,6 +4102,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3741
4102
|
while (this.match("NEWLINE")) {
|
|
3742
4103
|
}
|
|
3743
4104
|
}
|
|
4105
|
+
skipBlockMemberSeparators() {
|
|
4106
|
+
this.skipNewlines();
|
|
4107
|
+
while (this.matchBlockMemberSeparator()) {
|
|
4108
|
+
this.skipNewlines();
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
matchBlockMemberSeparator() {
|
|
4112
|
+
return this.match("COMMA") || this.match("SEMICOLON");
|
|
4113
|
+
}
|
|
3744
4114
|
currentLocation() {
|
|
3745
4115
|
const token = this.current();
|
|
3746
4116
|
return { line: token.line, column: token.column };
|
|
@@ -3828,16 +4198,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3828
4198
|
while (!this.check("RPAREN") && !this.check("EOF")) {
|
|
3829
4199
|
this.skipNewlines();
|
|
3830
4200
|
if (this.check("RPAREN")) break;
|
|
3831
|
-
if (!this.
|
|
4201
|
+
if (!this.isPropertyAssignmentStart()) {
|
|
3832
4202
|
config[`_arg${argIndex++}`] = this.parseValue();
|
|
3833
4203
|
} else {
|
|
3834
|
-
const key = this.
|
|
4204
|
+
const key = this.parsePropertyKey();
|
|
3835
4205
|
this.expect("COLON");
|
|
3836
4206
|
config[key] = this.parseValue();
|
|
3837
4207
|
}
|
|
3838
|
-
|
|
3839
|
-
this.advance();
|
|
3840
|
-
}
|
|
4208
|
+
this.matchBlockMemberSeparator();
|
|
3841
4209
|
this.skipNewlines();
|
|
3842
4210
|
}
|
|
3843
4211
|
this.expect("RPAREN");
|
|
@@ -3848,19 +4216,128 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3848
4216
|
this.skipNewlines();
|
|
3849
4217
|
const config = {};
|
|
3850
4218
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3851
|
-
this.
|
|
4219
|
+
this.skipBlockMemberSeparators();
|
|
3852
4220
|
if (this.check("RBRACE")) break;
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
if (this.check("
|
|
4221
|
+
if (this.isNamedOrTraitedPropertyBlockStart()) {
|
|
4222
|
+
const { key, value } = this.parseNamedOrTraitedPropertyBlock();
|
|
4223
|
+
config[key] = value;
|
|
4224
|
+
} else if (this.check("AT")) {
|
|
3857
4225
|
this.advance();
|
|
4226
|
+
const traitName = this.parseTraitName();
|
|
4227
|
+
if (traitName) {
|
|
4228
|
+
config[`@${traitName}`] = this.parseOptionalTraitConfig();
|
|
4229
|
+
}
|
|
4230
|
+
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
4231
|
+
const nestedKey = this.parsePropertyKey();
|
|
4232
|
+
config[nestedKey] = this.parseBlockTraitConfig();
|
|
4233
|
+
} else {
|
|
4234
|
+
const key = this.parsePropertyKey();
|
|
4235
|
+
this.expect("COLON");
|
|
4236
|
+
config[key] = this.parseInlineExpressionTail(this.parseValue());
|
|
3858
4237
|
}
|
|
4238
|
+
this.matchBlockMemberSeparator();
|
|
3859
4239
|
this.skipNewlines();
|
|
3860
4240
|
}
|
|
3861
4241
|
this.expect("RBRACE");
|
|
3862
4242
|
return config;
|
|
3863
4243
|
}
|
|
4244
|
+
parseInlineExpressionTail(value) {
|
|
4245
|
+
if (value === null || typeof value === "object" && !Array.isArray(value) || !this.isInlineExpressionTailStart()) {
|
|
4246
|
+
return value;
|
|
4247
|
+
}
|
|
4248
|
+
let text = String(value);
|
|
4249
|
+
while (!this.check(["NEWLINE", "COMMA", "SEMICOLON", "RBRACE", "RPAREN", "RBRACKET", "EOF"])) {
|
|
4250
|
+
const token = this.current();
|
|
4251
|
+
const raw = token.type === "STRING" ? `"${token.value}"` : token.value;
|
|
4252
|
+
text += ` ${raw}`;
|
|
4253
|
+
this.advance();
|
|
4254
|
+
}
|
|
4255
|
+
return text;
|
|
4256
|
+
}
|
|
4257
|
+
isInlineExpressionTailStart() {
|
|
4258
|
+
return this.check([
|
|
4259
|
+
"EQUALS_EQUALS",
|
|
4260
|
+
"BANG_EQUALS",
|
|
4261
|
+
"LESS",
|
|
4262
|
+
"LESS_EQUALS",
|
|
4263
|
+
"GREATER",
|
|
4264
|
+
"GREATER_EQUALS",
|
|
4265
|
+
"AND",
|
|
4266
|
+
"OR",
|
|
4267
|
+
"PLUS",
|
|
4268
|
+
"MINUS",
|
|
4269
|
+
"STAR",
|
|
4270
|
+
"SLASH"
|
|
4271
|
+
]);
|
|
4272
|
+
}
|
|
4273
|
+
isNamedOrTraitedPropertyBlockStart() {
|
|
4274
|
+
if (!this.isPropertyName()) return false;
|
|
4275
|
+
let index = this.pos + 1;
|
|
4276
|
+
const hasName = this.tokens[index]?.type === "STRING" || this.tokens[index]?.type === "IDENTIFIER";
|
|
4277
|
+
if (hasName) {
|
|
4278
|
+
index++;
|
|
4279
|
+
}
|
|
4280
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
4281
|
+
let hasTrait = false;
|
|
4282
|
+
while (this.tokens[index]?.type === "AT") {
|
|
4283
|
+
hasTrait = true;
|
|
4284
|
+
index++;
|
|
4285
|
+
if (this.tokens[index]?.type === "EOF") return false;
|
|
4286
|
+
index++;
|
|
4287
|
+
if (this.tokens[index]?.type === "LPAREN") {
|
|
4288
|
+
index = this.indexAfterBalancedTokens(index, "LPAREN", "RPAREN");
|
|
4289
|
+
}
|
|
4290
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
4291
|
+
}
|
|
4292
|
+
return (hasName || hasTrait) && this.tokens[index]?.type === "LBRACE";
|
|
4293
|
+
}
|
|
4294
|
+
indexAfterBalancedTokens(startIndex, openType, closeType) {
|
|
4295
|
+
let depth = 0;
|
|
4296
|
+
let index = startIndex;
|
|
4297
|
+
while (index < this.tokens.length) {
|
|
4298
|
+
if (this.tokens[index].type === openType) depth++;
|
|
4299
|
+
if (this.tokens[index].type === closeType) {
|
|
4300
|
+
depth--;
|
|
4301
|
+
index++;
|
|
4302
|
+
if (depth === 0) return index;
|
|
4303
|
+
continue;
|
|
4304
|
+
}
|
|
4305
|
+
index++;
|
|
4306
|
+
}
|
|
4307
|
+
return index;
|
|
4308
|
+
}
|
|
4309
|
+
parseNamedOrTraitedPropertyBlock() {
|
|
4310
|
+
const key = this.parsePropertyKey();
|
|
4311
|
+
const name = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : void 0;
|
|
4312
|
+
const traits = this.parseInlineTraitNamesBeforeBlock();
|
|
4313
|
+
const body = this.check("LBRACE") ? this.parseBlockTraitConfig() : {};
|
|
4314
|
+
return {
|
|
4315
|
+
key,
|
|
4316
|
+
value: {
|
|
4317
|
+
...name !== void 0 ? { name } : {},
|
|
4318
|
+
...traits.length > 0 ? { traits } : {},
|
|
4319
|
+
...body
|
|
4320
|
+
}
|
|
4321
|
+
};
|
|
4322
|
+
}
|
|
4323
|
+
parseInlineTraitNamesBeforeBlock() {
|
|
4324
|
+
const traits = [];
|
|
4325
|
+
while (this.check("AT")) {
|
|
4326
|
+
this.advance();
|
|
4327
|
+
const traitName = this.parseTraitName();
|
|
4328
|
+
if (traitName) traits.push(traitName);
|
|
4329
|
+
if (this.check("LPAREN")) {
|
|
4330
|
+
this.skipParens();
|
|
4331
|
+
}
|
|
4332
|
+
this.skipNewlines();
|
|
4333
|
+
}
|
|
4334
|
+
return traits;
|
|
4335
|
+
}
|
|
4336
|
+
parseSharePlayBlock() {
|
|
4337
|
+
this.advance();
|
|
4338
|
+
if (!this.check("LBRACE")) return {};
|
|
4339
|
+
return this.parseBlockTraitConfig();
|
|
4340
|
+
}
|
|
3864
4341
|
// ===========================================================================
|
|
3865
4342
|
// PLATFORM CONSTRAINT PARSING
|
|
3866
4343
|
// ===========================================================================
|
|
@@ -3976,7 +4453,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3976
4453
|
type: "NPC",
|
|
3977
4454
|
name,
|
|
3978
4455
|
properties: [],
|
|
3979
|
-
behaviors: []
|
|
4456
|
+
behaviors: [],
|
|
4457
|
+
traits: [],
|
|
4458
|
+
directives: []
|
|
3980
4459
|
};
|
|
3981
4460
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3982
4461
|
this.skipNewlines();
|
|
@@ -3985,29 +4464,86 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3985
4464
|
npc.behaviors.push(this.parseBehavior());
|
|
3986
4465
|
} else if (this.check("STATE")) {
|
|
3987
4466
|
npc.state = this.parseState();
|
|
3988
|
-
} else {
|
|
3989
|
-
const
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
this.
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4467
|
+
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
4468
|
+
const action = this.parseAction();
|
|
4469
|
+
(npc.directives ?? (npc.directives = [])).push({
|
|
4470
|
+
type: "method",
|
|
4471
|
+
name: action.name,
|
|
4472
|
+
parameters: action.parameters || [],
|
|
4473
|
+
body: action.body,
|
|
4474
|
+
async: action.async
|
|
4475
|
+
});
|
|
4476
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on" && this.peek(1).type === "IDENTIFIER") {
|
|
4477
|
+
const eventName = this.peek(1).value;
|
|
4478
|
+
this.advance();
|
|
4479
|
+
this.advance();
|
|
4480
|
+
while (this.check("DOT")) {
|
|
4481
|
+
this.advance();
|
|
4482
|
+
if (this.check("IDENTIFIER")) this.advance();
|
|
4483
|
+
}
|
|
4484
|
+
let parameters = [];
|
|
4485
|
+
if (this.check("LPAREN")) {
|
|
4486
|
+
parameters = this.parseParameterList();
|
|
4487
|
+
}
|
|
4488
|
+
this.skipBlock();
|
|
4489
|
+
(npc.directives ?? (npc.directives = [])).push({
|
|
4490
|
+
type: "lifecycle",
|
|
4491
|
+
hook: eventName,
|
|
4492
|
+
parameters,
|
|
4493
|
+
body: []
|
|
4494
|
+
});
|
|
4495
|
+
} else if (this.check("AT")) {
|
|
4496
|
+
this.advance();
|
|
4497
|
+
const traitName = this.parseTraitName();
|
|
4498
|
+
const config = this.parseOptionalTraitConfig(true);
|
|
4499
|
+
(npc.traits ?? (npc.traits = [])).push({ type: "ObjectTrait", name: traitName, config });
|
|
4500
|
+
} else {
|
|
4501
|
+
const key = this.expectIdentifier();
|
|
4502
|
+
this.expect("COLON");
|
|
4503
|
+
const value = this.parseValue();
|
|
4504
|
+
if (key === "type") npc.npcType = value;
|
|
4505
|
+
else if (key === "model") npc.model = value;
|
|
4506
|
+
else if (key === "dialogue_tree") npc.dialogueTree = value;
|
|
4507
|
+
else if (key === "position") {
|
|
4508
|
+
if (Array.isArray(value) && value.length >= 3) {
|
|
4509
|
+
npc.position = { x: value[0], y: value[1], z: value[2] };
|
|
4510
|
+
} else if (value && typeof value === "object" && "x" in value) {
|
|
4511
|
+
const v = value;
|
|
4512
|
+
npc.position = { x: v.x, y: v.y, z: v.z };
|
|
4513
|
+
}
|
|
4514
|
+
} else if (key === "brain_ref") {
|
|
4515
|
+
npc.brain = {
|
|
4516
|
+
...npc.brain ?? { type: "AgentBrainAttachment", brainType: "llm" },
|
|
4517
|
+
type: "AgentBrainAttachment",
|
|
4518
|
+
brainType: npc.brain?.brainType ?? "llm",
|
|
4519
|
+
brainRef: value
|
|
4520
|
+
};
|
|
4521
|
+
} else if (key === "brain") {
|
|
4522
|
+
const cfg = value && typeof value === "object" ? value : {};
|
|
4523
|
+
npc.brain = {
|
|
4524
|
+
type: "AgentBrainAttachment",
|
|
4525
|
+
brainType: cfg.type ?? "llm",
|
|
4526
|
+
autonomy: cfg.autonomy,
|
|
4527
|
+
brainRef: typeof cfg.ref === "string" ? cfg.ref : typeof cfg.brainRef === "string" ? cfg.brainRef : void 0,
|
|
4528
|
+
toolPermissions: Array.isArray(cfg.tools) ? cfg.tools.map(String) : void 0,
|
|
4529
|
+
model: cfg.model && typeof cfg.model === "object" ? cfg.model : void 0
|
|
4530
|
+
};
|
|
4531
|
+
} else npc.properties.push({ type: "NPCProperty", key, value });
|
|
4532
|
+
}
|
|
4533
|
+
this.skipNewlines();
|
|
4534
|
+
}
|
|
4535
|
+
this.expect("RBRACE");
|
|
4536
|
+
this.popContext();
|
|
4537
|
+
return npc;
|
|
4538
|
+
}
|
|
4539
|
+
parseBehavior() {
|
|
4540
|
+
this.expect("BEHAVIOR");
|
|
4541
|
+
const name = this.expectString();
|
|
4542
|
+
this.expect("LBRACE");
|
|
4543
|
+
this.skipNewlines();
|
|
4544
|
+
const behavior = {
|
|
4545
|
+
type: "Behavior",
|
|
4546
|
+
name,
|
|
4011
4547
|
trigger: "idle",
|
|
4012
4548
|
actions: []
|
|
4013
4549
|
};
|
|
@@ -4349,7 +4885,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4349
4885
|
options: []
|
|
4350
4886
|
};
|
|
4351
4887
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4352
|
-
this.
|
|
4888
|
+
this.skipBlockMemberSeparators();
|
|
4353
4889
|
if (this.check("RBRACE")) break;
|
|
4354
4890
|
const key = this.expectIdentifier();
|
|
4355
4891
|
this.expect("COLON");
|
|
@@ -4379,7 +4915,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4379
4915
|
text: ""
|
|
4380
4916
|
};
|
|
4381
4917
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4382
|
-
this.
|
|
4918
|
+
this.skipBlockMemberSeparators();
|
|
4383
4919
|
if (this.check("RBRACE")) break;
|
|
4384
4920
|
const key = this.expectIdentifier();
|
|
4385
4921
|
this.expect("COLON");
|
|
@@ -4402,9 +4938,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4402
4938
|
// BRITTNEY AI FEATURES - STATE MACHINES
|
|
4403
4939
|
// ===========================================================================
|
|
4404
4940
|
parseStateMachine() {
|
|
4405
|
-
this.currentLocation();
|
|
4941
|
+
const startLoc = this.currentLocation();
|
|
4406
4942
|
this.expect("STATE_MACHINE");
|
|
4407
|
-
const name = this.
|
|
4943
|
+
const name = this.parseOptionalStateMachineName("");
|
|
4944
|
+
if (!name) {
|
|
4945
|
+
this.error("Expected state_machine name");
|
|
4946
|
+
}
|
|
4408
4947
|
this.pushContext(`StateMachine "${name}"`);
|
|
4409
4948
|
this.expect("LBRACE");
|
|
4410
4949
|
this.skipNewlines();
|
|
@@ -4412,11 +4951,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4412
4951
|
type: "StateMachine",
|
|
4413
4952
|
name,
|
|
4414
4953
|
initialState: "",
|
|
4415
|
-
|
|
4954
|
+
inputs: [],
|
|
4955
|
+
listeners: [],
|
|
4956
|
+
states: {},
|
|
4957
|
+
transitions: []
|
|
4416
4958
|
};
|
|
4417
4959
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4418
4960
|
this.skipNewlines();
|
|
4419
4961
|
if (this.check("RBRACE")) break;
|
|
4962
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
4963
|
+
sm.transitions.push(this.parseAnimationTransitionShorthand());
|
|
4964
|
+
this.skipNewlines();
|
|
4965
|
+
continue;
|
|
4966
|
+
}
|
|
4420
4967
|
if (this.check("STATE")) {
|
|
4421
4968
|
this.advance();
|
|
4422
4969
|
const stateName = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : "anonymous";
|
|
@@ -4433,6 +4980,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4433
4980
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4434
4981
|
this.skipNewlines();
|
|
4435
4982
|
if (this.check("RBRACE")) break;
|
|
4983
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
4984
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
4985
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
4986
|
+
else this.advance();
|
|
4987
|
+
continue;
|
|
4988
|
+
}
|
|
4436
4989
|
const key2 = this.expectIdentifier();
|
|
4437
4990
|
if (this.check("COLON")) {
|
|
4438
4991
|
this.advance();
|
|
@@ -4448,7 +5001,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4448
5001
|
this.expect("RBRACE");
|
|
4449
5002
|
} else if (key2 === "actions") {
|
|
4450
5003
|
state.actions = this.parseBehaviorActions();
|
|
4451
|
-
} else if (key2 === "transitions") {
|
|
5004
|
+
} else if (this.parseAnimationStateMetadata(state, key2)) ; else if (key2 === "transitions") {
|
|
4452
5005
|
state.transitions = this.parseStateTransitions();
|
|
4453
5006
|
} else if (key2 === "onDamage") {
|
|
4454
5007
|
state.onDamage = this.parseStatementBlock();
|
|
@@ -4457,7 +5010,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4457
5010
|
} else if (key2 === "onTimeout") {
|
|
4458
5011
|
state.onTimeout = this.parseStatementBlock();
|
|
4459
5012
|
} else {
|
|
4460
|
-
this.
|
|
5013
|
+
if (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5014
|
+
this.parseValue();
|
|
5015
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5016
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
5017
|
+
}
|
|
4461
5018
|
}
|
|
4462
5019
|
} else if (this.check("LBRACE")) {
|
|
4463
5020
|
if (key2 === "enter" || key2 === "entry") {
|
|
@@ -4473,6 +5030,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4473
5030
|
} else {
|
|
4474
5031
|
this.skipBlock();
|
|
4475
5032
|
}
|
|
5033
|
+
} else if (this.check("LPAREN")) {
|
|
5034
|
+
this.skipParens();
|
|
5035
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4476
5036
|
}
|
|
4477
5037
|
this.skipNewlines();
|
|
4478
5038
|
}
|
|
@@ -4482,18 +5042,37 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4482
5042
|
this.skipNewlines();
|
|
4483
5043
|
continue;
|
|
4484
5044
|
}
|
|
5045
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
5046
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5047
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
5048
|
+
else this.advance();
|
|
5049
|
+
this.skipNewlines();
|
|
5050
|
+
continue;
|
|
5051
|
+
}
|
|
4485
5052
|
const key = this.expectIdentifier();
|
|
4486
5053
|
if (key === "initial" || key === "initialState") {
|
|
4487
5054
|
this.expect("COLON");
|
|
4488
5055
|
sm.initialState = this.parseValue();
|
|
5056
|
+
} else if (key === "input") {
|
|
5057
|
+
sm.inputs.push(this.parseAnimationInputDeclaration(startLoc));
|
|
5058
|
+
} else if (key === "listen") {
|
|
5059
|
+
sm.listeners.push(this.parseAnimationListenerDeclaration(startLoc));
|
|
4489
5060
|
} else if (key === "states" && this.check("COLON")) {
|
|
4490
5061
|
this.advance();
|
|
4491
5062
|
sm.states = this.parseStateMachineStates();
|
|
5063
|
+
} else if (key === "transitions" && this.check("COLON")) {
|
|
5064
|
+
this.advance();
|
|
5065
|
+
sm.transitions = this.parseStateTransitions();
|
|
4492
5066
|
} else if (this.check("COLON")) {
|
|
4493
5067
|
this.advance();
|
|
4494
5068
|
this.parseValue();
|
|
5069
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5070
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4495
5071
|
} else if (this.check("LBRACE")) {
|
|
4496
5072
|
this.skipBlock();
|
|
5073
|
+
} else if (this.check("LPAREN")) {
|
|
5074
|
+
this.skipParens();
|
|
5075
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4497
5076
|
}
|
|
4498
5077
|
this.skipNewlines();
|
|
4499
5078
|
}
|
|
@@ -4514,19 +5093,27 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4514
5093
|
* Without this, @state_machine blocks were stored as opaque traits and
|
|
4515
5094
|
* invisible to compile_to_a2a_agent_card and other compilers.
|
|
4516
5095
|
*/
|
|
4517
|
-
parseStateMachineFromDecorator() {
|
|
5096
|
+
parseStateMachineFromDecorator(name = "implicit") {
|
|
4518
5097
|
const startLoc = this.currentLocation();
|
|
4519
5098
|
this.expect("LBRACE");
|
|
4520
5099
|
this.skipNewlines();
|
|
4521
5100
|
const sm = {
|
|
4522
5101
|
type: "StateMachine",
|
|
4523
|
-
name
|
|
5102
|
+
name,
|
|
4524
5103
|
initialState: "",
|
|
4525
|
-
|
|
5104
|
+
inputs: [],
|
|
5105
|
+
listeners: [],
|
|
5106
|
+
states: {},
|
|
5107
|
+
transitions: []
|
|
4526
5108
|
};
|
|
4527
5109
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4528
5110
|
this.skipNewlines();
|
|
4529
5111
|
if (this.check("RBRACE")) break;
|
|
5112
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
5113
|
+
sm.transitions.push(this.parseAnimationTransitionShorthand());
|
|
5114
|
+
this.skipNewlines();
|
|
5115
|
+
continue;
|
|
5116
|
+
}
|
|
4530
5117
|
if (this.check("STATE")) {
|
|
4531
5118
|
this.advance();
|
|
4532
5119
|
const stateName = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : "anonymous";
|
|
@@ -4543,6 +5130,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4543
5130
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4544
5131
|
this.skipNewlines();
|
|
4545
5132
|
if (this.check("RBRACE")) break;
|
|
5133
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
5134
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5135
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
5136
|
+
else this.advance();
|
|
5137
|
+
continue;
|
|
5138
|
+
}
|
|
4546
5139
|
const key2 = this.expectIdentifier();
|
|
4547
5140
|
if (this.check("COLON")) {
|
|
4548
5141
|
this.advance();
|
|
@@ -4558,12 +5151,16 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4558
5151
|
this.expect("RBRACE");
|
|
4559
5152
|
} else if (key2 === "actions") {
|
|
4560
5153
|
state.actions = this.parseBehaviorActions();
|
|
4561
|
-
} else if (key2 === "transitions") {
|
|
5154
|
+
} else if (this.parseAnimationStateMetadata(state, key2)) ; else if (key2 === "transitions") {
|
|
4562
5155
|
state.transitions = this.parseStateTransitions();
|
|
4563
5156
|
} else if (key2 === "timeout") {
|
|
4564
5157
|
state.timeout = this.parseValue();
|
|
4565
5158
|
} else {
|
|
4566
|
-
this.
|
|
5159
|
+
if (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5160
|
+
this.parseValue();
|
|
5161
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5162
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
5163
|
+
}
|
|
4567
5164
|
}
|
|
4568
5165
|
} else if (this.check("LBRACE")) {
|
|
4569
5166
|
if (key2 === "enter" || key2 === "entry" || key2 === "on_entry") {
|
|
@@ -4581,6 +5178,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4581
5178
|
} else {
|
|
4582
5179
|
this.skipBlock();
|
|
4583
5180
|
}
|
|
5181
|
+
} else if (this.check("LPAREN")) {
|
|
5182
|
+
this.skipParens();
|
|
5183
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4584
5184
|
}
|
|
4585
5185
|
this.skipNewlines();
|
|
4586
5186
|
}
|
|
@@ -4590,21 +5190,40 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4590
5190
|
this.skipNewlines();
|
|
4591
5191
|
continue;
|
|
4592
5192
|
}
|
|
5193
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
5194
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5195
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
5196
|
+
else this.advance();
|
|
5197
|
+
this.skipNewlines();
|
|
5198
|
+
continue;
|
|
5199
|
+
}
|
|
4593
5200
|
const key = this.expectIdentifier();
|
|
4594
5201
|
if (key === "initial" || key === "initialState") {
|
|
4595
5202
|
this.expect("COLON");
|
|
4596
5203
|
sm.initialState = this.parseValue();
|
|
5204
|
+
} else if (key === "input") {
|
|
5205
|
+
sm.inputs.push(this.parseAnimationInputDeclaration(startLoc));
|
|
5206
|
+
} else if (key === "listen") {
|
|
5207
|
+
sm.listeners.push(this.parseAnimationListenerDeclaration(startLoc));
|
|
4597
5208
|
} else if (key === "name") {
|
|
4598
5209
|
this.expect("COLON");
|
|
4599
5210
|
sm.name = this.parseValue();
|
|
4600
5211
|
} else if (key === "states" && this.check("COLON")) {
|
|
4601
5212
|
this.advance();
|
|
4602
5213
|
sm.states = this.parseStateMachineStates();
|
|
5214
|
+
} else if (key === "transitions" && this.check("COLON")) {
|
|
5215
|
+
this.advance();
|
|
5216
|
+
sm.transitions = this.parseStateTransitions();
|
|
4603
5217
|
} else if (this.check("COLON")) {
|
|
4604
5218
|
this.advance();
|
|
4605
5219
|
this.parseValue();
|
|
5220
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5221
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4606
5222
|
} else if (this.check("LBRACE")) {
|
|
4607
5223
|
this.skipBlock();
|
|
5224
|
+
} else if (this.check("LPAREN")) {
|
|
5225
|
+
this.skipParens();
|
|
5226
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4608
5227
|
}
|
|
4609
5228
|
this.skipNewlines();
|
|
4610
5229
|
}
|
|
@@ -4637,7 +5256,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4637
5256
|
if (key === "entry") state.entry = this.parseStatementBlock();
|
|
4638
5257
|
else if (key === "exit") state.exit = this.parseStatementBlock();
|
|
4639
5258
|
else if (key === "actions") state.actions = this.parseBehaviorActions();
|
|
4640
|
-
else if (key === "onDamage") state.onDamage = this.parseStatementBlock();
|
|
5259
|
+
else if (this.parseAnimationStateMetadata(state, key)) ; else if (key === "onDamage") state.onDamage = this.parseStatementBlock();
|
|
4641
5260
|
else if (key === "timeout") state.timeout = this.parseValue();
|
|
4642
5261
|
else if (key === "onTimeout") state.onTimeout = this.parseStatementBlock();
|
|
4643
5262
|
else if (key === "transitions") state.transitions = this.parseStateTransitions();
|
|
@@ -4651,13 +5270,385 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4651
5270
|
this.expect("RBRACE");
|
|
4652
5271
|
return states;
|
|
4653
5272
|
}
|
|
5273
|
+
parseOptionalStateMachineName(defaultName) {
|
|
5274
|
+
if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
|
|
5275
|
+
return this.advance().value;
|
|
5276
|
+
}
|
|
5277
|
+
return defaultName;
|
|
5278
|
+
}
|
|
5279
|
+
parseAnimationStateMetadata(state, key) {
|
|
5280
|
+
if (key === "clip") {
|
|
5281
|
+
state.clip = String(this.parseValue() ?? "");
|
|
5282
|
+
return true;
|
|
5283
|
+
}
|
|
5284
|
+
if (key === "clips") {
|
|
5285
|
+
state.clips = this.coerceStringArray(this.parseValue());
|
|
5286
|
+
return true;
|
|
5287
|
+
}
|
|
5288
|
+
if (key === "parameter") {
|
|
5289
|
+
state.parameter = String(this.parseValue() ?? "");
|
|
5290
|
+
return true;
|
|
5291
|
+
}
|
|
5292
|
+
if (key === "parameters") {
|
|
5293
|
+
state.parameters = this.coerceStringArray(this.parseValue());
|
|
5294
|
+
return true;
|
|
5295
|
+
}
|
|
5296
|
+
if (key === "thresholds") {
|
|
5297
|
+
state.thresholds = this.coerceNumberArray(this.parseValue());
|
|
5298
|
+
return true;
|
|
5299
|
+
}
|
|
5300
|
+
if (key === "blendType" || key === "blend_type" || key === "blend") {
|
|
5301
|
+
const blendType = String(this.parseValue() ?? "").toLowerCase();
|
|
5302
|
+
if (blendType === "1d" || blendType === "direct") {
|
|
5303
|
+
state.blendType = blendType;
|
|
5304
|
+
} else {
|
|
5305
|
+
this.error(`Unknown animation blend type "${blendType}"`);
|
|
5306
|
+
}
|
|
5307
|
+
return true;
|
|
5308
|
+
}
|
|
5309
|
+
if (key === "blendMode" || key === "blend_mode") {
|
|
5310
|
+
const blendMode = String(this.parseValue() ?? "").toLowerCase();
|
|
5311
|
+
if (blendMode === "override" || blendMode === "additive") {
|
|
5312
|
+
state.blendMode = blendMode;
|
|
5313
|
+
} else {
|
|
5314
|
+
this.error(`Unknown animation blend mode "${blendMode}"`);
|
|
5315
|
+
}
|
|
5316
|
+
return true;
|
|
5317
|
+
}
|
|
5318
|
+
if (key === "mask") {
|
|
5319
|
+
state.mask = this.coerceStringArray(this.parseValue());
|
|
5320
|
+
return true;
|
|
5321
|
+
}
|
|
5322
|
+
if (key === "baseline") {
|
|
5323
|
+
state.baseline = this.coerceNumberRecord(this.parseValue());
|
|
5324
|
+
return true;
|
|
5325
|
+
}
|
|
5326
|
+
return false;
|
|
5327
|
+
}
|
|
5328
|
+
coerceStringArray(value) {
|
|
5329
|
+
if (!Array.isArray(value)) return value == null ? [] : [String(value)];
|
|
5330
|
+
return value.map((entry) => String(entry));
|
|
5331
|
+
}
|
|
5332
|
+
coerceNumberArray(value) {
|
|
5333
|
+
if (!Array.isArray(value)) {
|
|
5334
|
+
const single = Number(value);
|
|
5335
|
+
return Number.isFinite(single) ? [single] : [];
|
|
5336
|
+
}
|
|
5337
|
+
return value.map((entry) => Number(entry)).filter((entry) => Number.isFinite(entry));
|
|
5338
|
+
}
|
|
5339
|
+
coerceNumberRecord(value) {
|
|
5340
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
5341
|
+
const out = {};
|
|
5342
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
5343
|
+
const numeric = Number(raw);
|
|
5344
|
+
if (Number.isFinite(numeric)) out[key] = numeric;
|
|
5345
|
+
}
|
|
5346
|
+
return out;
|
|
5347
|
+
}
|
|
5348
|
+
isStateNameToken(offset = 0) {
|
|
5349
|
+
const token = this.peek(offset);
|
|
5350
|
+
return token.type === "STRING" || token.type === "IDENTIFIER" || this.isKeywordAsIdentifierType(token.type);
|
|
5351
|
+
}
|
|
5352
|
+
isAnimationTransitionShorthandStart() {
|
|
5353
|
+
if (!this.isStateNameToken()) return false;
|
|
5354
|
+
return this.peek(1).type === "ARROW" || this.peek(1).type === "MINUS" && this.peek(2).type === "GREATER";
|
|
5355
|
+
}
|
|
5356
|
+
consumeStateTransitionArrow() {
|
|
5357
|
+
if (this.match("ARROW")) return true;
|
|
5358
|
+
if (this.check("MINUS") && this.peek(1).type === "GREATER") {
|
|
5359
|
+
this.advance();
|
|
5360
|
+
this.advance();
|
|
5361
|
+
return true;
|
|
5362
|
+
}
|
|
5363
|
+
return false;
|
|
5364
|
+
}
|
|
5365
|
+
parseAnimationInputDeclaration(startLoc) {
|
|
5366
|
+
const name = this.expectIdentifier();
|
|
5367
|
+
this.expect("COLON");
|
|
5368
|
+
const rawType = this.parseIdentifierOrStringValue();
|
|
5369
|
+
const inputType = this.normalizeAnimationInputType(rawType);
|
|
5370
|
+
let defaultValue;
|
|
5371
|
+
if (this.match("EQUALS")) {
|
|
5372
|
+
defaultValue = this.coerceAnimationInputDefault(inputType, this.parseValue());
|
|
5373
|
+
}
|
|
5374
|
+
return {
|
|
5375
|
+
type: "AnimationInput",
|
|
5376
|
+
name,
|
|
5377
|
+
inputType,
|
|
5378
|
+
rawType,
|
|
5379
|
+
default: defaultValue,
|
|
5380
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5381
|
+
};
|
|
5382
|
+
}
|
|
5383
|
+
parseAnimationListenerDeclaration(startLoc) {
|
|
5384
|
+
const event = this.parseDottedIdentifierValue("Expected listener event");
|
|
5385
|
+
if (!this.consumeStateTransitionArrow()) {
|
|
5386
|
+
this.error("Expected -> in animation listener");
|
|
5387
|
+
}
|
|
5388
|
+
if (this.isIdentifierValue("fire")) {
|
|
5389
|
+
this.advance();
|
|
5390
|
+
return {
|
|
5391
|
+
type: "AnimationListener",
|
|
5392
|
+
event,
|
|
5393
|
+
parameter: this.parseDottedIdentifierValue("Expected trigger input"),
|
|
5394
|
+
action: "fire",
|
|
5395
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5396
|
+
};
|
|
5397
|
+
}
|
|
5398
|
+
if (this.isIdentifierValue("reset")) {
|
|
5399
|
+
this.advance();
|
|
5400
|
+
return {
|
|
5401
|
+
type: "AnimationListener",
|
|
5402
|
+
event,
|
|
5403
|
+
parameter: this.parseDottedIdentifierValue("Expected trigger input"),
|
|
5404
|
+
action: "reset",
|
|
5405
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5406
|
+
};
|
|
5407
|
+
}
|
|
5408
|
+
const parameter = this.parseDottedIdentifierValue("Expected animation input");
|
|
5409
|
+
this.expect("EQUALS");
|
|
5410
|
+
const assignment = this.parseAnimationListenerValue();
|
|
5411
|
+
return {
|
|
5412
|
+
type: "AnimationListener",
|
|
5413
|
+
event,
|
|
5414
|
+
parameter,
|
|
5415
|
+
action: "set",
|
|
5416
|
+
...assignment,
|
|
5417
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5418
|
+
};
|
|
5419
|
+
}
|
|
5420
|
+
parseAnimationListenerValue() {
|
|
5421
|
+
if (this.isIdentifierValue("event")) {
|
|
5422
|
+
return { source: this.parseDottedIdentifierValue("Expected event value source") };
|
|
5423
|
+
}
|
|
5424
|
+
const value = this.parseValue();
|
|
5425
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
|
|
5426
|
+
return { value };
|
|
5427
|
+
}
|
|
5428
|
+
return { value: String(value ?? "") };
|
|
5429
|
+
}
|
|
5430
|
+
normalizeAnimationInputType(rawType) {
|
|
5431
|
+
const normalized = rawType.toLowerCase();
|
|
5432
|
+
if (normalized === "number") return "float";
|
|
5433
|
+
if (normalized === "boolean") return "bool";
|
|
5434
|
+
if (normalized === "bool" || normalized === "float" || normalized === "int" || normalized === "trigger") {
|
|
5435
|
+
return normalized;
|
|
5436
|
+
}
|
|
5437
|
+
this.error(`Unknown animation input type "${rawType}", defaulting to float`);
|
|
5438
|
+
return "float";
|
|
5439
|
+
}
|
|
5440
|
+
coerceAnimationInputDefault(inputType, value) {
|
|
5441
|
+
if (inputType === "bool" || inputType === "trigger") return Boolean(value);
|
|
5442
|
+
if (typeof value === "number") return value;
|
|
5443
|
+
if (typeof value === "boolean") return value ? 1 : 0;
|
|
5444
|
+
return void 0;
|
|
5445
|
+
}
|
|
5446
|
+
parseAnimationTransitionShorthand() {
|
|
5447
|
+
const startLoc = this.currentLocation();
|
|
5448
|
+
const rawFrom = this.parseStateNameValue();
|
|
5449
|
+
const from = rawFrom.toLowerCase() === "any" ? "any" : rawFrom;
|
|
5450
|
+
if (!this.consumeStateTransitionArrow()) {
|
|
5451
|
+
this.error("Expected -> in animation transition");
|
|
5452
|
+
}
|
|
5453
|
+
const target = this.parseStateNameValue();
|
|
5454
|
+
const transition = {
|
|
5455
|
+
type: "StateTransition",
|
|
5456
|
+
from,
|
|
5457
|
+
target,
|
|
5458
|
+
conditions: [],
|
|
5459
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5460
|
+
};
|
|
5461
|
+
while (!this.check("NEWLINE") && !this.check("SEMICOLON") && !this.check("COMMA") && !this.check("RBRACE") && !this.isAtEnd()) {
|
|
5462
|
+
if (!this.isStateNameToken()) break;
|
|
5463
|
+
const clause = this.current().value.toLowerCase();
|
|
5464
|
+
this.advance();
|
|
5465
|
+
if (clause === "when") {
|
|
5466
|
+
transition.condition = this.parseExpression();
|
|
5467
|
+
transition.conditions = this.expressionToAnimationConditions(transition.condition);
|
|
5468
|
+
} else if (clause === "on") {
|
|
5469
|
+
const event = this.parseIdentifierOrStringValue();
|
|
5470
|
+
transition.event = event;
|
|
5471
|
+
transition.conditions = [
|
|
5472
|
+
{
|
|
5473
|
+
type: "AnimationTransitionCondition",
|
|
5474
|
+
parameter: event,
|
|
5475
|
+
operator: "==",
|
|
5476
|
+
value: true,
|
|
5477
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5478
|
+
}
|
|
5479
|
+
];
|
|
5480
|
+
} else if (clause === "over" || clause === "duration") {
|
|
5481
|
+
transition.duration = this.parseNumberClauseValue();
|
|
5482
|
+
} else if (clause === "easing") {
|
|
5483
|
+
transition.easing = this.parseIdentifierOrStringValue();
|
|
5484
|
+
} else if (clause === "exittime" || clause === "exit_time") {
|
|
5485
|
+
transition.exitTime = this.parseNumberClauseValue();
|
|
5486
|
+
transition.hasExitTime = true;
|
|
5487
|
+
} else if (clause === "pausewhenexiting" || clause === "pause_when_exiting") {
|
|
5488
|
+
transition.pauseWhenExiting = this.parseOptionalBooleanFlag();
|
|
5489
|
+
} else if (clause === "priority") {
|
|
5490
|
+
transition.priority = this.parseNumberClauseValue();
|
|
5491
|
+
} else if (clause === "cantransitiontoself" || clause === "can_transition_to_self") {
|
|
5492
|
+
transition.canTransitionToSelf = this.parseOptionalBooleanFlag();
|
|
5493
|
+
} else {
|
|
5494
|
+
this.error(`Unknown animation transition clause "${clause}"`);
|
|
5495
|
+
break;
|
|
5496
|
+
}
|
|
5497
|
+
}
|
|
5498
|
+
transition.loc = { start: startLoc, end: this.currentLocation() };
|
|
5499
|
+
if (this.check("COMMA") || this.check("SEMICOLON")) this.advance();
|
|
5500
|
+
return transition;
|
|
5501
|
+
}
|
|
5502
|
+
parseStateNameValue() {
|
|
5503
|
+
if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
|
|
5504
|
+
return this.advance().value;
|
|
5505
|
+
}
|
|
5506
|
+
this.error(`Expected state name, got ${this.current().type}`);
|
|
5507
|
+
return this.isAtEnd() ? "" : this.advance().value;
|
|
5508
|
+
}
|
|
5509
|
+
parseNumberClauseValue() {
|
|
5510
|
+
if (this.check("COLON")) this.advance();
|
|
5511
|
+
const value = this.parseValue();
|
|
5512
|
+
return typeof value === "number" ? value : Number(value) || 0;
|
|
5513
|
+
}
|
|
5514
|
+
parseIdentifierOrStringValue() {
|
|
5515
|
+
if (this.check("COLON")) this.advance();
|
|
5516
|
+
if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
|
|
5517
|
+
return this.advance().value;
|
|
5518
|
+
}
|
|
5519
|
+
const value = this.parseValue();
|
|
5520
|
+
return value == null ? "" : String(value);
|
|
5521
|
+
}
|
|
5522
|
+
parseDottedIdentifierValue(message) {
|
|
5523
|
+
let value = this.parseIdentifierOrStringValue();
|
|
5524
|
+
if (!value) {
|
|
5525
|
+
this.error(message);
|
|
5526
|
+
}
|
|
5527
|
+
while (this.check("DOT")) {
|
|
5528
|
+
this.advance();
|
|
5529
|
+
const part = this.parseIdentifierOrStringValue();
|
|
5530
|
+
if (!part) {
|
|
5531
|
+
this.error("Expected property name after dot");
|
|
5532
|
+
break;
|
|
5533
|
+
}
|
|
5534
|
+
value += `.${part}`;
|
|
5535
|
+
}
|
|
5536
|
+
return value;
|
|
5537
|
+
}
|
|
5538
|
+
isIdentifierValue(value) {
|
|
5539
|
+
return (this.current().type === "IDENTIFIER" || this.isKeywordAsIdentifierType(this.current().type)) && this.current().value === value;
|
|
5540
|
+
}
|
|
5541
|
+
parseOptionalBooleanFlag() {
|
|
5542
|
+
if (this.check("COLON")) this.advance();
|
|
5543
|
+
if (this.check("BOOLEAN")) return this.advance().value === "true";
|
|
5544
|
+
if (this.check("IDENTIFIER")) {
|
|
5545
|
+
const value = this.current().value.toLowerCase();
|
|
5546
|
+
if (value === "true" || value === "false") {
|
|
5547
|
+
this.advance();
|
|
5548
|
+
return value === "true";
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
return true;
|
|
5552
|
+
}
|
|
5553
|
+
expressionToAnimationConditions(expression) {
|
|
5554
|
+
if (expression.type === "BinaryExpression" && (expression.operator === "&&" || expression.operator === "||")) {
|
|
5555
|
+
const left = this.expressionToAnimationConditions(expression.left);
|
|
5556
|
+
const right = this.expressionToAnimationConditions(expression.right);
|
|
5557
|
+
if (left.length > 0 && right.length > 0) {
|
|
5558
|
+
left[left.length - 1].chain = expression.operator === "||" ? "or" : "and";
|
|
5559
|
+
}
|
|
5560
|
+
return [...left, ...right];
|
|
5561
|
+
}
|
|
5562
|
+
const comparison = this.expressionToAnimationCondition(expression);
|
|
5563
|
+
return comparison ? [comparison] : [];
|
|
5564
|
+
}
|
|
5565
|
+
expressionToAnimationCondition(expression) {
|
|
5566
|
+
const startLoc = expression.loc?.start ?? this.currentLocation();
|
|
5567
|
+
const endLoc = expression.loc?.end ?? this.currentLocation();
|
|
5568
|
+
if (expression.type === "BinaryExpression") {
|
|
5569
|
+
const normalizedOperator = this.normalizeAnimationConditionOperator(expression.operator);
|
|
5570
|
+
if (normalizedOperator) {
|
|
5571
|
+
const parameter = this.expressionToString(expression.left);
|
|
5572
|
+
if (parameter) {
|
|
5573
|
+
return {
|
|
5574
|
+
type: "AnimationTransitionCondition",
|
|
5575
|
+
parameter,
|
|
5576
|
+
operator: normalizedOperator,
|
|
5577
|
+
value: this.expressionLiteralValue(expression.right),
|
|
5578
|
+
loc: { start: startLoc, end: endLoc }
|
|
5579
|
+
};
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
if (expression.type === "Identifier" || expression.type === "MemberExpression") {
|
|
5584
|
+
return {
|
|
5585
|
+
type: "AnimationTransitionCondition",
|
|
5586
|
+
parameter: this.expressionToString(expression),
|
|
5587
|
+
operator: "==",
|
|
5588
|
+
value: true,
|
|
5589
|
+
loc: { start: startLoc, end: endLoc }
|
|
5590
|
+
};
|
|
5591
|
+
}
|
|
5592
|
+
if (expression.type === "UnaryExpression" && expression.operator === "!") {
|
|
5593
|
+
const parameter = this.expressionToString(expression.argument);
|
|
5594
|
+
if (parameter) {
|
|
5595
|
+
return {
|
|
5596
|
+
type: "AnimationTransitionCondition",
|
|
5597
|
+
parameter,
|
|
5598
|
+
operator: "==",
|
|
5599
|
+
value: false,
|
|
5600
|
+
loc: { start: startLoc, end: endLoc }
|
|
5601
|
+
};
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
return null;
|
|
5605
|
+
}
|
|
5606
|
+
normalizeAnimationConditionOperator(operator) {
|
|
5607
|
+
if (operator === "===") return "==";
|
|
5608
|
+
if (operator === "!==") return "!=";
|
|
5609
|
+
if (operator === "==" || operator === "!=" || operator === ">" || operator === "<" || operator === ">=" || operator === "<=") {
|
|
5610
|
+
return operator;
|
|
5611
|
+
}
|
|
5612
|
+
return null;
|
|
5613
|
+
}
|
|
5614
|
+
expressionLiteralValue(expression) {
|
|
5615
|
+
if (expression.type === "Literal") {
|
|
5616
|
+
if (expression.value === null) return "null";
|
|
5617
|
+
return expression.value;
|
|
5618
|
+
}
|
|
5619
|
+
const value = this.expressionToString(expression);
|
|
5620
|
+
return value || "";
|
|
5621
|
+
}
|
|
4654
5622
|
parseStateTransitions() {
|
|
5623
|
+
if (this.check("LBRACE")) {
|
|
5624
|
+
this.expect("LBRACE");
|
|
5625
|
+
this.skipNewlines();
|
|
5626
|
+
const transitions2 = [];
|
|
5627
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5628
|
+
this.skipNewlines();
|
|
5629
|
+
if (this.check("RBRACE")) break;
|
|
5630
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
5631
|
+
transitions2.push(this.parseAnimationTransitionShorthand());
|
|
5632
|
+
} else {
|
|
5633
|
+
this.error(`Expected animation transition, got ${this.current().type}`);
|
|
5634
|
+
this.advance();
|
|
5635
|
+
}
|
|
5636
|
+
this.skipNewlines();
|
|
5637
|
+
}
|
|
5638
|
+
this.expect("RBRACE");
|
|
5639
|
+
return transitions2;
|
|
5640
|
+
}
|
|
4655
5641
|
this.expect("LBRACKET");
|
|
4656
5642
|
this.skipNewlines();
|
|
4657
5643
|
const transitions = [];
|
|
4658
5644
|
while (!this.check("RBRACKET") && !this.isAtEnd()) {
|
|
4659
5645
|
this.skipNewlines();
|
|
4660
5646
|
if (this.check("RBRACKET")) break;
|
|
5647
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
5648
|
+
transitions.push(this.parseAnimationTransitionShorthand());
|
|
5649
|
+
this.skipNewlines();
|
|
5650
|
+
continue;
|
|
5651
|
+
}
|
|
4661
5652
|
this.expect("LBRACE");
|
|
4662
5653
|
this.skipNewlines();
|
|
4663
5654
|
const transition = {
|
|
@@ -4669,9 +5660,46 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4669
5660
|
if (this.check("RBRACE")) break;
|
|
4670
5661
|
const key = this.expectIdentifier();
|
|
4671
5662
|
this.expect("COLON");
|
|
4672
|
-
if (key === "
|
|
4673
|
-
|
|
4674
|
-
|
|
5663
|
+
if (key === "from") {
|
|
5664
|
+
const from = this.parseValue();
|
|
5665
|
+
transition.from = from.toLowerCase() === "any" ? "any" : from;
|
|
5666
|
+
} else if (key === "target" || key === "to") {
|
|
5667
|
+
transition.target = this.parseValue();
|
|
5668
|
+
} else if (key === "condition" || key === "when") {
|
|
5669
|
+
transition.condition = this.parseExpression();
|
|
5670
|
+
transition.conditions = this.expressionToAnimationConditions(transition.condition);
|
|
5671
|
+
} else if (key === "event" || key === "on") {
|
|
5672
|
+
transition.event = this.parseValue();
|
|
5673
|
+
transition.conditions = [
|
|
5674
|
+
{
|
|
5675
|
+
type: "AnimationTransitionCondition",
|
|
5676
|
+
parameter: transition.event,
|
|
5677
|
+
operator: "==",
|
|
5678
|
+
value: true,
|
|
5679
|
+
loc: transition.loc
|
|
5680
|
+
}
|
|
5681
|
+
];
|
|
5682
|
+
} else if (key === "duration" || key === "over") {
|
|
5683
|
+
const duration = this.parseValue();
|
|
5684
|
+
transition.duration = typeof duration === "number" ? duration : Number(duration) || 0;
|
|
5685
|
+
} else if (key === "easing") {
|
|
5686
|
+
transition.easing = this.parseValue();
|
|
5687
|
+
} else if (key === "exitTime" || key === "exit_time") {
|
|
5688
|
+
const exitTime = this.parseValue();
|
|
5689
|
+
transition.exitTime = typeof exitTime === "number" ? exitTime : Number(exitTime) || 0;
|
|
5690
|
+
transition.hasExitTime = true;
|
|
5691
|
+
} else if (key === "hasExitTime" || key === "has_exit_time") {
|
|
5692
|
+
transition.hasExitTime = Boolean(this.parseValue());
|
|
5693
|
+
} else if (key === "pauseWhenExiting" || key === "pause_when_exiting") {
|
|
5694
|
+
transition.pauseWhenExiting = Boolean(this.parseValue());
|
|
5695
|
+
} else if (key === "priority") {
|
|
5696
|
+
const priority = this.parseValue();
|
|
5697
|
+
transition.priority = typeof priority === "number" ? priority : Number(priority) || 0;
|
|
5698
|
+
} else if (key === "canTransitionToSelf" || key === "can_transition_to_self") {
|
|
5699
|
+
transition.canTransitionToSelf = Boolean(this.parseValue());
|
|
5700
|
+
} else {
|
|
5701
|
+
this.parseValue();
|
|
5702
|
+
}
|
|
4675
5703
|
this.skipNewlines();
|
|
4676
5704
|
}
|
|
4677
5705
|
this.expect("RBRACE");
|
|
@@ -4961,32 +5989,714 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4961
5989
|
isDomainBlockToken() {
|
|
4962
5990
|
return _HoloCompositionParser.DOMAIN_TOKENS.has(this.current().type);
|
|
4963
5991
|
}
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
this.
|
|
5992
|
+
isLooseOnHandlerStart() {
|
|
5993
|
+
return this.check("IDENTIFIER") && this.current().value === "on";
|
|
5994
|
+
}
|
|
5995
|
+
skipLooseOnHandler() {
|
|
5996
|
+
if (!this.isLooseOnHandlerStart()) return;
|
|
5997
|
+
this.advance();
|
|
5998
|
+
while (!this.check("LBRACE") && !this.isAtEnd()) {
|
|
5999
|
+
if (this.check("LPAREN")) {
|
|
6000
|
+
this.skipParens();
|
|
6001
|
+
} else {
|
|
6002
|
+
this.advance();
|
|
6003
|
+
}
|
|
6004
|
+
}
|
|
6005
|
+
if (this.check("LBRACE")) {
|
|
6006
|
+
this.skipBlock();
|
|
6007
|
+
}
|
|
6008
|
+
}
|
|
6009
|
+
isLooseDomainBlockStart() {
|
|
6010
|
+
if (!this.check("IDENTIFIER")) return false;
|
|
6011
|
+
const keyword = this.current().value;
|
|
6012
|
+
if (!/_material$/i.test(keyword)) return false;
|
|
6013
|
+
let index = this.pos + 1;
|
|
6014
|
+
if (this.tokens[index]?.type === "STRING" || this.tokens[index]?.type === "IDENTIFIER") {
|
|
6015
|
+
index++;
|
|
6016
|
+
}
|
|
6017
|
+
while (this.tokens[index]?.type === "AT") {
|
|
6018
|
+
index += 2;
|
|
6019
|
+
if (this.tokens[index]?.type === "LPAREN") {
|
|
6020
|
+
let depth = 1;
|
|
6021
|
+
index++;
|
|
6022
|
+
while (depth > 0 && index < this.tokens.length) {
|
|
6023
|
+
if (this.tokens[index].type === "LPAREN") depth++;
|
|
6024
|
+
else if (this.tokens[index].type === "RPAREN") depth--;
|
|
6025
|
+
index++;
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
6030
|
+
return this.tokens[index]?.type === "LBRACE";
|
|
6031
|
+
}
|
|
6032
|
+
isLooseNamedDomainBlockStart() {
|
|
6033
|
+
if (!this.check("IDENTIFIER")) return false;
|
|
6034
|
+
const keyword = this.current().value.toLowerCase();
|
|
6035
|
+
if (this.isPrimitiveShape(keyword) || this.isLightPrimitive(keyword) || keyword === "on") {
|
|
6036
|
+
return false;
|
|
6037
|
+
}
|
|
6038
|
+
let index = this.pos + 1;
|
|
6039
|
+
if (this.tokens[index]?.type !== "STRING" && this.tokens[index]?.type !== "IDENTIFIER") {
|
|
6040
|
+
return false;
|
|
6041
|
+
}
|
|
6042
|
+
index++;
|
|
6043
|
+
while (this.tokens[index]?.type === "AT") {
|
|
6044
|
+
index += 2;
|
|
6045
|
+
if (this.tokens[index]?.type === "LPAREN") {
|
|
6046
|
+
let depth = 1;
|
|
6047
|
+
index++;
|
|
6048
|
+
while (depth > 0 && index < this.tokens.length) {
|
|
6049
|
+
if (this.tokens[index].type === "LPAREN") depth++;
|
|
6050
|
+
else if (this.tokens[index].type === "RPAREN") depth--;
|
|
6051
|
+
index++;
|
|
6052
|
+
}
|
|
6053
|
+
}
|
|
6054
|
+
}
|
|
6055
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
6056
|
+
return this.tokens[index]?.type === "LBRACE";
|
|
6057
|
+
}
|
|
6058
|
+
// ===========================================================================
|
|
6059
|
+
// MMO/AAA GAME CONSTRUCTS (v6.2 — June 2026)
|
|
6060
|
+
// ===========================================================================
|
|
6061
|
+
/**
|
|
6062
|
+
* Parse a loot_table block with weighted entry sub-blocks and optional
|
|
6063
|
+
* guaranteed drop section.
|
|
6064
|
+
*
|
|
6065
|
+
* Syntax:
|
|
6066
|
+
* loot_table goblin_drops {
|
|
6067
|
+
* entry common_coin { item: "gold_coin" qty: "1..5" weight: 60 }
|
|
6068
|
+
* entry nothing { weight: 10 }
|
|
6069
|
+
* guaranteed { item: "goblin_ear" qty: 1 }
|
|
6070
|
+
* multiplier_on_faction_hostile: "ironveil * 1.5"
|
|
6071
|
+
* }
|
|
6072
|
+
*/
|
|
6073
|
+
parseLootTable() {
|
|
6074
|
+
const startLoc = this.currentLocation();
|
|
6075
|
+
this.pushContext("loot-table");
|
|
6076
|
+
this.advance();
|
|
6077
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6078
|
+
this.expect("LBRACE");
|
|
6079
|
+
this.skipNewlines();
|
|
6080
|
+
const entries = [];
|
|
6081
|
+
let guaranteed;
|
|
6082
|
+
const properties = {};
|
|
6083
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6084
|
+
this.skipNewlines();
|
|
6085
|
+
if (this.check("RBRACE")) break;
|
|
6086
|
+
if (this.check("IDENTIFIER") && this.current().value === "entry") {
|
|
6087
|
+
this.advance();
|
|
6088
|
+
const entryId = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6089
|
+
const entryProps = {};
|
|
6090
|
+
let weight = 0;
|
|
6091
|
+
let itemId;
|
|
6092
|
+
let qty;
|
|
6093
|
+
let rarity;
|
|
6094
|
+
let condition;
|
|
6095
|
+
if (this.check("LBRACE")) {
|
|
6096
|
+
this.advance();
|
|
6097
|
+
this.skipNewlines();
|
|
6098
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6099
|
+
this.skipNewlines();
|
|
6100
|
+
if (this.check("RBRACE")) break;
|
|
6101
|
+
const key = this.expectIdentifier();
|
|
6102
|
+
this.expect("COLON");
|
|
6103
|
+
const val = this.parseValue();
|
|
6104
|
+
if (key === "item") itemId = val;
|
|
6105
|
+
else if (key === "weight") weight = val;
|
|
6106
|
+
else if (key === "qty") qty = val;
|
|
6107
|
+
else if (key === "rarity") rarity = val;
|
|
6108
|
+
else if (key === "condition") condition = val;
|
|
6109
|
+
else entryProps[key] = val;
|
|
6110
|
+
if (this.check("COMMA")) this.advance();
|
|
6111
|
+
this.skipNewlines();
|
|
6112
|
+
}
|
|
6113
|
+
this.expect("RBRACE");
|
|
6114
|
+
}
|
|
6115
|
+
entries.push({
|
|
6116
|
+
type: "LootEntry",
|
|
6117
|
+
id: entryId,
|
|
6118
|
+
itemId,
|
|
6119
|
+
weight,
|
|
6120
|
+
qty,
|
|
6121
|
+
rarity,
|
|
6122
|
+
condition,
|
|
6123
|
+
properties: entryProps
|
|
6124
|
+
});
|
|
6125
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "guaranteed") {
|
|
6126
|
+
this.advance();
|
|
6127
|
+
if (this.check("LBRACE")) {
|
|
6128
|
+
this.advance();
|
|
6129
|
+
this.skipNewlines();
|
|
6130
|
+
guaranteed = {};
|
|
6131
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6132
|
+
this.skipNewlines();
|
|
6133
|
+
if (this.check("RBRACE")) break;
|
|
6134
|
+
const key = this.expectIdentifier();
|
|
6135
|
+
this.expect("COLON");
|
|
6136
|
+
guaranteed[key] = this.parseValue();
|
|
6137
|
+
if (this.check("COMMA")) this.advance();
|
|
6138
|
+
this.skipNewlines();
|
|
6139
|
+
}
|
|
6140
|
+
this.expect("RBRACE");
|
|
6141
|
+
}
|
|
6142
|
+
} else {
|
|
6143
|
+
const key = this.expectIdentifier();
|
|
6144
|
+
this.expect("COLON");
|
|
6145
|
+
properties[key] = this.parseValue();
|
|
6146
|
+
}
|
|
6147
|
+
if (this.check("COMMA")) this.advance();
|
|
6148
|
+
this.skipNewlines();
|
|
6149
|
+
}
|
|
6150
|
+
this.expect("RBRACE");
|
|
6151
|
+
this.popContext();
|
|
6152
|
+
return {
|
|
6153
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6154
|
+
type: "LootTable",
|
|
6155
|
+
name,
|
|
6156
|
+
entries,
|
|
6157
|
+
guaranteed,
|
|
6158
|
+
properties
|
|
6159
|
+
};
|
|
6160
|
+
}
|
|
6161
|
+
/**
|
|
6162
|
+
* Parse a world_chunk block for open-world streaming.
|
|
6163
|
+
*
|
|
6164
|
+
* Syntax:
|
|
6165
|
+
* world_chunk dockside {
|
|
6166
|
+
* bounds: ((-200, 0, -200), (200, 100, 200))
|
|
6167
|
+
* priority: "high"
|
|
6168
|
+
* lod_distances: [50, 150, 400]
|
|
6169
|
+
* biome: "coastal_urban"
|
|
6170
|
+
* npc_roster: ["merchant_alva", "harbor_guard_01"]
|
|
6171
|
+
* streaming { load_radius: 300 unload_radius: 500 budget_kb: 32768 }
|
|
6172
|
+
* }
|
|
6173
|
+
*/
|
|
6174
|
+
parseWorldChunk() {
|
|
6175
|
+
const startLoc = this.currentLocation();
|
|
6176
|
+
this.pushContext("world-chunk");
|
|
6177
|
+
this.advance();
|
|
6178
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6179
|
+
this.expect("LBRACE");
|
|
6180
|
+
this.skipNewlines();
|
|
6181
|
+
const properties = {};
|
|
6182
|
+
let priority;
|
|
6183
|
+
let biome;
|
|
6184
|
+
let lodDistances;
|
|
6185
|
+
let assetManifest;
|
|
6186
|
+
let npcRoster;
|
|
6187
|
+
let spawnPoints;
|
|
6188
|
+
let streaming;
|
|
6189
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6190
|
+
this.skipNewlines();
|
|
6191
|
+
if (this.check("RBRACE")) break;
|
|
6192
|
+
if (this.check("IDENTIFIER") && this.current().value === "streaming") {
|
|
6193
|
+
this.advance();
|
|
6194
|
+
if (this.check("LBRACE")) {
|
|
6195
|
+
this.advance();
|
|
6196
|
+
this.skipNewlines();
|
|
6197
|
+
streaming = {};
|
|
6198
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6199
|
+
this.skipNewlines();
|
|
6200
|
+
if (this.check("RBRACE")) break;
|
|
6201
|
+
const key = this.expectIdentifier();
|
|
6202
|
+
this.expect("COLON");
|
|
6203
|
+
streaming[key] = this.parseValue();
|
|
6204
|
+
if (this.check("COMMA")) this.advance();
|
|
6205
|
+
this.skipNewlines();
|
|
6206
|
+
}
|
|
6207
|
+
this.expect("RBRACE");
|
|
6208
|
+
}
|
|
6209
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "asset_manifest") {
|
|
6210
|
+
this.advance();
|
|
6211
|
+
const val = this.parseValue();
|
|
6212
|
+
assetManifest = Array.isArray(val) ? val : [val];
|
|
6213
|
+
} else {
|
|
6214
|
+
const key = this.expectIdentifier();
|
|
6215
|
+
this.expect("COLON");
|
|
6216
|
+
const val = this.parseValue();
|
|
6217
|
+
if (key === "priority") priority = val;
|
|
6218
|
+
else if (key === "biome") biome = val;
|
|
6219
|
+
else if (key === "lod_distances")
|
|
6220
|
+
lodDistances = Array.isArray(val) ? val : [val];
|
|
6221
|
+
else if (key === "npc_roster") npcRoster = Array.isArray(val) ? val : [val];
|
|
6222
|
+
else if (key === "spawn_points") spawnPoints = val;
|
|
6223
|
+
else properties[key] = val;
|
|
6224
|
+
}
|
|
6225
|
+
if (this.check("COMMA")) this.advance();
|
|
6226
|
+
this.skipNewlines();
|
|
6227
|
+
}
|
|
6228
|
+
this.expect("RBRACE");
|
|
6229
|
+
this.popContext();
|
|
6230
|
+
return {
|
|
6231
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6232
|
+
type: "WorldChunk",
|
|
6233
|
+
name,
|
|
6234
|
+
priority,
|
|
6235
|
+
biome,
|
|
6236
|
+
lodDistances,
|
|
6237
|
+
assetManifest,
|
|
6238
|
+
npcRoster,
|
|
6239
|
+
spawnPoints,
|
|
6240
|
+
streaming,
|
|
6241
|
+
properties
|
|
6242
|
+
};
|
|
6243
|
+
}
|
|
6244
|
+
/**
|
|
6245
|
+
* Parse a world_layer block (P2.4 — phasing).
|
|
6246
|
+
*
|
|
6247
|
+
* Syntax:
|
|
6248
|
+
* world_layer post_awakening {
|
|
6249
|
+
* requires_quest: "main_chapter_1" // visible AFTER the quest is done
|
|
6250
|
+
* npcs: ["restored_keeper"] // forbids_quest = visible BEFORE
|
|
6251
|
+
* objects: ["healed_shrine"]
|
|
6252
|
+
* }
|
|
6253
|
+
*/
|
|
6254
|
+
parseWorldLayer() {
|
|
6255
|
+
const startLoc = this.currentLocation();
|
|
6256
|
+
this.pushContext("world-layer");
|
|
6257
|
+
this.advance();
|
|
6258
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6259
|
+
this.expect("LBRACE");
|
|
6260
|
+
this.skipNewlines();
|
|
6261
|
+
const properties = {};
|
|
6262
|
+
let questId = "";
|
|
6263
|
+
let mustBeCompleted = true;
|
|
6264
|
+
let npcs = [];
|
|
6265
|
+
let objects = [];
|
|
6266
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6267
|
+
this.skipNewlines();
|
|
6268
|
+
if (this.check("RBRACE")) break;
|
|
6269
|
+
const key = this.expectIdentifier();
|
|
6270
|
+
this.expect("COLON");
|
|
6271
|
+
const val = this.parseValue();
|
|
6272
|
+
if (key === "requires_quest") {
|
|
6273
|
+
questId = String(val);
|
|
6274
|
+
mustBeCompleted = true;
|
|
6275
|
+
} else if (key === "forbids_quest") {
|
|
6276
|
+
questId = String(val);
|
|
6277
|
+
mustBeCompleted = false;
|
|
6278
|
+
} else if (key === "npcs") {
|
|
6279
|
+
npcs = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6280
|
+
} else if (key === "objects") {
|
|
6281
|
+
objects = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6282
|
+
} else {
|
|
6283
|
+
properties[key] = val;
|
|
6284
|
+
}
|
|
6285
|
+
if (this.check("COMMA")) this.advance();
|
|
6286
|
+
this.skipNewlines();
|
|
6287
|
+
}
|
|
6288
|
+
this.expect("RBRACE");
|
|
6289
|
+
this.popContext();
|
|
6290
|
+
return {
|
|
6291
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6292
|
+
type: "WorldLayer",
|
|
6293
|
+
name,
|
|
6294
|
+
predicate: { type: "PhasePredicate", kind: "quest_flag", questId, mustBeCompleted },
|
|
6295
|
+
npcs,
|
|
6296
|
+
objects,
|
|
6297
|
+
properties
|
|
6298
|
+
};
|
|
6299
|
+
}
|
|
6300
|
+
/**
|
|
6301
|
+
* Parse a dungeon_instance block (P2.6 — instanced content).
|
|
6302
|
+
*
|
|
6303
|
+
* Syntax:
|
|
6304
|
+
* dungeon_instance shadowfen_keep {
|
|
6305
|
+
* max_instances: 10
|
|
6306
|
+
* party_size: 5
|
|
6307
|
+
* reset_timer: 3600
|
|
6308
|
+
* completion_quest: "shadowfen_cleared"
|
|
6309
|
+
* npcs: ["dungeon_boss"]
|
|
6310
|
+
* }
|
|
6311
|
+
*/
|
|
6312
|
+
parseDungeonInstance() {
|
|
6313
|
+
const startLoc = this.currentLocation();
|
|
6314
|
+
this.pushContext("dungeon-instance");
|
|
6315
|
+
this.advance();
|
|
6316
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6317
|
+
this.expect("LBRACE");
|
|
6318
|
+
this.skipNewlines();
|
|
6319
|
+
const properties = {};
|
|
6320
|
+
let maxInstances = 1;
|
|
6321
|
+
let partySize = 1;
|
|
6322
|
+
let resetTimer = 0;
|
|
6323
|
+
let completionQuest = "";
|
|
6324
|
+
let npcs = [];
|
|
6325
|
+
let objects = [];
|
|
6326
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6327
|
+
this.skipNewlines();
|
|
6328
|
+
if (this.check("RBRACE")) break;
|
|
6329
|
+
const key = this.expectIdentifier();
|
|
6330
|
+
this.expect("COLON");
|
|
6331
|
+
const val = this.parseValue();
|
|
6332
|
+
if (key === "max_instances") maxInstances = Number(val) || 1;
|
|
6333
|
+
else if (key === "party_size") partySize = Number(val) || 1;
|
|
6334
|
+
else if (key === "reset_timer") resetTimer = Number(val) || 0;
|
|
6335
|
+
else if (key === "completion_quest") completionQuest = String(val);
|
|
6336
|
+
else if (key === "npcs") npcs = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6337
|
+
else if (key === "objects")
|
|
6338
|
+
objects = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6339
|
+
else properties[key] = val;
|
|
6340
|
+
if (this.check("COMMA")) this.advance();
|
|
6341
|
+
this.skipNewlines();
|
|
6342
|
+
}
|
|
6343
|
+
this.expect("RBRACE");
|
|
6344
|
+
this.popContext();
|
|
6345
|
+
return {
|
|
6346
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6347
|
+
type: "DungeonInstance",
|
|
6348
|
+
name,
|
|
6349
|
+
maxInstances,
|
|
6350
|
+
partySize,
|
|
6351
|
+
resetTimer,
|
|
6352
|
+
completionQuest,
|
|
6353
|
+
npcs,
|
|
6354
|
+
objects,
|
|
6355
|
+
properties
|
|
6356
|
+
};
|
|
6357
|
+
}
|
|
6358
|
+
/**
|
|
6359
|
+
* Parse a world_shard block (P2.5 — world sharding).
|
|
6360
|
+
*
|
|
6361
|
+
* Syntax:
|
|
6362
|
+
* world_shard north_province {
|
|
6363
|
+
* min: [-1000, 0, -1000]
|
|
6364
|
+
* max: [0, 256, 1000]
|
|
6365
|
+
* neighbors: ["south_province"]
|
|
6366
|
+
* max_players: 200
|
|
6367
|
+
* handoff: "seamless"
|
|
6368
|
+
* }
|
|
6369
|
+
*/
|
|
6370
|
+
parseWorldShard() {
|
|
6371
|
+
const startLoc = this.currentLocation();
|
|
6372
|
+
this.pushContext("world-shard");
|
|
6373
|
+
this.advance();
|
|
6374
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6375
|
+
this.expect("LBRACE");
|
|
6376
|
+
this.skipNewlines();
|
|
6377
|
+
const properties = {};
|
|
6378
|
+
let min = [0, 0, 0];
|
|
6379
|
+
let max = [0, 0, 0];
|
|
6380
|
+
let neighbors = [];
|
|
6381
|
+
let maxPlayers = 100;
|
|
6382
|
+
let handoff = "seamless";
|
|
6383
|
+
const toVec3 = (val) => {
|
|
6384
|
+
const a = (Array.isArray(val) ? val : [val]).map((v) => Number(v) || 0);
|
|
6385
|
+
return [a[0] ?? 0, a[1] ?? 0, a[2] ?? 0];
|
|
6386
|
+
};
|
|
6387
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6388
|
+
this.skipNewlines();
|
|
6389
|
+
if (this.check("RBRACE")) break;
|
|
6390
|
+
const key = this.expectIdentifier();
|
|
6391
|
+
this.expect("COLON");
|
|
6392
|
+
const val = this.parseValue();
|
|
6393
|
+
if (key === "min") min = toVec3(val);
|
|
6394
|
+
else if (key === "max") max = toVec3(val);
|
|
6395
|
+
else if (key === "neighbors")
|
|
6396
|
+
neighbors = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6397
|
+
else if (key === "max_players") maxPlayers = Number(val) || 100;
|
|
6398
|
+
else if (key === "handoff") handoff = String(val);
|
|
6399
|
+
else properties[key] = val;
|
|
6400
|
+
if (this.check("COMMA")) this.advance();
|
|
6401
|
+
this.skipNewlines();
|
|
6402
|
+
}
|
|
6403
|
+
this.expect("RBRACE");
|
|
6404
|
+
this.popContext();
|
|
6405
|
+
return {
|
|
6406
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6407
|
+
type: "WorldShard",
|
|
6408
|
+
name,
|
|
6409
|
+
min,
|
|
6410
|
+
max,
|
|
6411
|
+
neighbors,
|
|
6412
|
+
maxPlayers,
|
|
6413
|
+
handoff,
|
|
6414
|
+
properties
|
|
6415
|
+
};
|
|
6416
|
+
}
|
|
6417
|
+
/**
|
|
6418
|
+
* Parse a spawn_point block.
|
|
6419
|
+
*
|
|
6420
|
+
* Syntax:
|
|
6421
|
+
* spawn_point village_entry {
|
|
6422
|
+
* faction: "neutral"
|
|
6423
|
+
* max_count: 10
|
|
6424
|
+
* respawn_radius: 5
|
|
6425
|
+
* position: (10, 0, 10)
|
|
6426
|
+
* }
|
|
6427
|
+
*/
|
|
6428
|
+
parseSpawnPoint() {
|
|
6429
|
+
const startLoc = this.currentLocation();
|
|
6430
|
+
this.pushContext("spawn-point");
|
|
6431
|
+
this.advance();
|
|
6432
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6433
|
+
this.expect("LBRACE");
|
|
6434
|
+
this.skipNewlines();
|
|
6435
|
+
const properties = {};
|
|
6436
|
+
let faction;
|
|
6437
|
+
let maxCount;
|
|
6438
|
+
let respawnRadius;
|
|
6439
|
+
let position;
|
|
6440
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6441
|
+
this.skipNewlines();
|
|
6442
|
+
if (this.check("RBRACE")) break;
|
|
6443
|
+
const key = this.expectIdentifier();
|
|
6444
|
+
this.expect("COLON");
|
|
6445
|
+
const val = this.parseValue();
|
|
6446
|
+
if (key === "faction") faction = val;
|
|
6447
|
+
else if (key === "max_count") maxCount = val;
|
|
6448
|
+
else if (key === "respawn_radius") respawnRadius = val;
|
|
6449
|
+
else if (key === "position") {
|
|
6450
|
+
if (Array.isArray(val) && val.length >= 3) {
|
|
6451
|
+
position = { x: val[0], y: val[1], z: val[2] };
|
|
6452
|
+
}
|
|
6453
|
+
} else {
|
|
6454
|
+
properties[key] = val;
|
|
6455
|
+
}
|
|
6456
|
+
if (this.check("COMMA")) this.advance();
|
|
6457
|
+
this.skipNewlines();
|
|
6458
|
+
}
|
|
6459
|
+
this.expect("RBRACE");
|
|
6460
|
+
this.popContext();
|
|
6461
|
+
return {
|
|
6462
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6463
|
+
type: "SpawnPoint",
|
|
6464
|
+
name,
|
|
6465
|
+
faction,
|
|
6466
|
+
maxCount,
|
|
6467
|
+
respawnRadius,
|
|
6468
|
+
position,
|
|
6469
|
+
properties
|
|
6470
|
+
};
|
|
6471
|
+
}
|
|
6472
|
+
/**
|
|
6473
|
+
* Parse a trigger block for MMO interaction volumes.
|
|
6474
|
+
*
|
|
6475
|
+
* Syntax:
|
|
6476
|
+
* trigger dungeon_entrance {
|
|
6477
|
+
* radius: 3
|
|
6478
|
+
* faction_filter: ["alliance", "neutral"]
|
|
6479
|
+
* on_enter { emit("dungeon_enter") }
|
|
6480
|
+
* on_exit { emit("dungeon_exit") }
|
|
6481
|
+
* }
|
|
6482
|
+
*/
|
|
6483
|
+
parseGameTrigger() {
|
|
6484
|
+
const startLoc = this.currentLocation();
|
|
6485
|
+
this.pushContext("game-trigger");
|
|
6486
|
+
this.advance();
|
|
6487
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6488
|
+
this.expect("LBRACE");
|
|
6489
|
+
this.skipNewlines();
|
|
6490
|
+
const properties = {};
|
|
6491
|
+
let radius = 1;
|
|
6492
|
+
let factionFilter;
|
|
6493
|
+
let position;
|
|
6494
|
+
const onEnter = [];
|
|
6495
|
+
const onExit = [];
|
|
6496
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6497
|
+
this.skipNewlines();
|
|
6498
|
+
if (this.check("RBRACE")) break;
|
|
6499
|
+
if (this.check("IDENTIFIER") && this.current().value === "on_enter") {
|
|
6500
|
+
this.advance();
|
|
6501
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6502
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6503
|
+
this.advance();
|
|
6504
|
+
this.skipNewlines();
|
|
6505
|
+
const stmts = this.parseStatementBlock();
|
|
6506
|
+
this.expect("RBRACE");
|
|
6507
|
+
return stmts;
|
|
6508
|
+
})() : [];
|
|
6509
|
+
onEnter.push({ type: "EventHandler", event: "on_enter", parameters: params, body });
|
|
6510
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on_exit") {
|
|
6511
|
+
this.advance();
|
|
6512
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6513
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6514
|
+
this.advance();
|
|
6515
|
+
this.skipNewlines();
|
|
6516
|
+
const stmts = this.parseStatementBlock();
|
|
6517
|
+
this.expect("RBRACE");
|
|
6518
|
+
return stmts;
|
|
6519
|
+
})() : [];
|
|
6520
|
+
onExit.push({ type: "EventHandler", event: "on_exit", parameters: params, body });
|
|
6521
|
+
} else {
|
|
6522
|
+
const key = this.expectIdentifier();
|
|
6523
|
+
this.expect("COLON");
|
|
6524
|
+
const val = this.parseValue();
|
|
6525
|
+
if (key === "radius") radius = val;
|
|
6526
|
+
else if (key === "faction_filter")
|
|
6527
|
+
factionFilter = Array.isArray(val) ? val : [val];
|
|
6528
|
+
else if (key === "position") {
|
|
6529
|
+
if (Array.isArray(val) && val.length >= 3) {
|
|
6530
|
+
position = { x: val[0], y: val[1], z: val[2] };
|
|
6531
|
+
}
|
|
6532
|
+
} else {
|
|
6533
|
+
properties[key] = val;
|
|
6534
|
+
}
|
|
6535
|
+
}
|
|
6536
|
+
if (this.check("COMMA")) this.advance();
|
|
6537
|
+
this.skipNewlines();
|
|
6538
|
+
}
|
|
6539
|
+
this.expect("RBRACE");
|
|
6540
|
+
this.popContext();
|
|
6541
|
+
return {
|
|
6542
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6543
|
+
type: "GameTrigger",
|
|
6544
|
+
name,
|
|
6545
|
+
radius,
|
|
6546
|
+
factionFilter,
|
|
6547
|
+
onEnter: onEnter.length > 0 ? onEnter : void 0,
|
|
6548
|
+
onExit: onExit.length > 0 ? onExit : void 0,
|
|
6549
|
+
position,
|
|
6550
|
+
properties
|
|
6551
|
+
};
|
|
6552
|
+
}
|
|
6553
|
+
/**
|
|
6554
|
+
* Parse a scene-level movement path:
|
|
6555
|
+
* movement_path patrol_route { mode: "patrol" loop: true speed: 2.5
|
|
6556
|
+
* waypoints: [[0,0,0],[10,0,0]] easing: "linear" }
|
|
6557
|
+
*/
|
|
6558
|
+
parseMovementPath() {
|
|
6559
|
+
const startLoc = this.currentLocation();
|
|
6560
|
+
this.pushContext("movement-path");
|
|
6561
|
+
this.advance();
|
|
6562
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6563
|
+
this.expect("LBRACE");
|
|
6564
|
+
this.skipNewlines();
|
|
6565
|
+
const properties = {};
|
|
6566
|
+
let mode;
|
|
6567
|
+
let loop;
|
|
6568
|
+
let speed;
|
|
6569
|
+
let waypoints;
|
|
6570
|
+
let easing;
|
|
6571
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6572
|
+
this.skipNewlines();
|
|
6573
|
+
if (this.check("RBRACE")) break;
|
|
6574
|
+
const key = this.expectIdentifier();
|
|
6575
|
+
this.expect("COLON");
|
|
6576
|
+
const val = this.parseValue();
|
|
6577
|
+
if (key === "mode") mode = val;
|
|
6578
|
+
else if (key === "loop") loop = val;
|
|
6579
|
+
else if (key === "speed") speed = val;
|
|
6580
|
+
else if (key === "waypoints") waypoints = val;
|
|
6581
|
+
else if (key === "easing") easing = val;
|
|
6582
|
+
else properties[key] = val;
|
|
6583
|
+
if (this.check("COMMA")) this.advance();
|
|
6584
|
+
this.skipNewlines();
|
|
6585
|
+
}
|
|
6586
|
+
this.expect("RBRACE");
|
|
6587
|
+
this.popContext();
|
|
6588
|
+
return {
|
|
6589
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6590
|
+
type: "MovementPath",
|
|
6591
|
+
name,
|
|
6592
|
+
mode,
|
|
6593
|
+
loop,
|
|
6594
|
+
speed,
|
|
6595
|
+
waypoints,
|
|
6596
|
+
easing,
|
|
6597
|
+
properties
|
|
6598
|
+
};
|
|
6599
|
+
}
|
|
6600
|
+
/**
|
|
6601
|
+
* Parse a scene-level reaction trigger:
|
|
6602
|
+
* reaction_trigger on_player_enter { target: "player" condition: "..."
|
|
6603
|
+
* on_activate { emit("zone_entered") } on_deactivate { ... } cooldown: 2 }
|
|
6604
|
+
*/
|
|
6605
|
+
parseReactionTrigger() {
|
|
6606
|
+
const startLoc = this.currentLocation();
|
|
6607
|
+
this.pushContext("reaction-trigger");
|
|
6608
|
+
this.advance();
|
|
6609
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6610
|
+
this.expect("LBRACE");
|
|
6611
|
+
this.skipNewlines();
|
|
6612
|
+
const properties = {};
|
|
6613
|
+
let target;
|
|
6614
|
+
let condition;
|
|
6615
|
+
let cooldown;
|
|
6616
|
+
const onActivate = [];
|
|
6617
|
+
const onDeactivate = [];
|
|
6618
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6619
|
+
this.skipNewlines();
|
|
6620
|
+
if (this.check("RBRACE")) break;
|
|
6621
|
+
if (this.check("IDENTIFIER") && this.current().value === "on_activate") {
|
|
6622
|
+
this.advance();
|
|
6623
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6624
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6625
|
+
this.advance();
|
|
6626
|
+
this.skipNewlines();
|
|
6627
|
+
const stmts = this.parseStatementBlock();
|
|
6628
|
+
this.expect("RBRACE");
|
|
6629
|
+
return stmts;
|
|
6630
|
+
})() : [];
|
|
6631
|
+
onActivate.push({ type: "EventHandler", event: "on_activate", parameters: params, body });
|
|
6632
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on_deactivate") {
|
|
6633
|
+
this.advance();
|
|
6634
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6635
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6636
|
+
this.advance();
|
|
6637
|
+
this.skipNewlines();
|
|
6638
|
+
const stmts = this.parseStatementBlock();
|
|
6639
|
+
this.expect("RBRACE");
|
|
6640
|
+
return stmts;
|
|
6641
|
+
})() : [];
|
|
6642
|
+
onDeactivate.push({
|
|
6643
|
+
type: "EventHandler",
|
|
6644
|
+
event: "on_deactivate",
|
|
6645
|
+
parameters: params,
|
|
6646
|
+
body
|
|
6647
|
+
});
|
|
6648
|
+
} else {
|
|
6649
|
+
const key = this.expectIdentifier();
|
|
6650
|
+
this.expect("COLON");
|
|
6651
|
+
const val = this.parseValue();
|
|
6652
|
+
if (key === "target") target = val;
|
|
6653
|
+
else if (key === "condition") condition = val;
|
|
6654
|
+
else if (key === "cooldown") cooldown = val;
|
|
6655
|
+
else properties[key] = val;
|
|
6656
|
+
}
|
|
6657
|
+
if (this.check("COMMA")) this.advance();
|
|
6658
|
+
this.skipNewlines();
|
|
6659
|
+
}
|
|
6660
|
+
this.expect("RBRACE");
|
|
6661
|
+
this.popContext();
|
|
6662
|
+
return {
|
|
6663
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6664
|
+
type: "ReactionTrigger",
|
|
6665
|
+
name,
|
|
6666
|
+
target,
|
|
6667
|
+
condition,
|
|
6668
|
+
cooldown,
|
|
6669
|
+
onActivate: onActivate.length > 0 ? onActivate : void 0,
|
|
6670
|
+
onDeactivate: onDeactivate.length > 0 ? onDeactivate : void 0,
|
|
6671
|
+
properties
|
|
6672
|
+
};
|
|
6673
|
+
}
|
|
6674
|
+
// ===========================================================================
|
|
6675
|
+
// NORM LIFECYCLE BLOCKS (v4.5 — March 2026, CRSEC Model)
|
|
6676
|
+
// ===========================================================================
|
|
6677
|
+
/**
|
|
6678
|
+
* Parse a norm block with full CRSEC lifecycle sub-blocks.
|
|
6679
|
+
*
|
|
6680
|
+
* Pattern:
|
|
6681
|
+
* ```
|
|
6682
|
+
* norm "NormName" @trait1 @trait2 {
|
|
6683
|
+
* description: "..."
|
|
6684
|
+
* category: "..."
|
|
6685
|
+
* priority: 8
|
|
6686
|
+
*
|
|
6687
|
+
* creation { ... }
|
|
6688
|
+
* representation { ... }
|
|
6689
|
+
* spreading { ... }
|
|
6690
|
+
* evaluation { ... }
|
|
6691
|
+
* compliance { ... }
|
|
6692
|
+
*
|
|
6693
|
+
* on norm_violated(agent, context) { ... }
|
|
6694
|
+
* }
|
|
6695
|
+
* ```
|
|
6696
|
+
*/
|
|
6697
|
+
parseNormBlock() {
|
|
6698
|
+
const startLoc = this.currentLocation();
|
|
6699
|
+
this.pushContext("norm");
|
|
4990
6700
|
this.advance();
|
|
4991
6701
|
let name = "unnamed";
|
|
4992
6702
|
if (this.check("STRING")) {
|
|
@@ -4994,15 +6704,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4994
6704
|
} else if (this.check("IDENTIFIER")) {
|
|
4995
6705
|
name = this.expectIdentifier();
|
|
4996
6706
|
}
|
|
4997
|
-
const traits =
|
|
4998
|
-
while (this.check("AT") && this.peek(1)?.type === "IDENTIFIER") {
|
|
4999
|
-
this.advance();
|
|
5000
|
-
traits.push(this.current().value);
|
|
5001
|
-
this.advance();
|
|
5002
|
-
if (this.check("LPAREN")) {
|
|
5003
|
-
this.skipParens();
|
|
5004
|
-
}
|
|
5005
|
-
}
|
|
6707
|
+
const traits = this.parseInlineTraitNamesBeforeBlock();
|
|
5006
6708
|
this.expect("LBRACE");
|
|
5007
6709
|
this.skipNewlines();
|
|
5008
6710
|
const properties = {};
|
|
@@ -5056,6 +6758,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5056
6758
|
body
|
|
5057
6759
|
});
|
|
5058
6760
|
}
|
|
6761
|
+
} else if (this.isPropertyName() && this.peek(1)?.type === "LBRACE") {
|
|
6762
|
+
const key = this.parsePropertyKey();
|
|
6763
|
+
properties[key] = this.parseBlockTraitConfig();
|
|
5059
6764
|
} else if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
5060
6765
|
const key = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
5061
6766
|
this.expect("COLON");
|
|
@@ -5135,15 +6840,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5135
6840
|
} else if (this.check("IDENTIFIER")) {
|
|
5136
6841
|
name = this.expectIdentifier();
|
|
5137
6842
|
}
|
|
5138
|
-
const traits =
|
|
5139
|
-
while (this.check("AT") && this.peek(1)?.type === "IDENTIFIER") {
|
|
5140
|
-
this.advance();
|
|
5141
|
-
traits.push(this.current().value);
|
|
5142
|
-
this.advance();
|
|
5143
|
-
if (this.check("LPAREN")) {
|
|
5144
|
-
this.skipParens();
|
|
5145
|
-
}
|
|
5146
|
-
}
|
|
6843
|
+
const traits = this.parseInlineTraitNamesBeforeBlock();
|
|
5147
6844
|
this.expect("LBRACE");
|
|
5148
6845
|
this.skipNewlines();
|
|
5149
6846
|
const properties = {};
|
|
@@ -5185,6 +6882,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5185
6882
|
body
|
|
5186
6883
|
});
|
|
5187
6884
|
}
|
|
6885
|
+
} else if (this.isPropertyName() && this.peek(1)?.type === "LBRACE") {
|
|
6886
|
+
const key = this.parsePropertyKey();
|
|
6887
|
+
properties[key] = this.parseBlockTraitConfig();
|
|
5188
6888
|
} else if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
5189
6889
|
const key = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
5190
6890
|
this.expect("COLON");
|
|
@@ -5209,6 +6909,303 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5209
6909
|
eventHandlers: eventHandlers.length > 0 ? eventHandlers : void 0
|
|
5210
6910
|
};
|
|
5211
6911
|
}
|
|
6912
|
+
// ===========================================================================
|
|
6913
|
+
// SIMULATION CONTRACT BLOCK (v6.3)
|
|
6914
|
+
// ===========================================================================
|
|
6915
|
+
/**
|
|
6916
|
+
* Parse a `sim_contract { ... }` block.
|
|
6917
|
+
*
|
|
6918
|
+
* Syntax:
|
|
6919
|
+
* ```
|
|
6920
|
+
* sim_contract {
|
|
6921
|
+
* precondition "name" { expr }
|
|
6922
|
+
* precondition "name" "description" { expr }
|
|
6923
|
+
* invariant "name" { expr }
|
|
6924
|
+
* receipt { field: type, ... }
|
|
6925
|
+
* }
|
|
6926
|
+
* ```
|
|
6927
|
+
*/
|
|
6928
|
+
parseContractBlock() {
|
|
6929
|
+
const startLoc = this.currentLocation();
|
|
6930
|
+
this.pushContext("sim_contract");
|
|
6931
|
+
this.advance();
|
|
6932
|
+
this.expect("LBRACE");
|
|
6933
|
+
this.skipNewlines();
|
|
6934
|
+
const preconditions = [];
|
|
6935
|
+
const invariants = [];
|
|
6936
|
+
const receipt = {};
|
|
6937
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6938
|
+
this.skipNewlines();
|
|
6939
|
+
if (this.check("RBRACE")) break;
|
|
6940
|
+
const tokenLower = this.current().value.toLowerCase();
|
|
6941
|
+
if ((tokenLower === "precondition" || tokenLower === "invariant") && this.check("IDENTIFIER")) {
|
|
6942
|
+
const clauseKind = tokenLower;
|
|
6943
|
+
this.advance();
|
|
6944
|
+
let clauseName = "unnamed";
|
|
6945
|
+
if (this.check("STRING")) {
|
|
6946
|
+
clauseName = this.expectString();
|
|
6947
|
+
} else if (this.check("IDENTIFIER")) {
|
|
6948
|
+
clauseName = this.expectIdentifier();
|
|
6949
|
+
}
|
|
6950
|
+
let description;
|
|
6951
|
+
if (this.check("STRING")) {
|
|
6952
|
+
description = this.expectString();
|
|
6953
|
+
}
|
|
6954
|
+
let expr = "";
|
|
6955
|
+
if (this.check("LBRACE")) {
|
|
6956
|
+
this.advance();
|
|
6957
|
+
const parts = [];
|
|
6958
|
+
let depth = 1;
|
|
6959
|
+
while (depth > 0 && !this.isAtEnd()) {
|
|
6960
|
+
if (this.check("LBRACE")) depth++;
|
|
6961
|
+
if (this.check("RBRACE")) {
|
|
6962
|
+
depth--;
|
|
6963
|
+
if (depth === 0) break;
|
|
6964
|
+
}
|
|
6965
|
+
parts.push(this.current().value);
|
|
6966
|
+
this.advance();
|
|
6967
|
+
}
|
|
6968
|
+
this.expect("RBRACE");
|
|
6969
|
+
expr = parts.join(" ").trim();
|
|
6970
|
+
}
|
|
6971
|
+
const clause = { name: clauseName, expr };
|
|
6972
|
+
if (description !== void 0) clause.description = description;
|
|
6973
|
+
if (clauseKind === "precondition") {
|
|
6974
|
+
preconditions.push(clause);
|
|
6975
|
+
} else {
|
|
6976
|
+
invariants.push(clause);
|
|
6977
|
+
}
|
|
6978
|
+
} else if (tokenLower === "receipt" && this.check("IDENTIFIER")) {
|
|
6979
|
+
this.advance();
|
|
6980
|
+
if (this.check("LBRACE")) {
|
|
6981
|
+
this.advance();
|
|
6982
|
+
this.skipNewlines();
|
|
6983
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6984
|
+
this.skipNewlines();
|
|
6985
|
+
if (this.check("RBRACE")) break;
|
|
6986
|
+
let fieldName = "";
|
|
6987
|
+
if (this.check("IDENTIFIER")) {
|
|
6988
|
+
fieldName = this.expectIdentifier();
|
|
6989
|
+
} else if (this.check("STRING")) {
|
|
6990
|
+
fieldName = this.expectString();
|
|
6991
|
+
} else {
|
|
6992
|
+
this.advance();
|
|
6993
|
+
continue;
|
|
6994
|
+
}
|
|
6995
|
+
let typeName = "unknown";
|
|
6996
|
+
if (this.check("COLON")) {
|
|
6997
|
+
this.advance();
|
|
6998
|
+
if (this.check("IDENTIFIER")) {
|
|
6999
|
+
typeName = this.expectIdentifier();
|
|
7000
|
+
} else if (this.check("STRING")) {
|
|
7001
|
+
typeName = this.expectString();
|
|
7002
|
+
}
|
|
7003
|
+
}
|
|
7004
|
+
if (fieldName) receipt[fieldName] = typeName;
|
|
7005
|
+
if (this.check("COMMA")) this.advance();
|
|
7006
|
+
this.skipNewlines();
|
|
7007
|
+
}
|
|
7008
|
+
this.expect("RBRACE");
|
|
7009
|
+
}
|
|
7010
|
+
} else {
|
|
7011
|
+
this.advance();
|
|
7012
|
+
}
|
|
7013
|
+
this.skipNewlines();
|
|
7014
|
+
}
|
|
7015
|
+
this.expect("RBRACE");
|
|
7016
|
+
this.popContext();
|
|
7017
|
+
return {
|
|
7018
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7019
|
+
type: "contract",
|
|
7020
|
+
preconditions,
|
|
7021
|
+
invariants,
|
|
7022
|
+
receipt
|
|
7023
|
+
};
|
|
7024
|
+
}
|
|
7025
|
+
// ── Pub/sub messaging primitives (v6.4) ───────────────────────────────────
|
|
7026
|
+
/**
|
|
7027
|
+
* Parse policy_pack Name { ... } as a first-class regulated-AI governance
|
|
7028
|
+
* primitive. Validation lives in policy/PolicyPack.ts so compilers and deploy
|
|
7029
|
+
* gates consume the same schema the parser emits.
|
|
7030
|
+
*/
|
|
7031
|
+
parsePolicyPackBlock() {
|
|
7032
|
+
const startLoc = this.currentLocation();
|
|
7033
|
+
this.pushContext("policy-pack");
|
|
7034
|
+
this.advance();
|
|
7035
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
7036
|
+
this.expect("LBRACE");
|
|
7037
|
+
this.skipNewlines();
|
|
7038
|
+
const properties = {};
|
|
7039
|
+
let version = "1.0.0";
|
|
7040
|
+
let frameworkId = "";
|
|
7041
|
+
let requiredTests = [];
|
|
7042
|
+
let requiredCompileTargets = [];
|
|
7043
|
+
let auditRetention = {};
|
|
7044
|
+
let monitoringCadence = {};
|
|
7045
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7046
|
+
this.skipNewlines();
|
|
7047
|
+
if (this.check("RBRACE")) break;
|
|
7048
|
+
const key = this.expectIdentifier();
|
|
7049
|
+
if ((key === "audit_retention" || key === "auditRetention") && this.check("LBRACE")) {
|
|
7050
|
+
auditRetention = this.parseBlockTraitConfig();
|
|
7051
|
+
} else if ((key === "monitoring" || key === "monitoring_cadence" || key === "monitoringCadence") && this.check("LBRACE")) {
|
|
7052
|
+
monitoringCadence = this.parseBlockTraitConfig();
|
|
7053
|
+
} else {
|
|
7054
|
+
this.expect("COLON");
|
|
7055
|
+
const value = this.parseValue();
|
|
7056
|
+
if (key === "version") version = typeof value === "string" ? value : String(value);
|
|
7057
|
+
else if (key === "framework_id" || key === "frameworkId") {
|
|
7058
|
+
frameworkId = typeof value === "string" ? value : String(value);
|
|
7059
|
+
} else if (key === "required_tests" || key === "requiredTests") {
|
|
7060
|
+
requiredTests = Array.isArray(value) ? value : [value];
|
|
7061
|
+
} else if (key === "required_compile_targets" || key === "requiredCompileTargets") {
|
|
7062
|
+
requiredCompileTargets = (Array.isArray(value) ? value : [value]).map(
|
|
7063
|
+
(target) => String(target)
|
|
7064
|
+
);
|
|
7065
|
+
} else if (key === "audit_retention" || key === "auditRetention") {
|
|
7066
|
+
auditRetention = this.asRecord(value);
|
|
7067
|
+
} else if (key === "monitoring" || key === "monitoring_cadence" || key === "monitoringCadence") {
|
|
7068
|
+
monitoringCadence = this.asRecord(value);
|
|
7069
|
+
} else {
|
|
7070
|
+
properties[key] = value;
|
|
7071
|
+
}
|
|
7072
|
+
}
|
|
7073
|
+
if (this.check("COMMA")) this.advance();
|
|
7074
|
+
this.skipNewlines();
|
|
7075
|
+
}
|
|
7076
|
+
this.expect("RBRACE");
|
|
7077
|
+
this.popContext();
|
|
7078
|
+
return {
|
|
7079
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7080
|
+
type: "PolicyPack",
|
|
7081
|
+
name,
|
|
7082
|
+
version,
|
|
7083
|
+
frameworkId,
|
|
7084
|
+
requiredTests,
|
|
7085
|
+
requiredCompileTargets,
|
|
7086
|
+
auditRetention,
|
|
7087
|
+
monitoringCadence,
|
|
7088
|
+
properties
|
|
7089
|
+
};
|
|
7090
|
+
}
|
|
7091
|
+
asRecord(value) {
|
|
7092
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || "__bind" in value) {
|
|
7093
|
+
return {};
|
|
7094
|
+
}
|
|
7095
|
+
return value;
|
|
7096
|
+
}
|
|
7097
|
+
/** Parse `topic Name { type: "T" broadcast: true }` */
|
|
7098
|
+
parseTopicBlock() {
|
|
7099
|
+
const startLoc = this.currentLocation();
|
|
7100
|
+
this.advance();
|
|
7101
|
+
const name = this.check("IDENTIFIER") ? this.expectIdentifier() : "unnamed";
|
|
7102
|
+
const metadata = {};
|
|
7103
|
+
let dataType;
|
|
7104
|
+
let broadcast;
|
|
7105
|
+
if (this.check("LBRACE")) {
|
|
7106
|
+
this.advance();
|
|
7107
|
+
this.skipNewlines();
|
|
7108
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7109
|
+
this.skipNewlines();
|
|
7110
|
+
if (this.check("RBRACE") || this.check("NEWLINE")) {
|
|
7111
|
+
if (!this.check("RBRACE")) this.advance();
|
|
7112
|
+
continue;
|
|
7113
|
+
}
|
|
7114
|
+
const key = this.current().value;
|
|
7115
|
+
this.advance();
|
|
7116
|
+
if (this.check("COLON")) this.advance();
|
|
7117
|
+
if (key === "type" || key === "dataType") {
|
|
7118
|
+
dataType = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : (this.advance(), void 0);
|
|
7119
|
+
} else if (key === "broadcast") {
|
|
7120
|
+
broadcast = this.current().value === "true";
|
|
7121
|
+
this.advance();
|
|
7122
|
+
} else if (this.check("LBRACE") || this.check("STRING") || this.check("NUMBER") || this.check("IDENTIFIER") || this.check("LBRACKET")) {
|
|
7123
|
+
metadata[key] = this.parseValue();
|
|
7124
|
+
}
|
|
7125
|
+
if (this.check("COMMA")) this.advance();
|
|
7126
|
+
this.skipNewlines();
|
|
7127
|
+
}
|
|
7128
|
+
this.expect("RBRACE");
|
|
7129
|
+
}
|
|
7130
|
+
const topic = {
|
|
7131
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7132
|
+
type: "Topic",
|
|
7133
|
+
name
|
|
7134
|
+
};
|
|
7135
|
+
if (dataType !== void 0) topic.dataType = dataType;
|
|
7136
|
+
if (broadcast !== void 0) topic.broadcast = broadcast;
|
|
7137
|
+
if (Object.keys(metadata).length > 0) topic.metadata = metadata;
|
|
7138
|
+
return topic;
|
|
7139
|
+
}
|
|
7140
|
+
/** Parse `channel Name { from: A to: B capacity: N }` */
|
|
7141
|
+
parseChannelBlock() {
|
|
7142
|
+
const startLoc = this.currentLocation();
|
|
7143
|
+
this.advance();
|
|
7144
|
+
const name = this.check("IDENTIFIER") ? this.expectIdentifier() : "unnamed";
|
|
7145
|
+
const metadata = {};
|
|
7146
|
+
let from;
|
|
7147
|
+
let to;
|
|
7148
|
+
let capacity;
|
|
7149
|
+
if (this.check("LBRACE")) {
|
|
7150
|
+
this.advance();
|
|
7151
|
+
this.skipNewlines();
|
|
7152
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7153
|
+
this.skipNewlines();
|
|
7154
|
+
if (this.check("RBRACE") || this.check("NEWLINE")) {
|
|
7155
|
+
if (!this.check("RBRACE")) this.advance();
|
|
7156
|
+
continue;
|
|
7157
|
+
}
|
|
7158
|
+
const key = this.current().value;
|
|
7159
|
+
this.advance();
|
|
7160
|
+
if (this.check("COLON")) this.advance();
|
|
7161
|
+
if (key === "from") {
|
|
7162
|
+
from = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : void 0;
|
|
7163
|
+
} else if (key === "to") {
|
|
7164
|
+
to = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : void 0;
|
|
7165
|
+
} else if (key === "capacity") {
|
|
7166
|
+
capacity = this.check("NUMBER") ? Number(this.current().value) : void 0;
|
|
7167
|
+
if (capacity !== void 0) this.advance();
|
|
7168
|
+
} else if (this.check("LBRACE") || this.check("STRING") || this.check("NUMBER") || this.check("IDENTIFIER") || this.check("LBRACKET")) {
|
|
7169
|
+
metadata[key] = this.parseValue();
|
|
7170
|
+
}
|
|
7171
|
+
if (this.check("COMMA")) this.advance();
|
|
7172
|
+
this.skipNewlines();
|
|
7173
|
+
}
|
|
7174
|
+
this.expect("RBRACE");
|
|
7175
|
+
}
|
|
7176
|
+
const ch = {
|
|
7177
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7178
|
+
type: "Channel",
|
|
7179
|
+
name
|
|
7180
|
+
};
|
|
7181
|
+
if (from !== void 0) ch.from = from;
|
|
7182
|
+
if (to !== void 0) ch.to = to;
|
|
7183
|
+
if (capacity !== void 0) ch.capacity = capacity;
|
|
7184
|
+
if (Object.keys(metadata).length > 0) ch.metadata = metadata;
|
|
7185
|
+
return ch;
|
|
7186
|
+
}
|
|
7187
|
+
/** Parse `connect Identifier to Identifier [as "edgeType"]` */
|
|
7188
|
+
parseConnectionStmt() {
|
|
7189
|
+
const startLoc = this.currentLocation();
|
|
7190
|
+
this.advance();
|
|
7191
|
+
const from = this.check("IDENTIFIER") ? this.expectIdentifier() : "";
|
|
7192
|
+
if (this.check("IDENTIFIER") && this.current().value === "to") this.advance();
|
|
7193
|
+
const to = this.check("IDENTIFIER") ? this.expectIdentifier() : "";
|
|
7194
|
+
let edgeType;
|
|
7195
|
+
if (this.check("IDENTIFIER") && this.current().value === "as") {
|
|
7196
|
+
this.advance();
|
|
7197
|
+
if (this.check("STRING")) edgeType = this.expectString();
|
|
7198
|
+
else if (this.check("IDENTIFIER")) edgeType = this.expectIdentifier();
|
|
7199
|
+
}
|
|
7200
|
+
const conn = {
|
|
7201
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7202
|
+
type: "Connection",
|
|
7203
|
+
from,
|
|
7204
|
+
to
|
|
7205
|
+
};
|
|
7206
|
+
if (edgeType !== void 0) conn.edgeType = edgeType;
|
|
7207
|
+
return conn;
|
|
7208
|
+
}
|
|
5212
7209
|
/**
|
|
5213
7210
|
* Unified parser for all domain-specific blocks.
|
|
5214
7211
|
* Pattern: KEYWORD NAME @trait1 @trait2 { properties... }
|
|
@@ -5255,27 +7252,27 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5255
7252
|
if (domain === "pipeline" && keyword === "pipeline") {
|
|
5256
7253
|
return this.parsePipelineDomainBlock(name, traits);
|
|
5257
7254
|
}
|
|
7255
|
+
if (token.type === "PCG_GRAPH") {
|
|
7256
|
+
return this.parsePCGGraphDomainBlock(startLoc, name, traits, keyword, domain);
|
|
7257
|
+
}
|
|
5258
7258
|
this.expect("LBRACE");
|
|
5259
7259
|
this.skipNewlines();
|
|
5260
7260
|
const properties = {};
|
|
5261
7261
|
const children = [];
|
|
5262
7262
|
const eventHandlers = [];
|
|
5263
7263
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5264
|
-
this.
|
|
7264
|
+
this.skipBlockMemberSeparators();
|
|
5265
7265
|
if (this.check("RBRACE")) break;
|
|
5266
|
-
if (this.check("OBJECT")
|
|
7266
|
+
if (this.check("OBJECT")) {
|
|
5267
7267
|
children.push(this.parseObject());
|
|
7268
|
+
} else if (this.check("IDENTIFIER") && this.isPrimitiveShape(this.current().value) && this.peek(1).type !== "COLON") {
|
|
7269
|
+
children.push(this.parsePrimitiveObject());
|
|
5268
7270
|
} else if (this.check("IDENTIFIER") && this.current().value.startsWith("on")) {
|
|
5269
7271
|
const evtName = this.current().value;
|
|
5270
7272
|
if (this.tokens[this.pos + 1]?.type === "LPAREN" || this.tokens[this.pos + 1]?.type === "LBRACE") {
|
|
5271
7273
|
this.advance();
|
|
5272
7274
|
if (this.check("LPAREN")) {
|
|
5273
|
-
this.
|
|
5274
|
-
while (!this.check("RPAREN") && !this.isAtEnd()) {
|
|
5275
|
-
this.expectIdentifier();
|
|
5276
|
-
if (this.check("COMMA")) this.advance();
|
|
5277
|
-
}
|
|
5278
|
-
this.expect("RPAREN");
|
|
7275
|
+
this.skipParens();
|
|
5279
7276
|
}
|
|
5280
7277
|
if (this.check("LBRACE")) {
|
|
5281
7278
|
this.skipBlock();
|
|
@@ -5287,13 +7284,51 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5287
7284
|
body: []
|
|
5288
7285
|
});
|
|
5289
7286
|
} else {
|
|
5290
|
-
const key = this.
|
|
7287
|
+
const key = this.parsePropertyKey();
|
|
5291
7288
|
this.expect("COLON");
|
|
5292
7289
|
const value = this.parseValue();
|
|
5293
7290
|
properties[key] = value;
|
|
5294
7291
|
}
|
|
7292
|
+
} else if (this.check("AT")) {
|
|
7293
|
+
this.advance();
|
|
7294
|
+
const traitName = this.parseTraitName();
|
|
7295
|
+
if (traitName) traits.push(traitName);
|
|
7296
|
+
if (this.check("LPAREN") || this.check("LBRACE") || this.check("COLON")) {
|
|
7297
|
+
properties[`@${traitName}`] = this.parseOptionalTraitConfig();
|
|
7298
|
+
}
|
|
7299
|
+
} else if (this.isNamedOrTraitedPropertyBlockStart()) {
|
|
7300
|
+
const { key, value } = this.parseNamedOrTraitedPropertyBlock();
|
|
7301
|
+
properties[key] = value;
|
|
7302
|
+
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
7303
|
+
const key = this.parsePropertyKey();
|
|
7304
|
+
properties[key] = this.parseBlockTraitConfig();
|
|
7305
|
+
} else if (this.isPropertyName() && (this.peek(1).type === "STRING" || this.peek(1).type === "IDENTIFIER") && this.peek(2).type === "LBRACE") {
|
|
7306
|
+
const key = this.parsePropertyKey();
|
|
7307
|
+
const blockName = this.advance().value;
|
|
7308
|
+
properties[key] = {
|
|
7309
|
+
name: blockName,
|
|
7310
|
+
...this.parseBlockTraitConfig()
|
|
7311
|
+
};
|
|
7312
|
+
} else if (this.isPropertyName() && (this.peek(1).type === "ARROW" || this.peek(1).type === "MINUS" && this.peek(2).type === "GREATER")) {
|
|
7313
|
+
const from = this.parsePropertyKey();
|
|
7314
|
+
if (this.check("ARROW")) {
|
|
7315
|
+
this.advance();
|
|
7316
|
+
} else {
|
|
7317
|
+
this.advance();
|
|
7318
|
+
this.advance();
|
|
7319
|
+
}
|
|
7320
|
+
if (domain === "input") {
|
|
7321
|
+
properties[from] = this.parseValue();
|
|
7322
|
+
if (this.check("COMMA")) this.advance();
|
|
7323
|
+
this.skipNewlines();
|
|
7324
|
+
continue;
|
|
7325
|
+
}
|
|
7326
|
+
const to = this.isBarewordPathToken() ? this.parseBarewordPathValue() : "";
|
|
7327
|
+
const existing = properties.connections;
|
|
7328
|
+
const connection = { from, to };
|
|
7329
|
+
properties.connections = Array.isArray(existing) ? [...existing, connection] : [connection];
|
|
5295
7330
|
} else {
|
|
5296
|
-
const key = this.
|
|
7331
|
+
const key = this.parsePropertyKey();
|
|
5297
7332
|
this.expect("COLON");
|
|
5298
7333
|
const value = this.parseValue();
|
|
5299
7334
|
properties[key] = value;
|
|
@@ -5315,6 +7350,90 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5315
7350
|
eventHandlers: eventHandlers.length > 0 ? eventHandlers : void 0
|
|
5316
7351
|
};
|
|
5317
7352
|
}
|
|
7353
|
+
parsePCGGraphDomainBlock(startLoc, name, traits, keyword, domain) {
|
|
7354
|
+
this.expect("LBRACE");
|
|
7355
|
+
this.skipNewlines();
|
|
7356
|
+
const nodes = [];
|
|
7357
|
+
const properties = {
|
|
7358
|
+
nodes
|
|
7359
|
+
};
|
|
7360
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7361
|
+
this.skipNewlines();
|
|
7362
|
+
if (this.check("RBRACE")) break;
|
|
7363
|
+
const token = this.current();
|
|
7364
|
+
const next = this.peek(1);
|
|
7365
|
+
if (next?.type === "COLON" && (token.type === "IDENTIFIER" || token.type === "PCG_GRAPH")) {
|
|
7366
|
+
const key = token.value;
|
|
7367
|
+
this.advance();
|
|
7368
|
+
this.expect("COLON");
|
|
7369
|
+
properties[key] = this.parseValue();
|
|
7370
|
+
} else {
|
|
7371
|
+
const kind = token.value;
|
|
7372
|
+
this.advance();
|
|
7373
|
+
const nodeProperties = {};
|
|
7374
|
+
if (this.check("LPAREN")) {
|
|
7375
|
+
this.parsePCGNodeArgs(kind, nodeProperties);
|
|
7376
|
+
}
|
|
7377
|
+
nodes.push({
|
|
7378
|
+
kind,
|
|
7379
|
+
properties: nodeProperties
|
|
7380
|
+
});
|
|
7381
|
+
}
|
|
7382
|
+
this.skipNewlines();
|
|
7383
|
+
if (this.check("ARROW")) {
|
|
7384
|
+
this.advance();
|
|
7385
|
+
} else if (this.check("MINUS") && this.peek(1).type === "GREATER") {
|
|
7386
|
+
this.advance();
|
|
7387
|
+
this.advance();
|
|
7388
|
+
}
|
|
7389
|
+
if (this.check("COMMA")) this.advance();
|
|
7390
|
+
this.skipNewlines();
|
|
7391
|
+
}
|
|
7392
|
+
this.expect("RBRACE");
|
|
7393
|
+
this.popContext();
|
|
7394
|
+
return {
|
|
7395
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7396
|
+
type: "DomainBlock",
|
|
7397
|
+
domain,
|
|
7398
|
+
keyword,
|
|
7399
|
+
name,
|
|
7400
|
+
traits,
|
|
7401
|
+
properties
|
|
7402
|
+
};
|
|
7403
|
+
}
|
|
7404
|
+
parsePCGNodeArgs(kind, properties) {
|
|
7405
|
+
this.expect("LPAREN");
|
|
7406
|
+
const args = [];
|
|
7407
|
+
while (!this.check("RPAREN") && !this.isAtEnd()) {
|
|
7408
|
+
if (this.check("COMMA")) {
|
|
7409
|
+
this.advance();
|
|
7410
|
+
continue;
|
|
7411
|
+
}
|
|
7412
|
+
if (this.check("IDENTIFIER") && this.peek(1).type === "COLON") {
|
|
7413
|
+
const key = this.expectIdentifier();
|
|
7414
|
+
this.expect("COLON");
|
|
7415
|
+
properties[key] = this.parseValue();
|
|
7416
|
+
} else {
|
|
7417
|
+
args.push(this.parsePCGArgumentValue());
|
|
7418
|
+
}
|
|
7419
|
+
if (this.check("COMMA")) this.advance();
|
|
7420
|
+
}
|
|
7421
|
+
this.expect("RPAREN");
|
|
7422
|
+
if (kind === "scatter") {
|
|
7423
|
+
if (args[0] !== void 0) properties["source_mesh"] = args[0];
|
|
7424
|
+
if (args[1] !== void 0) properties["count"] = args[1];
|
|
7425
|
+
} else if (args.length > 0) {
|
|
7426
|
+
properties["args"] = args;
|
|
7427
|
+
}
|
|
7428
|
+
}
|
|
7429
|
+
parsePCGArgumentValue() {
|
|
7430
|
+
if (this.check("STRING") || this.check("NUMBER") || this.check("BOOLEAN") || this.check("NULL") || this.check("LBRACKET")) {
|
|
7431
|
+
return this.parseValue();
|
|
7432
|
+
}
|
|
7433
|
+
const value = this.current().value;
|
|
7434
|
+
this.advance();
|
|
7435
|
+
return value;
|
|
7436
|
+
}
|
|
5318
7437
|
/**
|
|
5319
7438
|
* Parse a pipeline domain block by extracting the raw body text
|
|
5320
7439
|
* and delegating to PipelineParser for structured AST.
|
|
@@ -5453,6 +7572,10 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5453
7572
|
"SIMULATION",
|
|
5454
7573
|
// Perception & simulation layer
|
|
5455
7574
|
"MATERIAL",
|
|
7575
|
+
"MATERIAL_GRAPH",
|
|
7576
|
+
"LIGHT_FIELD",
|
|
7577
|
+
"NAV_FIELD",
|
|
7578
|
+
"PHYSICS_CONTRACT",
|
|
5456
7579
|
"PBR_MATERIAL",
|
|
5457
7580
|
"UNLIT_MATERIAL",
|
|
5458
7581
|
"SHADER",
|
|
@@ -5463,6 +7586,7 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5463
7586
|
"PARTICLES",
|
|
5464
7587
|
"EMITTER",
|
|
5465
7588
|
"VFX",
|
|
7589
|
+
"PARTICLE_FIELD",
|
|
5466
7590
|
"POST_PROCESSING",
|
|
5467
7591
|
"POST_FX",
|
|
5468
7592
|
"AUDIO_SOURCE",
|
|
@@ -5471,6 +7595,7 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5471
7595
|
"WEATHER",
|
|
5472
7596
|
"ATMOSPHERE",
|
|
5473
7597
|
"PROCEDURAL",
|
|
7598
|
+
"PCG_GRAPH",
|
|
5474
7599
|
"SCATTER",
|
|
5475
7600
|
"LOD_BLOCK",
|
|
5476
7601
|
"RENDER",
|
|
@@ -5540,7 +7665,9 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5540
7665
|
"RETRY_BLOCK",
|
|
5541
7666
|
"TIMEOUT_BLOCK",
|
|
5542
7667
|
"FALLBACK_BLOCK",
|
|
5543
|
-
"BULKHEAD_BLOCK"
|
|
7668
|
+
"BULKHEAD_BLOCK",
|
|
7669
|
+
// MMO/AAA game constructs (v6.2) — real_estate only; others handled by dedicated parsers
|
|
7670
|
+
"REAL_ESTATE"
|
|
5544
7671
|
]);
|
|
5545
7672
|
/** Token → domain type mapping */
|
|
5546
7673
|
_HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
@@ -5582,6 +7709,10 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5582
7709
|
SIMULATION: "simulation",
|
|
5583
7710
|
// Perception & simulation layer
|
|
5584
7711
|
MATERIAL: "material",
|
|
7712
|
+
MATERIAL_GRAPH: "material_graph",
|
|
7713
|
+
LIGHT_FIELD: "light_field",
|
|
7714
|
+
NAV_FIELD: "nav_field",
|
|
7715
|
+
PHYSICS_CONTRACT: "physics_contract",
|
|
5585
7716
|
PBR_MATERIAL: "material",
|
|
5586
7717
|
UNLIT_MATERIAL: "material",
|
|
5587
7718
|
SHADER: "material",
|
|
@@ -5592,6 +7723,7 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5592
7723
|
PARTICLES: "vfx",
|
|
5593
7724
|
EMITTER: "vfx",
|
|
5594
7725
|
VFX: "vfx",
|
|
7726
|
+
PARTICLE_FIELD: "particle_field",
|
|
5595
7727
|
POST_PROCESSING: "postfx",
|
|
5596
7728
|
POST_FX: "postfx",
|
|
5597
7729
|
AUDIO_SOURCE: "audio",
|
|
@@ -5600,6 +7732,7 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5600
7732
|
WEATHER: "weather",
|
|
5601
7733
|
ATMOSPHERE: "weather",
|
|
5602
7734
|
PROCEDURAL: "procedural",
|
|
7735
|
+
PCG_GRAPH: "procedural",
|
|
5603
7736
|
SCATTER: "procedural",
|
|
5604
7737
|
LOD_BLOCK: "rendering",
|
|
5605
7738
|
RENDER: "rendering",
|
|
@@ -5669,7 +7802,9 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5669
7802
|
RETRY_BLOCK: "resilience",
|
|
5670
7803
|
TIMEOUT_BLOCK: "resilience",
|
|
5671
7804
|
FALLBACK_BLOCK: "resilience",
|
|
5672
|
-
BULKHEAD_BLOCK: "resilience"
|
|
7805
|
+
BULKHEAD_BLOCK: "resilience",
|
|
7806
|
+
// MMO/AAA game constructs (v6.2)
|
|
7807
|
+
REAL_ESTATE: "custom"
|
|
5673
7808
|
};
|
|
5674
7809
|
var HoloCompositionParser = _HoloCompositionParser;
|
|
5675
7810
|
function parseHolo(source, options) {
|
|
@@ -5739,6 +7874,6 @@ function parseHoloPartial(source, options) {
|
|
|
5739
7874
|
};
|
|
5740
7875
|
}
|
|
5741
7876
|
|
|
5742
|
-
export { HoloCompositionParser, parseHolo, parseHoloPartial, parseHoloStrict };
|
|
5743
|
-
//# sourceMappingURL=chunk-
|
|
5744
|
-
//# sourceMappingURL=chunk-
|
|
7877
|
+
export { HoloCompositionParser, KEYWORDS, LIGHT_PRIMITIVES, PRIMITIVE_SHAPES, parseHolo, parseHoloPartial, parseHoloStrict };
|
|
7878
|
+
//# sourceMappingURL=chunk-SZOLTWWD.js.map
|
|
7879
|
+
//# sourceMappingURL=chunk-SZOLTWWD.js.map
|