@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,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunk3VBO3IYQ_cjs = require('./chunk-3VBO3IYQ.cjs');
|
|
4
|
+
var chunkOV6HHKLE_cjs = require('./chunk-OV6HHKLE.cjs');
|
|
4
5
|
|
|
5
6
|
// src/parser/TypoDetector.ts
|
|
6
7
|
var TypoDetector = class {
|
|
@@ -172,6 +173,17 @@ var KEYWORDS = {
|
|
|
172
173
|
waypoints: "WAYPOINTS",
|
|
173
174
|
constraint: "CONSTRAINT",
|
|
174
175
|
terrain: "TERRAIN",
|
|
176
|
+
// MMO/AAA game constructs (v6.2)
|
|
177
|
+
loot_table: "LOOT_TABLE",
|
|
178
|
+
world_chunk: "WORLD_CHUNK",
|
|
179
|
+
spawn_point: "SPAWN_POINT",
|
|
180
|
+
game_trigger: "GAME_TRIGGER",
|
|
181
|
+
movement_path: "MOVEMENT_PATH",
|
|
182
|
+
reaction_trigger: "REACTION_TRIGGER",
|
|
183
|
+
world_layer: "WORLD_LAYER",
|
|
184
|
+
dungeon_instance: "DUNGEON_INSTANCE",
|
|
185
|
+
world_shard: "WORLD_SHARD",
|
|
186
|
+
real_estate: "REAL_ESTATE",
|
|
175
187
|
// IoT / Digital Twin
|
|
176
188
|
sensor: "IOT_SENSOR",
|
|
177
189
|
device: "IOT_DEVICE",
|
|
@@ -252,6 +264,10 @@ var KEYWORDS = {
|
|
|
252
264
|
bridge: "WEB3_CONTRACT",
|
|
253
265
|
// Perception & simulation layer (v4.2 — March 2026)
|
|
254
266
|
material: "MATERIAL",
|
|
267
|
+
material_graph: "MATERIAL_GRAPH",
|
|
268
|
+
light_field: "LIGHT_FIELD",
|
|
269
|
+
nav_field: "NAV_FIELD",
|
|
270
|
+
physics_contract: "PHYSICS_CONTRACT",
|
|
255
271
|
pbr_material: "PBR_MATERIAL",
|
|
256
272
|
unlit_material: "UNLIT_MATERIAL",
|
|
257
273
|
shader: "SHADER",
|
|
@@ -273,6 +289,7 @@ var KEYWORDS = {
|
|
|
273
289
|
particles: "PARTICLES",
|
|
274
290
|
emitter: "EMITTER",
|
|
275
291
|
vfx: "VFX",
|
|
292
|
+
particle_field: "PARTICLE_FIELD",
|
|
276
293
|
post_processing: "POST_PROCESSING",
|
|
277
294
|
post_fx: "POST_FX",
|
|
278
295
|
render_pipeline: "POST_PROCESSING",
|
|
@@ -288,6 +305,7 @@ var KEYWORDS = {
|
|
|
288
305
|
climate: "WEATHER",
|
|
289
306
|
simulation: "SIMULATION",
|
|
290
307
|
procedural: "PROCEDURAL",
|
|
308
|
+
pcg_graph: "PCG_GRAPH",
|
|
291
309
|
generate: "PROCEDURAL",
|
|
292
310
|
scatter: "SCATTER",
|
|
293
311
|
distribute: "SCATTER",
|
|
@@ -331,6 +349,11 @@ var KEYWORDS = {
|
|
|
331
349
|
payment_gate: "PAYMENT_GATE",
|
|
332
350
|
subscription: "SUBSCRIPTION",
|
|
333
351
|
tip_jar: "TIP_JAR",
|
|
352
|
+
// SimulationContract block (v6.3 — NORTH_STAR thesis: simulation IS the proof)
|
|
353
|
+
sim_contract: "HOLO_CONTRACT",
|
|
354
|
+
// Pub/sub messaging primitives (v6.4)
|
|
355
|
+
topic: "HOLO_TOPIC",
|
|
356
|
+
channel: "HOLO_CHANNEL",
|
|
334
357
|
// v6 Universal domains (v5.4 — Domains Unified)
|
|
335
358
|
service: "SERVICE_BLOCK",
|
|
336
359
|
endpoint: "ENDPOINT_BLOCK",
|
|
@@ -762,6 +785,7 @@ var KEYWORDS_AS_IDENTIFIERS = [
|
|
|
762
785
|
"EFFECTS",
|
|
763
786
|
"CAMERA",
|
|
764
787
|
"BIND",
|
|
788
|
+
"CONNECT",
|
|
765
789
|
"TIMELINE",
|
|
766
790
|
"AUDIO",
|
|
767
791
|
"ZONE",
|
|
@@ -794,7 +818,9 @@ var KEYWORDS_AS_IDENTIFIERS = [
|
|
|
794
818
|
"COMPOSITION",
|
|
795
819
|
"SPATIAL_GROUP",
|
|
796
820
|
"SPATIAL_AGENT",
|
|
797
|
-
"SPATIAL_CONTAINER"
|
|
821
|
+
"SPATIAL_CONTAINER",
|
|
822
|
+
"HOLO_TOPIC",
|
|
823
|
+
"HOLO_CHANNEL"
|
|
798
824
|
];
|
|
799
825
|
function isKeywordAsIdentifierType(api, type) {
|
|
800
826
|
if (api.DOMAIN_TOKENS.has(type)) return true;
|
|
@@ -1050,7 +1076,6 @@ function parseObjectExpression(api) {
|
|
|
1050
1076
|
|
|
1051
1077
|
// src/parser/HoloCompositionParser.ts
|
|
1052
1078
|
var _HoloCompositionParser = class _HoloCompositionParser {
|
|
1053
|
-
// Track parsing context for better errors
|
|
1054
1079
|
constructor(options = {}) {
|
|
1055
1080
|
this.tokens = [];
|
|
1056
1081
|
this.pos = 0;
|
|
@@ -1063,6 +1088,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1063
1088
|
strict: false,
|
|
1064
1089
|
...options
|
|
1065
1090
|
};
|
|
1091
|
+
this.errorRecovery = new chunkOV6HHKLE_cjs.ErrorRecovery(this.options.knownTraits);
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* The error-recovery engine for this parser, seeded with the injected
|
|
1095
|
+
* `knownTraits` union when one was supplied via parser options. Exposed so
|
|
1096
|
+
* tooling (and tests) can verify the trait-vocabulary seam is wired through.
|
|
1097
|
+
*/
|
|
1098
|
+
getErrorRecovery() {
|
|
1099
|
+
return this.errorRecovery;
|
|
1066
1100
|
}
|
|
1067
1101
|
/** Instance accessor for the static DOMAIN_TOKENS set — satisfies ExpressionParserApi. */
|
|
1068
1102
|
get DOMAIN_TOKENS() {
|
|
@@ -1137,7 +1171,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1137
1171
|
domainBlocks: [],
|
|
1138
1172
|
// v4.5 additions — CRSEC norm lifecycle
|
|
1139
1173
|
norms: [],
|
|
1140
|
-
metanorms: []
|
|
1174
|
+
metanorms: [],
|
|
1175
|
+
// v6.2 additions — MMO/AAA game constructs
|
|
1176
|
+
spawnPoints: [],
|
|
1177
|
+
triggers: [],
|
|
1178
|
+
lootTables: [],
|
|
1179
|
+
worldChunks: [],
|
|
1180
|
+
worldLayers: [],
|
|
1181
|
+
dungeonInstances: [],
|
|
1182
|
+
worldShards: [],
|
|
1183
|
+
movementPaths: [],
|
|
1184
|
+
reactionTriggers: [],
|
|
1185
|
+
policyPacks: []
|
|
1141
1186
|
};
|
|
1142
1187
|
while (!this.isAtEnd()) {
|
|
1143
1188
|
try {
|
|
@@ -1181,8 +1226,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1181
1226
|
} else if (decoratorName === "state") {
|
|
1182
1227
|
composition.state = this.parseStateBody();
|
|
1183
1228
|
} else if (decoratorName === "state_machine") {
|
|
1229
|
+
const name = this.parseOptionalStateMachineName("implicit");
|
|
1184
1230
|
if (this.check("LBRACE")) {
|
|
1185
|
-
composition.stateMachines.push(this.parseStateMachineFromDecorator());
|
|
1231
|
+
composition.stateMachines.push(this.parseStateMachineFromDecorator(name));
|
|
1186
1232
|
}
|
|
1187
1233
|
} else {
|
|
1188
1234
|
composition.traits = composition.traits || [];
|
|
@@ -1212,7 +1258,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1212
1258
|
composition.logic = this.parseLogic();
|
|
1213
1259
|
} else if (this.check("TIMELINE")) {
|
|
1214
1260
|
composition.timelines.push(this.parseTimeline());
|
|
1215
|
-
} else if (this.check("STATE")) {
|
|
1261
|
+
} else if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
1216
1262
|
composition.state = this.parseState();
|
|
1217
1263
|
} else if (this.check("IMPORT")) {
|
|
1218
1264
|
composition.imports.push(this.parseImport());
|
|
@@ -1247,8 +1293,53 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1247
1293
|
composition.norms.push(this.parseNormBlock());
|
|
1248
1294
|
} else if (this.check("METANORM")) {
|
|
1249
1295
|
composition.metanorms.push(this.parseMetanormBlock());
|
|
1296
|
+
} else if (this.check("HOLO_CONTRACT")) {
|
|
1297
|
+
composition.contract = this.parseContractBlock();
|
|
1298
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "policy_pack") {
|
|
1299
|
+
composition.policyPacks.push(this.parsePolicyPackBlock());
|
|
1300
|
+
} else if (this.check("HOLO_TOPIC")) {
|
|
1301
|
+
if (!composition.topics) composition.topics = [];
|
|
1302
|
+
composition.topics.push(this.parseTopicBlock());
|
|
1303
|
+
} else if (this.check("HOLO_CHANNEL")) {
|
|
1304
|
+
if (!composition.channels) composition.channels = [];
|
|
1305
|
+
composition.channels.push(this.parseChannelBlock());
|
|
1306
|
+
} else if (this.check("CONNECT")) {
|
|
1307
|
+
if (!composition.connections) composition.connections = [];
|
|
1308
|
+
composition.connections.push(this.parseConnectionStmt());
|
|
1309
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "shareplay") {
|
|
1310
|
+
composition.metadata = {
|
|
1311
|
+
...composition.metadata ?? {},
|
|
1312
|
+
shareplay: this.parseSharePlayBlock()
|
|
1313
|
+
};
|
|
1314
|
+
} else if (this.isLooseOnHandlerStart()) {
|
|
1315
|
+
this.skipLooseOnHandler();
|
|
1316
|
+
} else if (this.check("LOOT_TABLE")) {
|
|
1317
|
+
composition.lootTables.push(this.parseLootTable());
|
|
1318
|
+
} else if (this.check("WORLD_CHUNK")) {
|
|
1319
|
+
composition.worldChunks.push(this.parseWorldChunk());
|
|
1320
|
+
} else if (this.check("SPAWN_POINT")) {
|
|
1321
|
+
composition.spawnPoints.push(this.parseSpawnPoint());
|
|
1322
|
+
} else if (this.check("GAME_TRIGGER")) {
|
|
1323
|
+
composition.triggers.push(this.parseGameTrigger());
|
|
1324
|
+
} else if (this.check("MOVEMENT_PATH")) {
|
|
1325
|
+
composition.movementPaths.push(this.parseMovementPath());
|
|
1326
|
+
} else if (this.check("REACTION_TRIGGER")) {
|
|
1327
|
+
composition.reactionTriggers.push(this.parseReactionTrigger());
|
|
1328
|
+
} else if (this.check("WORLD_LAYER")) {
|
|
1329
|
+
composition.worldLayers.push(this.parseWorldLayer());
|
|
1330
|
+
} else if (this.check("DUNGEON_INSTANCE")) {
|
|
1331
|
+
composition.dungeonInstances.push(this.parseDungeonInstance());
|
|
1332
|
+
} else if (this.check("WORLD_SHARD")) {
|
|
1333
|
+
composition.worldShards.push(this.parseWorldShard());
|
|
1334
|
+
} else if (this.check("REAL_ESTATE")) {
|
|
1335
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1336
|
+
} else if (this.check("SCENE")) {
|
|
1337
|
+
if (!composition.scenes) composition.scenes = [];
|
|
1338
|
+
composition.scenes.push(this.parseScene());
|
|
1250
1339
|
} else if (this.isDomainBlockToken()) {
|
|
1251
1340
|
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1341
|
+
} else if (this.isLooseDomainBlockStart() || this.isLooseNamedDomainBlockStart()) {
|
|
1342
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1252
1343
|
} else if (this.check("MODULE")) {
|
|
1253
1344
|
this.advance();
|
|
1254
1345
|
if (this.check("STRING")) this.expectString();
|
|
@@ -1304,12 +1395,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1304
1395
|
this.expect("LBRACE");
|
|
1305
1396
|
this.skipNewlines();
|
|
1306
1397
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1307
|
-
this.
|
|
1398
|
+
this.skipBlockMemberSeparators();
|
|
1308
1399
|
if (this.check("RBRACE")) break;
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1400
|
+
if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
1401
|
+
const key = this.parsePropertyKey();
|
|
1402
|
+
const value = this.parseBlockTraitConfig();
|
|
1403
|
+
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1404
|
+
} else {
|
|
1405
|
+
const key = this.parsePropertyKey();
|
|
1406
|
+
this.expect("COLON");
|
|
1407
|
+
const value = this.parseValue();
|
|
1408
|
+
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1409
|
+
}
|
|
1313
1410
|
this.skipNewlines();
|
|
1314
1411
|
}
|
|
1315
1412
|
this.expect("RBRACE");
|
|
@@ -1339,15 +1436,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1339
1436
|
this.expect("LBRACE");
|
|
1340
1437
|
this.skipNewlines();
|
|
1341
1438
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1342
|
-
this.
|
|
1439
|
+
this.skipBlockMemberSeparators();
|
|
1343
1440
|
if (this.check("RBRACE")) break;
|
|
1344
1441
|
if (this.check("AT")) {
|
|
1345
1442
|
this.advance();
|
|
1346
1443
|
const traitName = this.expectIdentifier();
|
|
1347
1444
|
const config = this.parseOptionalTraitConfig();
|
|
1348
1445
|
traits.push({ type: "ObjectTrait", name: traitName, config });
|
|
1349
|
-
} else if (this.
|
|
1350
|
-
const key = this.
|
|
1446
|
+
} else if (this.isPropertyName()) {
|
|
1447
|
+
const key = this.parsePropertyKey();
|
|
1351
1448
|
if (this.check("COLON")) {
|
|
1352
1449
|
this.advance();
|
|
1353
1450
|
properties.push({ type: "ObjectProperty", key, value: this.parseValue() });
|
|
@@ -1435,13 +1532,31 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1435
1532
|
domainBlocks: [],
|
|
1436
1533
|
// v4.5 additions — CRSEC norm lifecycle
|
|
1437
1534
|
norms: [],
|
|
1438
|
-
metanorms: []
|
|
1535
|
+
metanorms: [],
|
|
1536
|
+
// v6.2 additions — MMO/AAA game constructs
|
|
1537
|
+
spawnPoints: [],
|
|
1538
|
+
triggers: [],
|
|
1539
|
+
lootTables: [],
|
|
1540
|
+
worldChunks: [],
|
|
1541
|
+
worldLayers: [],
|
|
1542
|
+
dungeonInstances: [],
|
|
1543
|
+
worldShards: [],
|
|
1544
|
+
movementPaths: [],
|
|
1545
|
+
reactionTriggers: [],
|
|
1546
|
+
policyPacks: []
|
|
1439
1547
|
};
|
|
1440
1548
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1441
1549
|
try {
|
|
1442
|
-
this.
|
|
1550
|
+
this.skipBlockMemberSeparators();
|
|
1443
1551
|
if (this.check("RBRACE")) break;
|
|
1444
|
-
if (this.check("
|
|
1552
|
+
if (this.peek(1).type === "COLON" && (this.isPropertyName() || this.check("METADATA_BLOCK"))) {
|
|
1553
|
+
const key = this.advance().value;
|
|
1554
|
+
this.advance();
|
|
1555
|
+
const value = !this.check("RBRACE") && !this.isAtEnd() ? this.parseValue() : null;
|
|
1556
|
+
if (key === "metadata" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
1557
|
+
composition.metadata = { ...composition.metadata ?? {}, ...value };
|
|
1558
|
+
}
|
|
1559
|
+
} else if (this.check("IMPORT")) {
|
|
1445
1560
|
composition.imports.push(this.parseImport());
|
|
1446
1561
|
} else if (this.check("THEME")) {
|
|
1447
1562
|
composition.theme = this.parseTheme();
|
|
@@ -1450,7 +1565,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1450
1565
|
} else if (this.check("SCENE")) {
|
|
1451
1566
|
if (!composition.scenes) composition.scenes = [];
|
|
1452
1567
|
composition.scenes.push(this.parseScene());
|
|
1453
|
-
} else if (this.check("STATE")) {
|
|
1568
|
+
} else if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
1454
1569
|
composition.state = this.parseState();
|
|
1455
1570
|
} else if (this.check("METADATA_BLOCK")) {
|
|
1456
1571
|
this.advance();
|
|
@@ -1522,8 +1637,48 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1522
1637
|
composition.norms.push(this.parseNormBlock());
|
|
1523
1638
|
} else if (this.check("METANORM")) {
|
|
1524
1639
|
composition.metanorms.push(this.parseMetanormBlock());
|
|
1640
|
+
} else if (this.check("HOLO_CONTRACT")) {
|
|
1641
|
+
composition.contract = this.parseContractBlock();
|
|
1642
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "policy_pack") {
|
|
1643
|
+
composition.policyPacks.push(this.parsePolicyPackBlock());
|
|
1644
|
+
} else if (this.check("HOLO_TOPIC")) {
|
|
1645
|
+
if (!composition.topics) composition.topics = [];
|
|
1646
|
+
composition.topics.push(this.parseTopicBlock());
|
|
1647
|
+
} else if (this.check("HOLO_CHANNEL")) {
|
|
1648
|
+
if (!composition.channels) composition.channels = [];
|
|
1649
|
+
composition.channels.push(this.parseChannelBlock());
|
|
1650
|
+
} else if (this.check("CONNECT")) {
|
|
1651
|
+
if (!composition.connections) composition.connections = [];
|
|
1652
|
+
composition.connections.push(this.parseConnectionStmt());
|
|
1653
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "shareplay") {
|
|
1654
|
+
composition.metadata = {
|
|
1655
|
+
...composition.metadata ?? {},
|
|
1656
|
+
shareplay: this.parseSharePlayBlock()
|
|
1657
|
+
};
|
|
1658
|
+
} else if (this.check("LOOT_TABLE")) {
|
|
1659
|
+
composition.lootTables.push(this.parseLootTable());
|
|
1660
|
+
} else if (this.check("WORLD_CHUNK")) {
|
|
1661
|
+
composition.worldChunks.push(this.parseWorldChunk());
|
|
1662
|
+
} else if (this.check("SPAWN_POINT")) {
|
|
1663
|
+
composition.spawnPoints.push(this.parseSpawnPoint());
|
|
1664
|
+
} else if (this.check("GAME_TRIGGER")) {
|
|
1665
|
+
composition.triggers.push(this.parseGameTrigger());
|
|
1666
|
+
} else if (this.check("MOVEMENT_PATH")) {
|
|
1667
|
+
composition.movementPaths.push(this.parseMovementPath());
|
|
1668
|
+
} else if (this.check("REACTION_TRIGGER")) {
|
|
1669
|
+
composition.reactionTriggers.push(this.parseReactionTrigger());
|
|
1670
|
+
} else if (this.check("WORLD_LAYER")) {
|
|
1671
|
+
composition.worldLayers.push(this.parseWorldLayer());
|
|
1672
|
+
} else if (this.check("DUNGEON_INSTANCE")) {
|
|
1673
|
+
composition.dungeonInstances.push(this.parseDungeonInstance());
|
|
1674
|
+
} else if (this.check("WORLD_SHARD")) {
|
|
1675
|
+
composition.worldShards.push(this.parseWorldShard());
|
|
1676
|
+
} else if (this.check("REAL_ESTATE")) {
|
|
1677
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1525
1678
|
} else if (this.isDomainBlockToken()) {
|
|
1526
1679
|
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1680
|
+
} else if (this.isLooseDomainBlockStart() || this.isLooseNamedDomainBlockStart()) {
|
|
1681
|
+
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1527
1682
|
} else if (this.check("MODULE")) {
|
|
1528
1683
|
composition.domainBlocks.push(this.parseDomainBlock());
|
|
1529
1684
|
} else if (this.check("AT")) {
|
|
@@ -1564,8 +1719,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1564
1719
|
} else if (decoratorName === "world" || decoratorName === "environment") {
|
|
1565
1720
|
composition.environment = this.parseEnvironmentBody();
|
|
1566
1721
|
} else if (decoratorName === "state_machine") {
|
|
1722
|
+
const name2 = this.parseOptionalStateMachineName("implicit");
|
|
1567
1723
|
if (this.check("LBRACE")) {
|
|
1568
|
-
composition.stateMachines.push(this.parseStateMachineFromDecorator());
|
|
1724
|
+
composition.stateMachines.push(this.parseStateMachineFromDecorator(name2));
|
|
1569
1725
|
}
|
|
1570
1726
|
} else {
|
|
1571
1727
|
composition.traits = composition.traits || [];
|
|
@@ -1576,6 +1732,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1576
1732
|
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
1577
1733
|
composition.actions = composition.actions || [];
|
|
1578
1734
|
composition.actions.push(this.parseAction());
|
|
1735
|
+
} else if (this.check("FUNCTION")) {
|
|
1736
|
+
this.skipFunctionDeclaration();
|
|
1579
1737
|
} else if (this.check("USING")) {
|
|
1580
1738
|
this.advance();
|
|
1581
1739
|
if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
|
|
@@ -1583,27 +1741,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1583
1741
|
this.advance();
|
|
1584
1742
|
if (this.check("IDENTIFIER")) this.advance();
|
|
1585
1743
|
}
|
|
1586
|
-
} else if (this.
|
|
1587
|
-
|
|
1588
|
-
this.advance();
|
|
1589
|
-
this.advance();
|
|
1590
|
-
while (this.check("DOT")) {
|
|
1591
|
-
this.advance();
|
|
1592
|
-
if (this.check("IDENTIFIER")) this.advance();
|
|
1593
|
-
}
|
|
1594
|
-
let parameters = [];
|
|
1595
|
-
if (this.check("LPAREN")) {
|
|
1596
|
-
parameters = this.parseParameterList();
|
|
1597
|
-
}
|
|
1598
|
-
if (this.check("LBRACE")) this.skipBlock();
|
|
1599
|
-
composition.eventHandlers = composition.eventHandlers || [];
|
|
1600
|
-
composition.eventHandlers.push({
|
|
1601
|
-
type: "EventHandler",
|
|
1602
|
-
event: eventName,
|
|
1603
|
-
parameters,
|
|
1604
|
-
body: []
|
|
1605
|
-
// Skipped body
|
|
1606
|
-
});
|
|
1744
|
+
} else if (this.isLooseOnHandlerStart()) {
|
|
1745
|
+
this.skipLooseOnHandler();
|
|
1607
1746
|
} else if (this.check("COLON")) {
|
|
1608
1747
|
this.advance();
|
|
1609
1748
|
if (!this.check("RBRACE") && !this.isAtEnd()) this.parseValue();
|
|
@@ -1632,6 +1771,10 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1632
1771
|
if (this.check("COLON")) {
|
|
1633
1772
|
this.advance();
|
|
1634
1773
|
if (!this.check("RBRACE") && !this.isAtEnd()) this.parseValue();
|
|
1774
|
+
} else if (this.check("LBRACKET")) {
|
|
1775
|
+
this.advance();
|
|
1776
|
+
while (!this.check("RBRACKET") && !this.isAtEnd()) this.advance();
|
|
1777
|
+
if (this.check("RBRACKET")) this.advance();
|
|
1635
1778
|
} else {
|
|
1636
1779
|
if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
|
|
1637
1780
|
if (this.check("LPAREN")) this.skipParens();
|
|
@@ -1780,7 +1923,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1780
1923
|
this.skipNewlines();
|
|
1781
1924
|
const properties = [];
|
|
1782
1925
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1783
|
-
this.
|
|
1926
|
+
this.skipBlockMemberSeparators();
|
|
1784
1927
|
if (this.check("RBRACE")) break;
|
|
1785
1928
|
if (this.check("PARTICLES") || this.check("PARTICLE_SYSTEM")) {
|
|
1786
1929
|
const ps = this.parseParticleSystem();
|
|
@@ -1789,15 +1932,16 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1789
1932
|
key: ps.name,
|
|
1790
1933
|
value: ps
|
|
1791
1934
|
});
|
|
1935
|
+
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
1936
|
+
const key = this.parsePropertyKey();
|
|
1937
|
+
const value = this.parseBlockTraitConfig();
|
|
1938
|
+
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1792
1939
|
} else {
|
|
1793
|
-
const key = this.
|
|
1940
|
+
const key = this.parsePropertyKey();
|
|
1794
1941
|
this.expect("COLON");
|
|
1795
1942
|
const value = this.parseValue();
|
|
1796
1943
|
properties.push({ type: "EnvironmentProperty", key, value });
|
|
1797
1944
|
}
|
|
1798
|
-
if (this.check("SEMICOLON")) {
|
|
1799
|
-
this.advance();
|
|
1800
|
-
}
|
|
1801
1945
|
this.skipNewlines();
|
|
1802
1946
|
}
|
|
1803
1947
|
this.expect("RBRACE");
|
|
@@ -1827,14 +1971,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1827
1971
|
let environment;
|
|
1828
1972
|
const objects = [];
|
|
1829
1973
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1830
|
-
this.
|
|
1974
|
+
this.skipBlockMemberSeparators();
|
|
1831
1975
|
if (this.check("RBRACE")) break;
|
|
1832
1976
|
if (this.check("ENVIRONMENT")) {
|
|
1833
1977
|
environment = this.parseEnvironment();
|
|
1834
1978
|
} else if (this.check("OBJECT")) {
|
|
1835
1979
|
objects.push(this.parseObject());
|
|
1980
|
+
} else if (this.check("LBRACE")) {
|
|
1981
|
+
this.skipBlock();
|
|
1836
1982
|
} else {
|
|
1837
1983
|
this.advance();
|
|
1984
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) this.advance();
|
|
1985
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
1986
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
1838
1987
|
}
|
|
1839
1988
|
}
|
|
1840
1989
|
this.expect("RBRACE");
|
|
@@ -1858,7 +2007,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1858
2007
|
this.skipNewlines();
|
|
1859
2008
|
const properties = {};
|
|
1860
2009
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1861
|
-
this.
|
|
2010
|
+
this.skipBlockMemberSeparators();
|
|
1862
2011
|
if (this.check("RBRACE")) break;
|
|
1863
2012
|
const key = this.expectIdentifier();
|
|
1864
2013
|
this.expect("COLON");
|
|
@@ -1896,24 +2045,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1896
2045
|
this.advance();
|
|
1897
2046
|
}
|
|
1898
2047
|
}
|
|
2048
|
+
const inlineTraitProperties = [];
|
|
2049
|
+
while (this.check("AT")) {
|
|
2050
|
+
inlineTraitProperties.push(this.parseTraitAsLightProperty(true));
|
|
2051
|
+
}
|
|
1899
2052
|
this.expect("LBRACE");
|
|
1900
2053
|
this.skipNewlines();
|
|
1901
|
-
const properties = [];
|
|
2054
|
+
const properties = [...inlineTraitProperties];
|
|
1902
2055
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1903
|
-
this.
|
|
2056
|
+
this.skipBlockMemberSeparators();
|
|
1904
2057
|
if (this.check("RBRACE")) break;
|
|
1905
2058
|
if (this.check("AT")) {
|
|
1906
|
-
this.
|
|
1907
|
-
const traitName = this.parseTraitName();
|
|
1908
|
-
const cfg = this.parseOptionalTraitConfig();
|
|
1909
|
-
const cfgKeys = Object.keys(cfg);
|
|
1910
|
-
let traitValue;
|
|
1911
|
-
if (cfgKeys.length === 0) traitValue = true;
|
|
1912
|
-
else if (cfgKeys.every((k) => /^_arg\d+$/.test(k))) {
|
|
1913
|
-
const arr = cfgKeys.sort().map((k) => cfg[k]);
|
|
1914
|
-
traitValue = arr.length === 1 ? arr[0] : arr;
|
|
1915
|
-
} else traitValue = cfg;
|
|
1916
|
-
properties.push({ type: "LightProperty", key: traitName, value: traitValue });
|
|
2059
|
+
properties.push(this.parseTraitAsLightProperty());
|
|
1917
2060
|
this.skipNewlines();
|
|
1918
2061
|
continue;
|
|
1919
2062
|
}
|
|
@@ -1949,6 +2092,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1949
2092
|
properties
|
|
1950
2093
|
};
|
|
1951
2094
|
}
|
|
2095
|
+
parseTraitAsLightProperty(requireBodyAfterBareBrace = false) {
|
|
2096
|
+
this.expect("AT");
|
|
2097
|
+
const traitName = this.parseTraitName();
|
|
2098
|
+
const cfg = this.parseOptionalTraitConfig(requireBodyAfterBareBrace);
|
|
2099
|
+
const cfgKeys = Object.keys(cfg);
|
|
2100
|
+
let traitValue;
|
|
2101
|
+
if (cfgKeys.length === 0) traitValue = true;
|
|
2102
|
+
else if (cfgKeys.every((k) => /^_arg\d+$/.test(k))) {
|
|
2103
|
+
const arr = cfgKeys.sort().map((k) => cfg[k]);
|
|
2104
|
+
traitValue = arr.length === 1 ? arr[0] : arr;
|
|
2105
|
+
} else traitValue = cfg;
|
|
2106
|
+
return { type: "LightProperty", key: traitName, value: traitValue };
|
|
2107
|
+
}
|
|
1952
2108
|
// ===========================================================================
|
|
1953
2109
|
// EFFECTS (post-processing block)
|
|
1954
2110
|
// ===========================================================================
|
|
@@ -1959,14 +2115,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
1959
2115
|
this.skipNewlines();
|
|
1960
2116
|
const effects = [];
|
|
1961
2117
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1962
|
-
this.
|
|
2118
|
+
this.skipBlockMemberSeparators();
|
|
1963
2119
|
if (this.check("RBRACE")) break;
|
|
1964
2120
|
const effectType = this.expectIdentifier();
|
|
1965
2121
|
this.expect("LBRACE");
|
|
1966
2122
|
this.skipNewlines();
|
|
1967
2123
|
const properties = {};
|
|
1968
2124
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
1969
|
-
this.
|
|
2125
|
+
this.skipBlockMemberSeparators();
|
|
1970
2126
|
if (this.check("RBRACE")) break;
|
|
1971
2127
|
const key = this.expectIdentifier();
|
|
1972
2128
|
this.expect("COLON");
|
|
@@ -2008,7 +2164,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2008
2164
|
this.skipNewlines();
|
|
2009
2165
|
const properties = [];
|
|
2010
2166
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2011
|
-
this.
|
|
2167
|
+
this.skipBlockMemberSeparators();
|
|
2012
2168
|
if (this.check("RBRACE")) break;
|
|
2013
2169
|
if (this.check("AT")) {
|
|
2014
2170
|
this.advance();
|
|
@@ -2049,7 +2205,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2049
2205
|
let autoplay;
|
|
2050
2206
|
let loop;
|
|
2051
2207
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2052
|
-
this.
|
|
2208
|
+
this.skipBlockMemberSeparators();
|
|
2053
2209
|
if (this.check("RBRACE")) break;
|
|
2054
2210
|
if (this.check("IDENTIFIER") && (this.current().value === "autoplay" || this.current().value === "loop")) {
|
|
2055
2211
|
const key = this.advance().value;
|
|
@@ -2088,7 +2244,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2088
2244
|
this.skipNewlines();
|
|
2089
2245
|
const properties = {};
|
|
2090
2246
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2091
|
-
this.
|
|
2247
|
+
this.skipBlockMemberSeparators();
|
|
2092
2248
|
if (this.check("RBRACE")) break;
|
|
2093
2249
|
const key = this.expectIdentifier();
|
|
2094
2250
|
this.expect("COLON");
|
|
@@ -2133,7 +2289,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2133
2289
|
this.skipNewlines();
|
|
2134
2290
|
const properties = [];
|
|
2135
2291
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2136
|
-
this.
|
|
2292
|
+
this.skipBlockMemberSeparators();
|
|
2137
2293
|
if (this.check("RBRACE")) break;
|
|
2138
2294
|
if (this.check("AT")) {
|
|
2139
2295
|
this.advance();
|
|
@@ -2172,7 +2328,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2172
2328
|
const properties = [];
|
|
2173
2329
|
const handlers = [];
|
|
2174
2330
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2175
|
-
this.
|
|
2331
|
+
this.skipBlockMemberSeparators();
|
|
2176
2332
|
if (this.check("RBRACE")) break;
|
|
2177
2333
|
if (this.check("IDENTIFIER") && this.current().value.startsWith("on_")) {
|
|
2178
2334
|
const event = this.advance().value;
|
|
@@ -2212,7 +2368,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2212
2368
|
this.skipNewlines();
|
|
2213
2369
|
const elements = [];
|
|
2214
2370
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2215
|
-
this.
|
|
2371
|
+
this.skipBlockMemberSeparators();
|
|
2216
2372
|
if (this.check("RBRACE")) break;
|
|
2217
2373
|
if (this.check("ELEMENT")) {
|
|
2218
2374
|
elements.push(this.parseUIElement());
|
|
@@ -2237,7 +2393,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2237
2393
|
this.skipNewlines();
|
|
2238
2394
|
const properties = [];
|
|
2239
2395
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2240
|
-
this.
|
|
2396
|
+
this.skipBlockMemberSeparators();
|
|
2241
2397
|
if (this.check("RBRACE")) break;
|
|
2242
2398
|
const key = this.expectIdentifier();
|
|
2243
2399
|
this.expect("COLON");
|
|
@@ -2264,7 +2420,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2264
2420
|
this.skipNewlines();
|
|
2265
2421
|
const properties = [];
|
|
2266
2422
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2267
|
-
this.
|
|
2423
|
+
this.skipBlockMemberSeparators();
|
|
2268
2424
|
if (this.check("RBRACE")) break;
|
|
2269
2425
|
const key = this.expectIdentifier();
|
|
2270
2426
|
this.expect("COLON");
|
|
@@ -2398,7 +2554,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2398
2554
|
this.skipNewlines();
|
|
2399
2555
|
const properties = [];
|
|
2400
2556
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2401
|
-
this.
|
|
2557
|
+
this.skipBlockMemberSeparators();
|
|
2402
2558
|
if (this.check("RBRACE")) break;
|
|
2403
2559
|
const key = this.expectIdentifier();
|
|
2404
2560
|
this.expect("COLON");
|
|
@@ -2433,11 +2589,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2433
2589
|
// Initialize directives
|
|
2434
2590
|
};
|
|
2435
2591
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
2436
|
-
this.
|
|
2592
|
+
this.skipBlockMemberSeparators();
|
|
2437
2593
|
if (this.check("RBRACE")) break;
|
|
2438
|
-
if (this.check("STATE")) {
|
|
2594
|
+
if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
2439
2595
|
template.state = this.parseState();
|
|
2440
|
-
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
2596
|
+
} else if (this.check("ACTION") && this.peek(1).type !== "COLON" || this.check("ASYNC")) {
|
|
2441
2597
|
const action = this.parseAction();
|
|
2442
2598
|
template.actions.push(action);
|
|
2443
2599
|
template.directives.push({
|
|
@@ -2502,7 +2658,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2502
2658
|
body: []
|
|
2503
2659
|
});
|
|
2504
2660
|
} else if (this.isPropertyName() && this.peek(1).type === "LPAREN") {
|
|
2505
|
-
const methodName = this.
|
|
2661
|
+
const methodName = this.parsePropertyKey();
|
|
2506
2662
|
this.skipParens();
|
|
2507
2663
|
if (this.check("LBRACE")) {
|
|
2508
2664
|
this.skipBlock();
|
|
@@ -2514,7 +2670,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2514
2670
|
});
|
|
2515
2671
|
}
|
|
2516
2672
|
} else if (this.isPropertyName() && (this.peek(1).type === "IDENTIFIER" || this.peek(1).type === "STRING")) {
|
|
2517
|
-
const blockType = this.
|
|
2673
|
+
const blockType = this.parsePropertyKey();
|
|
2518
2674
|
const blockName = this.check("STRING") ? this.advance().value : this.expectIdentifier();
|
|
2519
2675
|
if (this.check("LPAREN")) {
|
|
2520
2676
|
this.skipParens();
|
|
@@ -2529,7 +2685,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2529
2685
|
});
|
|
2530
2686
|
}
|
|
2531
2687
|
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
2532
|
-
const blockType = this.
|
|
2688
|
+
const blockType = this.parsePropertyKey();
|
|
2533
2689
|
if (this.check("LBRACE")) {
|
|
2534
2690
|
this.skipBlock();
|
|
2535
2691
|
template.directives.push({
|
|
@@ -2540,12 +2696,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2540
2696
|
});
|
|
2541
2697
|
}
|
|
2542
2698
|
} else {
|
|
2543
|
-
const key = this.
|
|
2699
|
+
const key = this.parsePropertyKey();
|
|
2544
2700
|
this.expect("COLON");
|
|
2545
2701
|
const value = this.parseValue();
|
|
2546
2702
|
template.properties.push({ type: "TemplateProperty", key, value });
|
|
2547
2703
|
}
|
|
2548
|
-
this.
|
|
2704
|
+
this.skipBlockMemberSeparators();
|
|
2549
2705
|
}
|
|
2550
2706
|
this.expect("RBRACE");
|
|
2551
2707
|
template.loc = { start: startLoc, end: this.currentLocation() };
|
|
@@ -2565,8 +2721,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2565
2721
|
let name = "";
|
|
2566
2722
|
if (this.check("STRING")) {
|
|
2567
2723
|
name = this.expectString();
|
|
2568
|
-
} else if (this.
|
|
2569
|
-
name = this.
|
|
2724
|
+
} else if (this.isObjectNameToken()) {
|
|
2725
|
+
name = this.advance().value;
|
|
2570
2726
|
} else if (typeOverride === "behavior" && this.check("LBRACE")) {
|
|
2571
2727
|
name = "behavior";
|
|
2572
2728
|
} else {
|
|
@@ -2600,14 +2756,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2600
2756
|
const directives = [];
|
|
2601
2757
|
let state;
|
|
2602
2758
|
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
2603
|
-
this.
|
|
2759
|
+
this.skipBlockMemberSeparators();
|
|
2604
2760
|
if (this.check("RBRACE")) break;
|
|
2605
|
-
if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") || this.current().type.startsWith("UI_")) {
|
|
2761
|
+
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_")) {
|
|
2606
2762
|
const nestedType = this.check("OBJECT") ? void 0 : this.current().value.toLowerCase();
|
|
2607
2763
|
children.push(this.parseObject(nestedType));
|
|
2608
2764
|
} else if (this.check("SUB_ORB")) {
|
|
2609
2765
|
subOrbs.push(this.parseSubOrb());
|
|
2610
|
-
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
2766
|
+
} else if (this.check("ACTION") && this.peek(1).type !== "COLON" || this.check("ASYNC")) {
|
|
2611
2767
|
const action = this.parseAction();
|
|
2612
2768
|
directives.push({
|
|
2613
2769
|
type: "method",
|
|
@@ -2658,7 +2814,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2658
2814
|
config: config2,
|
|
2659
2815
|
platformConstraint: constraint
|
|
2660
2816
|
});
|
|
2661
|
-
} else if (this.check("OBJECT") || this.check("SPATIAL_AGENT") || this.check("TOOL_SLOT") || this.check("BEHAVIOR") || this.current().type.startsWith("UI_")) {
|
|
2817
|
+
} 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_")) {
|
|
2662
2818
|
const nestedType = this.check("OBJECT") ? void 0 : this.current().value.toLowerCase();
|
|
2663
2819
|
const child = this.parseObject(nestedType);
|
|
2664
2820
|
child.platformConstraint = constraint;
|
|
@@ -2671,7 +2827,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2671
2827
|
const trait = { type: "ObjectTrait", name: traitName, config };
|
|
2672
2828
|
traits.push(trait);
|
|
2673
2829
|
directives.push({ type: "trait", name: traitName, config });
|
|
2674
|
-
} else if (this.check("STATE")) {
|
|
2830
|
+
} else if (this.check("STATE") && this.peek(1).type !== "COLON") {
|
|
2675
2831
|
state = this.parseState();
|
|
2676
2832
|
} else if (this.isDomainBlockToken() && this.peek(1).type !== "COLON") {
|
|
2677
2833
|
const domainBlock = this.parseDomainBlock();
|
|
@@ -2683,7 +2839,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2683
2839
|
const physicsValue = this.parseValue();
|
|
2684
2840
|
properties.push({ type: "ObjectProperty", key, value: physicsValue });
|
|
2685
2841
|
} else if (this.isPropertyName()) {
|
|
2686
|
-
const key = this.
|
|
2842
|
+
const key = this.parsePropertyKey();
|
|
2687
2843
|
if (this.check("COLON")) {
|
|
2688
2844
|
this.advance();
|
|
2689
2845
|
if (this.check("LBRACE")) {
|
|
@@ -2717,7 +2873,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2717
2873
|
if (this.check("LPAREN")) this.skipParens();
|
|
2718
2874
|
let parsedBody = "";
|
|
2719
2875
|
if (this.check("LBRACE")) {
|
|
2720
|
-
|
|
2876
|
+
if (key === "on" || key.startsWith("on_") || /^on[A-Z]/.test(key)) {
|
|
2877
|
+
this.skipBlock();
|
|
2878
|
+
} else {
|
|
2879
|
+
parsedBody = this.parseBlockTraitConfig();
|
|
2880
|
+
}
|
|
2721
2881
|
}
|
|
2722
2882
|
directives.push({ type: key, name: blockName, parameters: [], body: parsedBody });
|
|
2723
2883
|
} else if (this.check("LBRACE")) {
|
|
@@ -2865,6 +3025,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2865
3025
|
this.expect("LBRACE");
|
|
2866
3026
|
this.skipNewlines();
|
|
2867
3027
|
const objects = [];
|
|
3028
|
+
const lights = [];
|
|
2868
3029
|
const groups = [];
|
|
2869
3030
|
const body = [];
|
|
2870
3031
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
@@ -2872,6 +3033,8 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2872
3033
|
if (this.check("RBRACE")) break;
|
|
2873
3034
|
if (this.check("OBJECT")) {
|
|
2874
3035
|
objects.push(this.parseObject());
|
|
3036
|
+
} else if (this.check("LIGHT")) {
|
|
3037
|
+
lights.push(this.parseLight());
|
|
2875
3038
|
} else if (this.check("SPATIAL_GROUP")) {
|
|
2876
3039
|
groups.push(this.parseSpatialGroup());
|
|
2877
3040
|
} else if (this.check("TEMPLATE")) {
|
|
@@ -2924,6 +3087,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2924
3087
|
name,
|
|
2925
3088
|
properties,
|
|
2926
3089
|
objects,
|
|
3090
|
+
lights: lights.length > 0 ? lights : void 0,
|
|
2927
3091
|
groups: groups.length > 0 ? groups : void 0,
|
|
2928
3092
|
body: body.length > 0 ? body : void 0
|
|
2929
3093
|
};
|
|
@@ -2943,6 +3107,18 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
2943
3107
|
if (this.check("RBRACE")) break;
|
|
2944
3108
|
if (this.check("ACTION") || this.check("ASYNC")) {
|
|
2945
3109
|
actions.push(this.parseAction());
|
|
3110
|
+
} else if (this.check("FUNCTION")) {
|
|
3111
|
+
this.skipFunctionDeclaration();
|
|
3112
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on" && (this.peek(1).type === "STRING" || this.peek(1).type === "IDENTIFIER")) {
|
|
3113
|
+
this.advance();
|
|
3114
|
+
const event = this.advance().value;
|
|
3115
|
+
const parameters = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
3116
|
+
if (this.check("LBRACE")) {
|
|
3117
|
+
this.skipBlock();
|
|
3118
|
+
handlers.push({ type: "EventHandler", event, parameters, body: [] });
|
|
3119
|
+
} else {
|
|
3120
|
+
handlers.push({ type: "EventHandler", event, parameters, body: [] });
|
|
3121
|
+
}
|
|
2946
3122
|
} else if (this.check("IDENTIFIER")) {
|
|
2947
3123
|
const name = this.advance().value;
|
|
2948
3124
|
if (this.check("IDENTIFIER")) {
|
|
@@ -3323,6 +3499,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3323
3499
|
isKeywordAsIdentifier() {
|
|
3324
3500
|
return isKeywordAsIdentifier(this._exprApi);
|
|
3325
3501
|
}
|
|
3502
|
+
isObjectNameToken() {
|
|
3503
|
+
const type = this.current().type;
|
|
3504
|
+
if (type === "IDENTIFIER") return true;
|
|
3505
|
+
if (type === "OBJECT") return false;
|
|
3506
|
+
return this.isKeywordAsIdentifierType(type);
|
|
3507
|
+
}
|
|
3326
3508
|
// ===========================================================================
|
|
3327
3509
|
// VALUES
|
|
3328
3510
|
// ===========================================================================
|
|
@@ -3350,14 +3532,22 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3350
3532
|
return this.parseBindValue();
|
|
3351
3533
|
}
|
|
3352
3534
|
if (this.match("AT")) {
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
}
|
|
3535
|
+
const traitName = this.parseTraitName();
|
|
3536
|
+
if (traitName) return `@${traitName}`;
|
|
3356
3537
|
this.error(`Expected trait name after '@', got ${this.current().type}`);
|
|
3357
3538
|
return null;
|
|
3358
3539
|
}
|
|
3359
|
-
if (this.match("
|
|
3360
|
-
return this.
|
|
3540
|
+
if (this.match("HASH")) {
|
|
3541
|
+
return this.parseHashLiteral();
|
|
3542
|
+
}
|
|
3543
|
+
if (this.check("ENUM")) {
|
|
3544
|
+
return this.parseEnumTypeSpec();
|
|
3545
|
+
}
|
|
3546
|
+
if (this.check("FUNCTION")) {
|
|
3547
|
+
return this.parseFunctionValue();
|
|
3548
|
+
}
|
|
3549
|
+
if (this.isBarewordPathToken()) {
|
|
3550
|
+
return this.parseBarewordPathValue();
|
|
3361
3551
|
}
|
|
3362
3552
|
if (this.match("LBRACKET")) {
|
|
3363
3553
|
return this.parseArrayValue();
|
|
@@ -3365,13 +3555,148 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3365
3555
|
if (this.match("LBRACE")) {
|
|
3366
3556
|
return this.parseObjectValue();
|
|
3367
3557
|
}
|
|
3368
|
-
if (_HoloCompositionParser.DOMAIN_TOKENS.has(this.current().type) || this.isKeywordAsIdentifierType(this.current().type)) {
|
|
3369
|
-
return this.advance().value;
|
|
3370
|
-
}
|
|
3371
3558
|
this.error(`Expected value, got ${this.current().type}`);
|
|
3372
3559
|
this.advance();
|
|
3373
3560
|
return null;
|
|
3374
3561
|
}
|
|
3562
|
+
/**
|
|
3563
|
+
* Parse an `enum(...)` type-spec expression, e.g.:
|
|
3564
|
+
* enum("button" | "slider" | "checkbox")
|
|
3565
|
+
*
|
|
3566
|
+
* Returns the canonical string representation so trait loaders and schema
|
|
3567
|
+
* emitters can read it as a type annotation. Called from parseValue() when
|
|
3568
|
+
* the current token is ENUM (the keyword `enum` tokenized as 'ENUM' rather
|
|
3569
|
+
* than 'IDENTIFIER').
|
|
3570
|
+
*
|
|
3571
|
+
* The opening `enum` token is consumed here. The caller should check for a
|
|
3572
|
+
* trailing `= defaultValue` if the context supports it (e.g. parseObjectValue).
|
|
3573
|
+
*/
|
|
3574
|
+
parseEnumTypeSpec() {
|
|
3575
|
+
this.advance();
|
|
3576
|
+
let spec = "enum";
|
|
3577
|
+
if (this.check("LPAREN")) {
|
|
3578
|
+
spec += this.parseParenthesizedLiteral();
|
|
3579
|
+
}
|
|
3580
|
+
return spec;
|
|
3581
|
+
}
|
|
3582
|
+
parseFunctionValue() {
|
|
3583
|
+
this.expect("FUNCTION");
|
|
3584
|
+
let name = "";
|
|
3585
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) {
|
|
3586
|
+
name = this.advance().value;
|
|
3587
|
+
}
|
|
3588
|
+
const params = this.check("LPAREN") ? this.collectFunctionParameterNames() : [];
|
|
3589
|
+
if (this.check("LBRACE")) {
|
|
3590
|
+
this.skipBlock();
|
|
3591
|
+
}
|
|
3592
|
+
return {
|
|
3593
|
+
type: "FunctionValue",
|
|
3594
|
+
name,
|
|
3595
|
+
params
|
|
3596
|
+
};
|
|
3597
|
+
}
|
|
3598
|
+
skipFunctionDeclaration() {
|
|
3599
|
+
this.expect("FUNCTION");
|
|
3600
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) {
|
|
3601
|
+
this.advance();
|
|
3602
|
+
}
|
|
3603
|
+
if (this.check("LPAREN")) {
|
|
3604
|
+
this.skipParens();
|
|
3605
|
+
}
|
|
3606
|
+
if (this.check("LBRACE")) {
|
|
3607
|
+
this.skipBlock();
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
collectFunctionParameterNames() {
|
|
3611
|
+
const params = [];
|
|
3612
|
+
if (!this.check("LPAREN")) return params;
|
|
3613
|
+
this.advance();
|
|
3614
|
+
let parenDepth = 1;
|
|
3615
|
+
while (parenDepth > 0 && !this.isAtEnd()) {
|
|
3616
|
+
if (this.check("LPAREN")) {
|
|
3617
|
+
parenDepth++;
|
|
3618
|
+
this.advance();
|
|
3619
|
+
continue;
|
|
3620
|
+
}
|
|
3621
|
+
if (this.check("RPAREN")) {
|
|
3622
|
+
parenDepth--;
|
|
3623
|
+
this.advance();
|
|
3624
|
+
continue;
|
|
3625
|
+
}
|
|
3626
|
+
if (parenDepth === 1 && this.check("IDENTIFIER")) {
|
|
3627
|
+
params.push(this.advance().value);
|
|
3628
|
+
continue;
|
|
3629
|
+
}
|
|
3630
|
+
this.advance();
|
|
3631
|
+
}
|
|
3632
|
+
return params;
|
|
3633
|
+
}
|
|
3634
|
+
isBarewordPathToken(token = this.current()) {
|
|
3635
|
+
const type = token.type;
|
|
3636
|
+
return type === "IDENTIFIER" || type === "STATE" || _HoloCompositionParser.DOMAIN_TOKENS.has(type) || this.isKeywordAsIdentifierType(type);
|
|
3637
|
+
}
|
|
3638
|
+
parseBarewordPathValue() {
|
|
3639
|
+
let value = this.advance().value;
|
|
3640
|
+
while (this.match("DOT")) {
|
|
3641
|
+
if (!this.isBarewordPathToken()) {
|
|
3642
|
+
this.error(`Expected identifier after '.', got ${this.current().type}`);
|
|
3643
|
+
break;
|
|
3644
|
+
}
|
|
3645
|
+
value += `.${this.advance().value}`;
|
|
3646
|
+
}
|
|
3647
|
+
while (this.check("COLON") && this.isBarewordPathToken(this.peek(1))) {
|
|
3648
|
+
this.advance();
|
|
3649
|
+
value += `:${this.advance().value}`;
|
|
3650
|
+
}
|
|
3651
|
+
if (this.match("LESS")) {
|
|
3652
|
+
value += "<";
|
|
3653
|
+
let depth = 1;
|
|
3654
|
+
while (depth > 0 && !this.isAtEnd()) {
|
|
3655
|
+
if (this.check("LESS")) {
|
|
3656
|
+
depth++;
|
|
3657
|
+
value += this.advance().value;
|
|
3658
|
+
continue;
|
|
3659
|
+
}
|
|
3660
|
+
if (this.check("GREATER")) {
|
|
3661
|
+
depth--;
|
|
3662
|
+
this.advance();
|
|
3663
|
+
value += ">";
|
|
3664
|
+
if (depth === 0) break;
|
|
3665
|
+
continue;
|
|
3666
|
+
}
|
|
3667
|
+
value += this.advance().value;
|
|
3668
|
+
}
|
|
3669
|
+
}
|
|
3670
|
+
if (this.check("LPAREN")) {
|
|
3671
|
+
value += this.parseParenthesizedLiteral();
|
|
3672
|
+
}
|
|
3673
|
+
return value;
|
|
3674
|
+
}
|
|
3675
|
+
parseHashLiteral() {
|
|
3676
|
+
let value = "#";
|
|
3677
|
+
while (!this.isAtEnd()) {
|
|
3678
|
+
if (this.check("IDENTIFIER") || this.check("NUMBER") || this.check("MINUS") || this.check("DOT")) {
|
|
3679
|
+
value += this.advance().value;
|
|
3680
|
+
continue;
|
|
3681
|
+
}
|
|
3682
|
+
break;
|
|
3683
|
+
}
|
|
3684
|
+
return value;
|
|
3685
|
+
}
|
|
3686
|
+
parseParenthesizedLiteral() {
|
|
3687
|
+
let value = "";
|
|
3688
|
+
if (!this.check("LPAREN")) return value;
|
|
3689
|
+
let depth = 0;
|
|
3690
|
+
while (!this.isAtEnd()) {
|
|
3691
|
+
const token = this.current();
|
|
3692
|
+
if (token.type === "LPAREN") depth++;
|
|
3693
|
+
if (token.type === "RPAREN") depth--;
|
|
3694
|
+
value += token.type === "STRING" ? `"${token.value}"` : token.value;
|
|
3695
|
+
this.advance();
|
|
3696
|
+
if (depth === 0) break;
|
|
3697
|
+
}
|
|
3698
|
+
return value;
|
|
3699
|
+
}
|
|
3375
3700
|
parseBindValue() {
|
|
3376
3701
|
this.expect("BIND");
|
|
3377
3702
|
this.expect("LPAREN");
|
|
@@ -3397,9 +3722,10 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3397
3722
|
const elements = [];
|
|
3398
3723
|
while (!this.check("RBRACKET") && !this.isAtEnd()) {
|
|
3399
3724
|
this.skipNewlines();
|
|
3725
|
+
if (this.check("RBRACKET")) break;
|
|
3400
3726
|
elements.push(this.parseValue());
|
|
3401
3727
|
this.skipNewlines();
|
|
3402
|
-
|
|
3728
|
+
this.match("COMMA");
|
|
3403
3729
|
this.skipNewlines();
|
|
3404
3730
|
}
|
|
3405
3731
|
this.skipNewlines();
|
|
@@ -3410,13 +3736,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3410
3736
|
this.skipNewlines();
|
|
3411
3737
|
const obj = {};
|
|
3412
3738
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3413
|
-
this.
|
|
3739
|
+
this.skipBlockMemberSeparators();
|
|
3414
3740
|
if (this.check("RBRACE")) break;
|
|
3415
|
-
this.
|
|
3416
|
-
|
|
3417
|
-
const key = this.expectIdentifier();
|
|
3741
|
+
if (this.isPropertyAssignmentStart()) {
|
|
3742
|
+
const key = this.parsePropertyKey();
|
|
3418
3743
|
this.expect("COLON");
|
|
3419
3744
|
obj[key] = this.parseValue();
|
|
3745
|
+
if (this.match("EQUALS")) {
|
|
3746
|
+
this.parseValue();
|
|
3747
|
+
}
|
|
3420
3748
|
} else if (this.check("RBRACE")) {
|
|
3421
3749
|
break;
|
|
3422
3750
|
} else {
|
|
@@ -3499,7 +3827,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3499
3827
|
this.skipNewlines();
|
|
3500
3828
|
const properties = [];
|
|
3501
3829
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3502
|
-
this.
|
|
3830
|
+
this.skipBlockMemberSeparators();
|
|
3503
3831
|
if (this.check("RBRACE")) break;
|
|
3504
3832
|
const key = this.expectIdentifier();
|
|
3505
3833
|
this.expect("COLON");
|
|
@@ -3540,6 +3868,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3540
3868
|
"QUEST",
|
|
3541
3869
|
"ABILITY",
|
|
3542
3870
|
"DIALOGUE",
|
|
3871
|
+
"BEHAVIOR",
|
|
3543
3872
|
"SHAPE",
|
|
3544
3873
|
"IMPORT",
|
|
3545
3874
|
"USING",
|
|
@@ -3558,10 +3887,42 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3558
3887
|
"WAYPOINTS",
|
|
3559
3888
|
"CONSTRAINT",
|
|
3560
3889
|
"TERRAIN",
|
|
3561
|
-
"PARTICLES"
|
|
3890
|
+
"PARTICLES",
|
|
3891
|
+
"METADATA_BLOCK",
|
|
3892
|
+
"HOLO_TOPIC",
|
|
3893
|
+
"HOLO_CHANNEL",
|
|
3894
|
+
"CONNECT",
|
|
3895
|
+
"BIND"
|
|
3562
3896
|
];
|
|
3563
3897
|
return validPropertyKeywords.includes(type);
|
|
3564
3898
|
}
|
|
3899
|
+
isPropertyNameToken(token) {
|
|
3900
|
+
return token.type === "IDENTIFIER" || _HoloCompositionParser.DOMAIN_TOKENS.has(token.type) || this.isKeywordAsIdentifierType(token.type);
|
|
3901
|
+
}
|
|
3902
|
+
isPropertyAssignmentStart() {
|
|
3903
|
+
if (!this.isPropertyName()) return false;
|
|
3904
|
+
let index = this.pos + 1;
|
|
3905
|
+
if (this.tokens[index]?.type === "QUESTION") index++;
|
|
3906
|
+
while (this.tokens[index]?.type === "DOT" && this.isPropertyNameToken(this.tokens[index + 1])) {
|
|
3907
|
+
index += 2;
|
|
3908
|
+
if (this.tokens[index]?.type === "QUESTION") index++;
|
|
3909
|
+
}
|
|
3910
|
+
return this.tokens[index]?.type === "COLON";
|
|
3911
|
+
}
|
|
3912
|
+
parsePropertyKey() {
|
|
3913
|
+
const parts = [];
|
|
3914
|
+
parts.push(this.isPropertyName() ? this.advance().value : this.expectIdentifier());
|
|
3915
|
+
while (this.match("DOT")) {
|
|
3916
|
+
if (!this.isPropertyName()) {
|
|
3917
|
+
this.error(`Expected identifier after '.', got ${this.current().type}`);
|
|
3918
|
+
break;
|
|
3919
|
+
}
|
|
3920
|
+
parts.push(this.advance().value);
|
|
3921
|
+
}
|
|
3922
|
+
let key = parts.join(".");
|
|
3923
|
+
if (this.match("QUESTION")) key += "?";
|
|
3924
|
+
return key;
|
|
3925
|
+
}
|
|
3565
3926
|
/**
|
|
3566
3927
|
* Parse primitive#id or primitive #id { } syntax
|
|
3567
3928
|
* Examples:
|
|
@@ -3599,15 +3960,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3599
3960
|
this.expect("LBRACE");
|
|
3600
3961
|
this.skipNewlines();
|
|
3601
3962
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3602
|
-
this.
|
|
3963
|
+
this.skipBlockMemberSeparators();
|
|
3603
3964
|
if (this.check("RBRACE")) break;
|
|
3604
3965
|
if (this.check("AT")) {
|
|
3605
3966
|
this.advance();
|
|
3606
3967
|
const name = this.parseTraitName();
|
|
3607
3968
|
const config = this.parseOptionalTraitConfig();
|
|
3608
3969
|
traits.push({ type: "ObjectTrait", name, config });
|
|
3609
|
-
} else if (this.
|
|
3610
|
-
const key = this.
|
|
3970
|
+
} else if (this.isPropertyName()) {
|
|
3971
|
+
const key = this.parsePropertyKey();
|
|
3611
3972
|
if (this.check("COLON")) {
|
|
3612
3973
|
this.advance();
|
|
3613
3974
|
properties.push({ type: "ObjectProperty", key, value: this.parseValue() });
|
|
@@ -3743,6 +4104,15 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3743
4104
|
while (this.match("NEWLINE")) {
|
|
3744
4105
|
}
|
|
3745
4106
|
}
|
|
4107
|
+
skipBlockMemberSeparators() {
|
|
4108
|
+
this.skipNewlines();
|
|
4109
|
+
while (this.matchBlockMemberSeparator()) {
|
|
4110
|
+
this.skipNewlines();
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
matchBlockMemberSeparator() {
|
|
4114
|
+
return this.match("COMMA") || this.match("SEMICOLON");
|
|
4115
|
+
}
|
|
3746
4116
|
currentLocation() {
|
|
3747
4117
|
const token = this.current();
|
|
3748
4118
|
return { line: token.line, column: token.column };
|
|
@@ -3830,16 +4200,14 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3830
4200
|
while (!this.check("RPAREN") && !this.check("EOF")) {
|
|
3831
4201
|
this.skipNewlines();
|
|
3832
4202
|
if (this.check("RPAREN")) break;
|
|
3833
|
-
if (!this.
|
|
4203
|
+
if (!this.isPropertyAssignmentStart()) {
|
|
3834
4204
|
config[`_arg${argIndex++}`] = this.parseValue();
|
|
3835
4205
|
} else {
|
|
3836
|
-
const key = this.
|
|
4206
|
+
const key = this.parsePropertyKey();
|
|
3837
4207
|
this.expect("COLON");
|
|
3838
4208
|
config[key] = this.parseValue();
|
|
3839
4209
|
}
|
|
3840
|
-
|
|
3841
|
-
this.advance();
|
|
3842
|
-
}
|
|
4210
|
+
this.matchBlockMemberSeparator();
|
|
3843
4211
|
this.skipNewlines();
|
|
3844
4212
|
}
|
|
3845
4213
|
this.expect("RPAREN");
|
|
@@ -3850,19 +4218,128 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3850
4218
|
this.skipNewlines();
|
|
3851
4219
|
const config = {};
|
|
3852
4220
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3853
|
-
this.
|
|
4221
|
+
this.skipBlockMemberSeparators();
|
|
3854
4222
|
if (this.check("RBRACE")) break;
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
if (this.check("
|
|
4223
|
+
if (this.isNamedOrTraitedPropertyBlockStart()) {
|
|
4224
|
+
const { key, value } = this.parseNamedOrTraitedPropertyBlock();
|
|
4225
|
+
config[key] = value;
|
|
4226
|
+
} else if (this.check("AT")) {
|
|
3859
4227
|
this.advance();
|
|
4228
|
+
const traitName = this.parseTraitName();
|
|
4229
|
+
if (traitName) {
|
|
4230
|
+
config[`@${traitName}`] = this.parseOptionalTraitConfig();
|
|
4231
|
+
}
|
|
4232
|
+
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
4233
|
+
const nestedKey = this.parsePropertyKey();
|
|
4234
|
+
config[nestedKey] = this.parseBlockTraitConfig();
|
|
4235
|
+
} else {
|
|
4236
|
+
const key = this.parsePropertyKey();
|
|
4237
|
+
this.expect("COLON");
|
|
4238
|
+
config[key] = this.parseInlineExpressionTail(this.parseValue());
|
|
3860
4239
|
}
|
|
4240
|
+
this.matchBlockMemberSeparator();
|
|
3861
4241
|
this.skipNewlines();
|
|
3862
4242
|
}
|
|
3863
4243
|
this.expect("RBRACE");
|
|
3864
4244
|
return config;
|
|
3865
4245
|
}
|
|
4246
|
+
parseInlineExpressionTail(value) {
|
|
4247
|
+
if (value === null || typeof value === "object" && !Array.isArray(value) || !this.isInlineExpressionTailStart()) {
|
|
4248
|
+
return value;
|
|
4249
|
+
}
|
|
4250
|
+
let text = String(value);
|
|
4251
|
+
while (!this.check(["NEWLINE", "COMMA", "SEMICOLON", "RBRACE", "RPAREN", "RBRACKET", "EOF"])) {
|
|
4252
|
+
const token = this.current();
|
|
4253
|
+
const raw = token.type === "STRING" ? `"${token.value}"` : token.value;
|
|
4254
|
+
text += ` ${raw}`;
|
|
4255
|
+
this.advance();
|
|
4256
|
+
}
|
|
4257
|
+
return text;
|
|
4258
|
+
}
|
|
4259
|
+
isInlineExpressionTailStart() {
|
|
4260
|
+
return this.check([
|
|
4261
|
+
"EQUALS_EQUALS",
|
|
4262
|
+
"BANG_EQUALS",
|
|
4263
|
+
"LESS",
|
|
4264
|
+
"LESS_EQUALS",
|
|
4265
|
+
"GREATER",
|
|
4266
|
+
"GREATER_EQUALS",
|
|
4267
|
+
"AND",
|
|
4268
|
+
"OR",
|
|
4269
|
+
"PLUS",
|
|
4270
|
+
"MINUS",
|
|
4271
|
+
"STAR",
|
|
4272
|
+
"SLASH"
|
|
4273
|
+
]);
|
|
4274
|
+
}
|
|
4275
|
+
isNamedOrTraitedPropertyBlockStart() {
|
|
4276
|
+
if (!this.isPropertyName()) return false;
|
|
4277
|
+
let index = this.pos + 1;
|
|
4278
|
+
const hasName = this.tokens[index]?.type === "STRING" || this.tokens[index]?.type === "IDENTIFIER";
|
|
4279
|
+
if (hasName) {
|
|
4280
|
+
index++;
|
|
4281
|
+
}
|
|
4282
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
4283
|
+
let hasTrait = false;
|
|
4284
|
+
while (this.tokens[index]?.type === "AT") {
|
|
4285
|
+
hasTrait = true;
|
|
4286
|
+
index++;
|
|
4287
|
+
if (this.tokens[index]?.type === "EOF") return false;
|
|
4288
|
+
index++;
|
|
4289
|
+
if (this.tokens[index]?.type === "LPAREN") {
|
|
4290
|
+
index = this.indexAfterBalancedTokens(index, "LPAREN", "RPAREN");
|
|
4291
|
+
}
|
|
4292
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
4293
|
+
}
|
|
4294
|
+
return (hasName || hasTrait) && this.tokens[index]?.type === "LBRACE";
|
|
4295
|
+
}
|
|
4296
|
+
indexAfterBalancedTokens(startIndex, openType, closeType) {
|
|
4297
|
+
let depth = 0;
|
|
4298
|
+
let index = startIndex;
|
|
4299
|
+
while (index < this.tokens.length) {
|
|
4300
|
+
if (this.tokens[index].type === openType) depth++;
|
|
4301
|
+
if (this.tokens[index].type === closeType) {
|
|
4302
|
+
depth--;
|
|
4303
|
+
index++;
|
|
4304
|
+
if (depth === 0) return index;
|
|
4305
|
+
continue;
|
|
4306
|
+
}
|
|
4307
|
+
index++;
|
|
4308
|
+
}
|
|
4309
|
+
return index;
|
|
4310
|
+
}
|
|
4311
|
+
parseNamedOrTraitedPropertyBlock() {
|
|
4312
|
+
const key = this.parsePropertyKey();
|
|
4313
|
+
const name = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : void 0;
|
|
4314
|
+
const traits = this.parseInlineTraitNamesBeforeBlock();
|
|
4315
|
+
const body = this.check("LBRACE") ? this.parseBlockTraitConfig() : {};
|
|
4316
|
+
return {
|
|
4317
|
+
key,
|
|
4318
|
+
value: {
|
|
4319
|
+
...name !== void 0 ? { name } : {},
|
|
4320
|
+
...traits.length > 0 ? { traits } : {},
|
|
4321
|
+
...body
|
|
4322
|
+
}
|
|
4323
|
+
};
|
|
4324
|
+
}
|
|
4325
|
+
parseInlineTraitNamesBeforeBlock() {
|
|
4326
|
+
const traits = [];
|
|
4327
|
+
while (this.check("AT")) {
|
|
4328
|
+
this.advance();
|
|
4329
|
+
const traitName = this.parseTraitName();
|
|
4330
|
+
if (traitName) traits.push(traitName);
|
|
4331
|
+
if (this.check("LPAREN")) {
|
|
4332
|
+
this.skipParens();
|
|
4333
|
+
}
|
|
4334
|
+
this.skipNewlines();
|
|
4335
|
+
}
|
|
4336
|
+
return traits;
|
|
4337
|
+
}
|
|
4338
|
+
parseSharePlayBlock() {
|
|
4339
|
+
this.advance();
|
|
4340
|
+
if (!this.check("LBRACE")) return {};
|
|
4341
|
+
return this.parseBlockTraitConfig();
|
|
4342
|
+
}
|
|
3866
4343
|
// ===========================================================================
|
|
3867
4344
|
// PLATFORM CONSTRAINT PARSING
|
|
3868
4345
|
// ===========================================================================
|
|
@@ -3978,7 +4455,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3978
4455
|
type: "NPC",
|
|
3979
4456
|
name,
|
|
3980
4457
|
properties: [],
|
|
3981
|
-
behaviors: []
|
|
4458
|
+
behaviors: [],
|
|
4459
|
+
traits: [],
|
|
4460
|
+
directives: []
|
|
3982
4461
|
};
|
|
3983
4462
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
3984
4463
|
this.skipNewlines();
|
|
@@ -3987,29 +4466,86 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
3987
4466
|
npc.behaviors.push(this.parseBehavior());
|
|
3988
4467
|
} else if (this.check("STATE")) {
|
|
3989
4468
|
npc.state = this.parseState();
|
|
3990
|
-
} else {
|
|
3991
|
-
const
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
this.
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4469
|
+
} else if (this.check("ACTION") || this.check("ASYNC")) {
|
|
4470
|
+
const action = this.parseAction();
|
|
4471
|
+
(npc.directives ?? (npc.directives = [])).push({
|
|
4472
|
+
type: "method",
|
|
4473
|
+
name: action.name,
|
|
4474
|
+
parameters: action.parameters || [],
|
|
4475
|
+
body: action.body,
|
|
4476
|
+
async: action.async
|
|
4477
|
+
});
|
|
4478
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on" && this.peek(1).type === "IDENTIFIER") {
|
|
4479
|
+
const eventName = this.peek(1).value;
|
|
4480
|
+
this.advance();
|
|
4481
|
+
this.advance();
|
|
4482
|
+
while (this.check("DOT")) {
|
|
4483
|
+
this.advance();
|
|
4484
|
+
if (this.check("IDENTIFIER")) this.advance();
|
|
4485
|
+
}
|
|
4486
|
+
let parameters = [];
|
|
4487
|
+
if (this.check("LPAREN")) {
|
|
4488
|
+
parameters = this.parseParameterList();
|
|
4489
|
+
}
|
|
4490
|
+
this.skipBlock();
|
|
4491
|
+
(npc.directives ?? (npc.directives = [])).push({
|
|
4492
|
+
type: "lifecycle",
|
|
4493
|
+
hook: eventName,
|
|
4494
|
+
parameters,
|
|
4495
|
+
body: []
|
|
4496
|
+
});
|
|
4497
|
+
} else if (this.check("AT")) {
|
|
4498
|
+
this.advance();
|
|
4499
|
+
const traitName = this.parseTraitName();
|
|
4500
|
+
const config = this.parseOptionalTraitConfig(true);
|
|
4501
|
+
(npc.traits ?? (npc.traits = [])).push({ type: "ObjectTrait", name: traitName, config });
|
|
4502
|
+
} else {
|
|
4503
|
+
const key = this.expectIdentifier();
|
|
4504
|
+
this.expect("COLON");
|
|
4505
|
+
const value = this.parseValue();
|
|
4506
|
+
if (key === "type") npc.npcType = value;
|
|
4507
|
+
else if (key === "model") npc.model = value;
|
|
4508
|
+
else if (key === "dialogue_tree") npc.dialogueTree = value;
|
|
4509
|
+
else if (key === "position") {
|
|
4510
|
+
if (Array.isArray(value) && value.length >= 3) {
|
|
4511
|
+
npc.position = { x: value[0], y: value[1], z: value[2] };
|
|
4512
|
+
} else if (value && typeof value === "object" && "x" in value) {
|
|
4513
|
+
const v = value;
|
|
4514
|
+
npc.position = { x: v.x, y: v.y, z: v.z };
|
|
4515
|
+
}
|
|
4516
|
+
} else if (key === "brain_ref") {
|
|
4517
|
+
npc.brain = {
|
|
4518
|
+
...npc.brain ?? { type: "AgentBrainAttachment", brainType: "llm" },
|
|
4519
|
+
type: "AgentBrainAttachment",
|
|
4520
|
+
brainType: npc.brain?.brainType ?? "llm",
|
|
4521
|
+
brainRef: value
|
|
4522
|
+
};
|
|
4523
|
+
} else if (key === "brain") {
|
|
4524
|
+
const cfg = value && typeof value === "object" ? value : {};
|
|
4525
|
+
npc.brain = {
|
|
4526
|
+
type: "AgentBrainAttachment",
|
|
4527
|
+
brainType: cfg.type ?? "llm",
|
|
4528
|
+
autonomy: cfg.autonomy,
|
|
4529
|
+
brainRef: typeof cfg.ref === "string" ? cfg.ref : typeof cfg.brainRef === "string" ? cfg.brainRef : void 0,
|
|
4530
|
+
toolPermissions: Array.isArray(cfg.tools) ? cfg.tools.map(String) : void 0,
|
|
4531
|
+
model: cfg.model && typeof cfg.model === "object" ? cfg.model : void 0
|
|
4532
|
+
};
|
|
4533
|
+
} else npc.properties.push({ type: "NPCProperty", key, value });
|
|
4534
|
+
}
|
|
4535
|
+
this.skipNewlines();
|
|
4536
|
+
}
|
|
4537
|
+
this.expect("RBRACE");
|
|
4538
|
+
this.popContext();
|
|
4539
|
+
return npc;
|
|
4540
|
+
}
|
|
4541
|
+
parseBehavior() {
|
|
4542
|
+
this.expect("BEHAVIOR");
|
|
4543
|
+
const name = this.expectString();
|
|
4544
|
+
this.expect("LBRACE");
|
|
4545
|
+
this.skipNewlines();
|
|
4546
|
+
const behavior = {
|
|
4547
|
+
type: "Behavior",
|
|
4548
|
+
name,
|
|
4013
4549
|
trigger: "idle",
|
|
4014
4550
|
actions: []
|
|
4015
4551
|
};
|
|
@@ -4351,7 +4887,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4351
4887
|
options: []
|
|
4352
4888
|
};
|
|
4353
4889
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4354
|
-
this.
|
|
4890
|
+
this.skipBlockMemberSeparators();
|
|
4355
4891
|
if (this.check("RBRACE")) break;
|
|
4356
4892
|
const key = this.expectIdentifier();
|
|
4357
4893
|
this.expect("COLON");
|
|
@@ -4381,7 +4917,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4381
4917
|
text: ""
|
|
4382
4918
|
};
|
|
4383
4919
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4384
|
-
this.
|
|
4920
|
+
this.skipBlockMemberSeparators();
|
|
4385
4921
|
if (this.check("RBRACE")) break;
|
|
4386
4922
|
const key = this.expectIdentifier();
|
|
4387
4923
|
this.expect("COLON");
|
|
@@ -4404,9 +4940,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4404
4940
|
// BRITTNEY AI FEATURES - STATE MACHINES
|
|
4405
4941
|
// ===========================================================================
|
|
4406
4942
|
parseStateMachine() {
|
|
4407
|
-
this.currentLocation();
|
|
4943
|
+
const startLoc = this.currentLocation();
|
|
4408
4944
|
this.expect("STATE_MACHINE");
|
|
4409
|
-
const name = this.
|
|
4945
|
+
const name = this.parseOptionalStateMachineName("");
|
|
4946
|
+
if (!name) {
|
|
4947
|
+
this.error("Expected state_machine name");
|
|
4948
|
+
}
|
|
4410
4949
|
this.pushContext(`StateMachine "${name}"`);
|
|
4411
4950
|
this.expect("LBRACE");
|
|
4412
4951
|
this.skipNewlines();
|
|
@@ -4414,11 +4953,19 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4414
4953
|
type: "StateMachine",
|
|
4415
4954
|
name,
|
|
4416
4955
|
initialState: "",
|
|
4417
|
-
|
|
4956
|
+
inputs: [],
|
|
4957
|
+
listeners: [],
|
|
4958
|
+
states: {},
|
|
4959
|
+
transitions: []
|
|
4418
4960
|
};
|
|
4419
4961
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4420
4962
|
this.skipNewlines();
|
|
4421
4963
|
if (this.check("RBRACE")) break;
|
|
4964
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
4965
|
+
sm.transitions.push(this.parseAnimationTransitionShorthand());
|
|
4966
|
+
this.skipNewlines();
|
|
4967
|
+
continue;
|
|
4968
|
+
}
|
|
4422
4969
|
if (this.check("STATE")) {
|
|
4423
4970
|
this.advance();
|
|
4424
4971
|
const stateName = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : "anonymous";
|
|
@@ -4435,6 +4982,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4435
4982
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4436
4983
|
this.skipNewlines();
|
|
4437
4984
|
if (this.check("RBRACE")) break;
|
|
4985
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
4986
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
4987
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
4988
|
+
else this.advance();
|
|
4989
|
+
continue;
|
|
4990
|
+
}
|
|
4438
4991
|
const key2 = this.expectIdentifier();
|
|
4439
4992
|
if (this.check("COLON")) {
|
|
4440
4993
|
this.advance();
|
|
@@ -4450,7 +5003,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4450
5003
|
this.expect("RBRACE");
|
|
4451
5004
|
} else if (key2 === "actions") {
|
|
4452
5005
|
state.actions = this.parseBehaviorActions();
|
|
4453
|
-
} else if (key2 === "transitions") {
|
|
5006
|
+
} else if (this.parseAnimationStateMetadata(state, key2)) ; else if (key2 === "transitions") {
|
|
4454
5007
|
state.transitions = this.parseStateTransitions();
|
|
4455
5008
|
} else if (key2 === "onDamage") {
|
|
4456
5009
|
state.onDamage = this.parseStatementBlock();
|
|
@@ -4459,7 +5012,11 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4459
5012
|
} else if (key2 === "onTimeout") {
|
|
4460
5013
|
state.onTimeout = this.parseStatementBlock();
|
|
4461
5014
|
} else {
|
|
4462
|
-
this.
|
|
5015
|
+
if (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5016
|
+
this.parseValue();
|
|
5017
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5018
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
5019
|
+
}
|
|
4463
5020
|
}
|
|
4464
5021
|
} else if (this.check("LBRACE")) {
|
|
4465
5022
|
if (key2 === "enter" || key2 === "entry") {
|
|
@@ -4475,6 +5032,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4475
5032
|
} else {
|
|
4476
5033
|
this.skipBlock();
|
|
4477
5034
|
}
|
|
5035
|
+
} else if (this.check("LPAREN")) {
|
|
5036
|
+
this.skipParens();
|
|
5037
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4478
5038
|
}
|
|
4479
5039
|
this.skipNewlines();
|
|
4480
5040
|
}
|
|
@@ -4484,18 +5044,37 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4484
5044
|
this.skipNewlines();
|
|
4485
5045
|
continue;
|
|
4486
5046
|
}
|
|
5047
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
5048
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5049
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
5050
|
+
else this.advance();
|
|
5051
|
+
this.skipNewlines();
|
|
5052
|
+
continue;
|
|
5053
|
+
}
|
|
4487
5054
|
const key = this.expectIdentifier();
|
|
4488
5055
|
if (key === "initial" || key === "initialState") {
|
|
4489
5056
|
this.expect("COLON");
|
|
4490
5057
|
sm.initialState = this.parseValue();
|
|
5058
|
+
} else if (key === "input") {
|
|
5059
|
+
sm.inputs.push(this.parseAnimationInputDeclaration(startLoc));
|
|
5060
|
+
} else if (key === "listen") {
|
|
5061
|
+
sm.listeners.push(this.parseAnimationListenerDeclaration(startLoc));
|
|
4491
5062
|
} else if (key === "states" && this.check("COLON")) {
|
|
4492
5063
|
this.advance();
|
|
4493
5064
|
sm.states = this.parseStateMachineStates();
|
|
5065
|
+
} else if (key === "transitions" && this.check("COLON")) {
|
|
5066
|
+
this.advance();
|
|
5067
|
+
sm.transitions = this.parseStateTransitions();
|
|
4494
5068
|
} else if (this.check("COLON")) {
|
|
4495
5069
|
this.advance();
|
|
4496
5070
|
this.parseValue();
|
|
5071
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5072
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4497
5073
|
} else if (this.check("LBRACE")) {
|
|
4498
5074
|
this.skipBlock();
|
|
5075
|
+
} else if (this.check("LPAREN")) {
|
|
5076
|
+
this.skipParens();
|
|
5077
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4499
5078
|
}
|
|
4500
5079
|
this.skipNewlines();
|
|
4501
5080
|
}
|
|
@@ -4516,19 +5095,27 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4516
5095
|
* Without this, @state_machine blocks were stored as opaque traits and
|
|
4517
5096
|
* invisible to compile_to_a2a_agent_card and other compilers.
|
|
4518
5097
|
*/
|
|
4519
|
-
parseStateMachineFromDecorator() {
|
|
5098
|
+
parseStateMachineFromDecorator(name = "implicit") {
|
|
4520
5099
|
const startLoc = this.currentLocation();
|
|
4521
5100
|
this.expect("LBRACE");
|
|
4522
5101
|
this.skipNewlines();
|
|
4523
5102
|
const sm = {
|
|
4524
5103
|
type: "StateMachine",
|
|
4525
|
-
name
|
|
5104
|
+
name,
|
|
4526
5105
|
initialState: "",
|
|
4527
|
-
|
|
5106
|
+
inputs: [],
|
|
5107
|
+
listeners: [],
|
|
5108
|
+
states: {},
|
|
5109
|
+
transitions: []
|
|
4528
5110
|
};
|
|
4529
5111
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4530
5112
|
this.skipNewlines();
|
|
4531
5113
|
if (this.check("RBRACE")) break;
|
|
5114
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
5115
|
+
sm.transitions.push(this.parseAnimationTransitionShorthand());
|
|
5116
|
+
this.skipNewlines();
|
|
5117
|
+
continue;
|
|
5118
|
+
}
|
|
4532
5119
|
if (this.check("STATE")) {
|
|
4533
5120
|
this.advance();
|
|
4534
5121
|
const stateName = this.check("STRING") || this.check("IDENTIFIER") ? this.advance().value : "anonymous";
|
|
@@ -4545,6 +5132,12 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4545
5132
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
4546
5133
|
this.skipNewlines();
|
|
4547
5134
|
if (this.check("RBRACE")) break;
|
|
5135
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
5136
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5137
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
5138
|
+
else this.advance();
|
|
5139
|
+
continue;
|
|
5140
|
+
}
|
|
4548
5141
|
const key2 = this.expectIdentifier();
|
|
4549
5142
|
if (this.check("COLON")) {
|
|
4550
5143
|
this.advance();
|
|
@@ -4560,12 +5153,16 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4560
5153
|
this.expect("RBRACE");
|
|
4561
5154
|
} else if (key2 === "actions") {
|
|
4562
5155
|
state.actions = this.parseBehaviorActions();
|
|
4563
|
-
} else if (key2 === "transitions") {
|
|
5156
|
+
} else if (this.parseAnimationStateMetadata(state, key2)) ; else if (key2 === "transitions") {
|
|
4564
5157
|
state.transitions = this.parseStateTransitions();
|
|
4565
5158
|
} else if (key2 === "timeout") {
|
|
4566
5159
|
state.timeout = this.parseValue();
|
|
4567
5160
|
} else {
|
|
4568
|
-
this.
|
|
5161
|
+
if (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5162
|
+
this.parseValue();
|
|
5163
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5164
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
5165
|
+
}
|
|
4569
5166
|
}
|
|
4570
5167
|
} else if (this.check("LBRACE")) {
|
|
4571
5168
|
if (key2 === "enter" || key2 === "entry" || key2 === "on_entry") {
|
|
@@ -4583,6 +5180,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4583
5180
|
} else {
|
|
4584
5181
|
this.skipBlock();
|
|
4585
5182
|
}
|
|
5183
|
+
} else if (this.check("LPAREN")) {
|
|
5184
|
+
this.skipParens();
|
|
5185
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4586
5186
|
}
|
|
4587
5187
|
this.skipNewlines();
|
|
4588
5188
|
}
|
|
@@ -4592,21 +5192,40 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4592
5192
|
this.skipNewlines();
|
|
4593
5193
|
continue;
|
|
4594
5194
|
}
|
|
5195
|
+
if (this.current().type !== "IDENTIFIER" && !this.isKeywordAsIdentifierType(this.current().type)) {
|
|
5196
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5197
|
+
else if (this.check("LBRACE")) this.skipBlock();
|
|
5198
|
+
else this.advance();
|
|
5199
|
+
this.skipNewlines();
|
|
5200
|
+
continue;
|
|
5201
|
+
}
|
|
4595
5202
|
const key = this.expectIdentifier();
|
|
4596
5203
|
if (key === "initial" || key === "initialState") {
|
|
4597
5204
|
this.expect("COLON");
|
|
4598
5205
|
sm.initialState = this.parseValue();
|
|
5206
|
+
} else if (key === "input") {
|
|
5207
|
+
sm.inputs.push(this.parseAnimationInputDeclaration(startLoc));
|
|
5208
|
+
} else if (key === "listen") {
|
|
5209
|
+
sm.listeners.push(this.parseAnimationListenerDeclaration(startLoc));
|
|
4599
5210
|
} else if (key === "name") {
|
|
4600
5211
|
this.expect("COLON");
|
|
4601
5212
|
sm.name = this.parseValue();
|
|
4602
5213
|
} else if (key === "states" && this.check("COLON")) {
|
|
4603
5214
|
this.advance();
|
|
4604
5215
|
sm.states = this.parseStateMachineStates();
|
|
5216
|
+
} else if (key === "transitions" && this.check("COLON")) {
|
|
5217
|
+
this.advance();
|
|
5218
|
+
sm.transitions = this.parseStateTransitions();
|
|
4605
5219
|
} else if (this.check("COLON")) {
|
|
4606
5220
|
this.advance();
|
|
4607
5221
|
this.parseValue();
|
|
5222
|
+
if (this.check("LPAREN")) this.skipParens();
|
|
5223
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4608
5224
|
} else if (this.check("LBRACE")) {
|
|
4609
5225
|
this.skipBlock();
|
|
5226
|
+
} else if (this.check("LPAREN")) {
|
|
5227
|
+
this.skipParens();
|
|
5228
|
+
if (this.check("LBRACE")) this.skipBlock();
|
|
4610
5229
|
}
|
|
4611
5230
|
this.skipNewlines();
|
|
4612
5231
|
}
|
|
@@ -4639,7 +5258,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4639
5258
|
if (key === "entry") state.entry = this.parseStatementBlock();
|
|
4640
5259
|
else if (key === "exit") state.exit = this.parseStatementBlock();
|
|
4641
5260
|
else if (key === "actions") state.actions = this.parseBehaviorActions();
|
|
4642
|
-
else if (key === "onDamage") state.onDamage = this.parseStatementBlock();
|
|
5261
|
+
else if (this.parseAnimationStateMetadata(state, key)) ; else if (key === "onDamage") state.onDamage = this.parseStatementBlock();
|
|
4643
5262
|
else if (key === "timeout") state.timeout = this.parseValue();
|
|
4644
5263
|
else if (key === "onTimeout") state.onTimeout = this.parseStatementBlock();
|
|
4645
5264
|
else if (key === "transitions") state.transitions = this.parseStateTransitions();
|
|
@@ -4653,13 +5272,385 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4653
5272
|
this.expect("RBRACE");
|
|
4654
5273
|
return states;
|
|
4655
5274
|
}
|
|
5275
|
+
parseOptionalStateMachineName(defaultName) {
|
|
5276
|
+
if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
|
|
5277
|
+
return this.advance().value;
|
|
5278
|
+
}
|
|
5279
|
+
return defaultName;
|
|
5280
|
+
}
|
|
5281
|
+
parseAnimationStateMetadata(state, key) {
|
|
5282
|
+
if (key === "clip") {
|
|
5283
|
+
state.clip = String(this.parseValue() ?? "");
|
|
5284
|
+
return true;
|
|
5285
|
+
}
|
|
5286
|
+
if (key === "clips") {
|
|
5287
|
+
state.clips = this.coerceStringArray(this.parseValue());
|
|
5288
|
+
return true;
|
|
5289
|
+
}
|
|
5290
|
+
if (key === "parameter") {
|
|
5291
|
+
state.parameter = String(this.parseValue() ?? "");
|
|
5292
|
+
return true;
|
|
5293
|
+
}
|
|
5294
|
+
if (key === "parameters") {
|
|
5295
|
+
state.parameters = this.coerceStringArray(this.parseValue());
|
|
5296
|
+
return true;
|
|
5297
|
+
}
|
|
5298
|
+
if (key === "thresholds") {
|
|
5299
|
+
state.thresholds = this.coerceNumberArray(this.parseValue());
|
|
5300
|
+
return true;
|
|
5301
|
+
}
|
|
5302
|
+
if (key === "blendType" || key === "blend_type" || key === "blend") {
|
|
5303
|
+
const blendType = String(this.parseValue() ?? "").toLowerCase();
|
|
5304
|
+
if (blendType === "1d" || blendType === "direct") {
|
|
5305
|
+
state.blendType = blendType;
|
|
5306
|
+
} else {
|
|
5307
|
+
this.error(`Unknown animation blend type "${blendType}"`);
|
|
5308
|
+
}
|
|
5309
|
+
return true;
|
|
5310
|
+
}
|
|
5311
|
+
if (key === "blendMode" || key === "blend_mode") {
|
|
5312
|
+
const blendMode = String(this.parseValue() ?? "").toLowerCase();
|
|
5313
|
+
if (blendMode === "override" || blendMode === "additive") {
|
|
5314
|
+
state.blendMode = blendMode;
|
|
5315
|
+
} else {
|
|
5316
|
+
this.error(`Unknown animation blend mode "${blendMode}"`);
|
|
5317
|
+
}
|
|
5318
|
+
return true;
|
|
5319
|
+
}
|
|
5320
|
+
if (key === "mask") {
|
|
5321
|
+
state.mask = this.coerceStringArray(this.parseValue());
|
|
5322
|
+
return true;
|
|
5323
|
+
}
|
|
5324
|
+
if (key === "baseline") {
|
|
5325
|
+
state.baseline = this.coerceNumberRecord(this.parseValue());
|
|
5326
|
+
return true;
|
|
5327
|
+
}
|
|
5328
|
+
return false;
|
|
5329
|
+
}
|
|
5330
|
+
coerceStringArray(value) {
|
|
5331
|
+
if (!Array.isArray(value)) return value == null ? [] : [String(value)];
|
|
5332
|
+
return value.map((entry) => String(entry));
|
|
5333
|
+
}
|
|
5334
|
+
coerceNumberArray(value) {
|
|
5335
|
+
if (!Array.isArray(value)) {
|
|
5336
|
+
const single = Number(value);
|
|
5337
|
+
return Number.isFinite(single) ? [single] : [];
|
|
5338
|
+
}
|
|
5339
|
+
return value.map((entry) => Number(entry)).filter((entry) => Number.isFinite(entry));
|
|
5340
|
+
}
|
|
5341
|
+
coerceNumberRecord(value) {
|
|
5342
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
5343
|
+
const out = {};
|
|
5344
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
5345
|
+
const numeric = Number(raw);
|
|
5346
|
+
if (Number.isFinite(numeric)) out[key] = numeric;
|
|
5347
|
+
}
|
|
5348
|
+
return out;
|
|
5349
|
+
}
|
|
5350
|
+
isStateNameToken(offset = 0) {
|
|
5351
|
+
const token = this.peek(offset);
|
|
5352
|
+
return token.type === "STRING" || token.type === "IDENTIFIER" || this.isKeywordAsIdentifierType(token.type);
|
|
5353
|
+
}
|
|
5354
|
+
isAnimationTransitionShorthandStart() {
|
|
5355
|
+
if (!this.isStateNameToken()) return false;
|
|
5356
|
+
return this.peek(1).type === "ARROW" || this.peek(1).type === "MINUS" && this.peek(2).type === "GREATER";
|
|
5357
|
+
}
|
|
5358
|
+
consumeStateTransitionArrow() {
|
|
5359
|
+
if (this.match("ARROW")) return true;
|
|
5360
|
+
if (this.check("MINUS") && this.peek(1).type === "GREATER") {
|
|
5361
|
+
this.advance();
|
|
5362
|
+
this.advance();
|
|
5363
|
+
return true;
|
|
5364
|
+
}
|
|
5365
|
+
return false;
|
|
5366
|
+
}
|
|
5367
|
+
parseAnimationInputDeclaration(startLoc) {
|
|
5368
|
+
const name = this.expectIdentifier();
|
|
5369
|
+
this.expect("COLON");
|
|
5370
|
+
const rawType = this.parseIdentifierOrStringValue();
|
|
5371
|
+
const inputType = this.normalizeAnimationInputType(rawType);
|
|
5372
|
+
let defaultValue;
|
|
5373
|
+
if (this.match("EQUALS")) {
|
|
5374
|
+
defaultValue = this.coerceAnimationInputDefault(inputType, this.parseValue());
|
|
5375
|
+
}
|
|
5376
|
+
return {
|
|
5377
|
+
type: "AnimationInput",
|
|
5378
|
+
name,
|
|
5379
|
+
inputType,
|
|
5380
|
+
rawType,
|
|
5381
|
+
default: defaultValue,
|
|
5382
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5383
|
+
};
|
|
5384
|
+
}
|
|
5385
|
+
parseAnimationListenerDeclaration(startLoc) {
|
|
5386
|
+
const event = this.parseDottedIdentifierValue("Expected listener event");
|
|
5387
|
+
if (!this.consumeStateTransitionArrow()) {
|
|
5388
|
+
this.error("Expected -> in animation listener");
|
|
5389
|
+
}
|
|
5390
|
+
if (this.isIdentifierValue("fire")) {
|
|
5391
|
+
this.advance();
|
|
5392
|
+
return {
|
|
5393
|
+
type: "AnimationListener",
|
|
5394
|
+
event,
|
|
5395
|
+
parameter: this.parseDottedIdentifierValue("Expected trigger input"),
|
|
5396
|
+
action: "fire",
|
|
5397
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5398
|
+
};
|
|
5399
|
+
}
|
|
5400
|
+
if (this.isIdentifierValue("reset")) {
|
|
5401
|
+
this.advance();
|
|
5402
|
+
return {
|
|
5403
|
+
type: "AnimationListener",
|
|
5404
|
+
event,
|
|
5405
|
+
parameter: this.parseDottedIdentifierValue("Expected trigger input"),
|
|
5406
|
+
action: "reset",
|
|
5407
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5408
|
+
};
|
|
5409
|
+
}
|
|
5410
|
+
const parameter = this.parseDottedIdentifierValue("Expected animation input");
|
|
5411
|
+
this.expect("EQUALS");
|
|
5412
|
+
const assignment = this.parseAnimationListenerValue();
|
|
5413
|
+
return {
|
|
5414
|
+
type: "AnimationListener",
|
|
5415
|
+
event,
|
|
5416
|
+
parameter,
|
|
5417
|
+
action: "set",
|
|
5418
|
+
...assignment,
|
|
5419
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5420
|
+
};
|
|
5421
|
+
}
|
|
5422
|
+
parseAnimationListenerValue() {
|
|
5423
|
+
if (this.isIdentifierValue("event")) {
|
|
5424
|
+
return { source: this.parseDottedIdentifierValue("Expected event value source") };
|
|
5425
|
+
}
|
|
5426
|
+
const value = this.parseValue();
|
|
5427
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
|
|
5428
|
+
return { value };
|
|
5429
|
+
}
|
|
5430
|
+
return { value: String(value ?? "") };
|
|
5431
|
+
}
|
|
5432
|
+
normalizeAnimationInputType(rawType) {
|
|
5433
|
+
const normalized = rawType.toLowerCase();
|
|
5434
|
+
if (normalized === "number") return "float";
|
|
5435
|
+
if (normalized === "boolean") return "bool";
|
|
5436
|
+
if (normalized === "bool" || normalized === "float" || normalized === "int" || normalized === "trigger") {
|
|
5437
|
+
return normalized;
|
|
5438
|
+
}
|
|
5439
|
+
this.error(`Unknown animation input type "${rawType}", defaulting to float`);
|
|
5440
|
+
return "float";
|
|
5441
|
+
}
|
|
5442
|
+
coerceAnimationInputDefault(inputType, value) {
|
|
5443
|
+
if (inputType === "bool" || inputType === "trigger") return Boolean(value);
|
|
5444
|
+
if (typeof value === "number") return value;
|
|
5445
|
+
if (typeof value === "boolean") return value ? 1 : 0;
|
|
5446
|
+
return void 0;
|
|
5447
|
+
}
|
|
5448
|
+
parseAnimationTransitionShorthand() {
|
|
5449
|
+
const startLoc = this.currentLocation();
|
|
5450
|
+
const rawFrom = this.parseStateNameValue();
|
|
5451
|
+
const from = rawFrom.toLowerCase() === "any" ? "any" : rawFrom;
|
|
5452
|
+
if (!this.consumeStateTransitionArrow()) {
|
|
5453
|
+
this.error("Expected -> in animation transition");
|
|
5454
|
+
}
|
|
5455
|
+
const target = this.parseStateNameValue();
|
|
5456
|
+
const transition = {
|
|
5457
|
+
type: "StateTransition",
|
|
5458
|
+
from,
|
|
5459
|
+
target,
|
|
5460
|
+
conditions: [],
|
|
5461
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5462
|
+
};
|
|
5463
|
+
while (!this.check("NEWLINE") && !this.check("SEMICOLON") && !this.check("COMMA") && !this.check("RBRACE") && !this.isAtEnd()) {
|
|
5464
|
+
if (!this.isStateNameToken()) break;
|
|
5465
|
+
const clause = this.current().value.toLowerCase();
|
|
5466
|
+
this.advance();
|
|
5467
|
+
if (clause === "when") {
|
|
5468
|
+
transition.condition = this.parseExpression();
|
|
5469
|
+
transition.conditions = this.expressionToAnimationConditions(transition.condition);
|
|
5470
|
+
} else if (clause === "on") {
|
|
5471
|
+
const event = this.parseIdentifierOrStringValue();
|
|
5472
|
+
transition.event = event;
|
|
5473
|
+
transition.conditions = [
|
|
5474
|
+
{
|
|
5475
|
+
type: "AnimationTransitionCondition",
|
|
5476
|
+
parameter: event,
|
|
5477
|
+
operator: "==",
|
|
5478
|
+
value: true,
|
|
5479
|
+
loc: { start: startLoc, end: this.currentLocation() }
|
|
5480
|
+
}
|
|
5481
|
+
];
|
|
5482
|
+
} else if (clause === "over" || clause === "duration") {
|
|
5483
|
+
transition.duration = this.parseNumberClauseValue();
|
|
5484
|
+
} else if (clause === "easing") {
|
|
5485
|
+
transition.easing = this.parseIdentifierOrStringValue();
|
|
5486
|
+
} else if (clause === "exittime" || clause === "exit_time") {
|
|
5487
|
+
transition.exitTime = this.parseNumberClauseValue();
|
|
5488
|
+
transition.hasExitTime = true;
|
|
5489
|
+
} else if (clause === "pausewhenexiting" || clause === "pause_when_exiting") {
|
|
5490
|
+
transition.pauseWhenExiting = this.parseOptionalBooleanFlag();
|
|
5491
|
+
} else if (clause === "priority") {
|
|
5492
|
+
transition.priority = this.parseNumberClauseValue();
|
|
5493
|
+
} else if (clause === "cantransitiontoself" || clause === "can_transition_to_self") {
|
|
5494
|
+
transition.canTransitionToSelf = this.parseOptionalBooleanFlag();
|
|
5495
|
+
} else {
|
|
5496
|
+
this.error(`Unknown animation transition clause "${clause}"`);
|
|
5497
|
+
break;
|
|
5498
|
+
}
|
|
5499
|
+
}
|
|
5500
|
+
transition.loc = { start: startLoc, end: this.currentLocation() };
|
|
5501
|
+
if (this.check("COMMA") || this.check("SEMICOLON")) this.advance();
|
|
5502
|
+
return transition;
|
|
5503
|
+
}
|
|
5504
|
+
parseStateNameValue() {
|
|
5505
|
+
if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
|
|
5506
|
+
return this.advance().value;
|
|
5507
|
+
}
|
|
5508
|
+
this.error(`Expected state name, got ${this.current().type}`);
|
|
5509
|
+
return this.isAtEnd() ? "" : this.advance().value;
|
|
5510
|
+
}
|
|
5511
|
+
parseNumberClauseValue() {
|
|
5512
|
+
if (this.check("COLON")) this.advance();
|
|
5513
|
+
const value = this.parseValue();
|
|
5514
|
+
return typeof value === "number" ? value : Number(value) || 0;
|
|
5515
|
+
}
|
|
5516
|
+
parseIdentifierOrStringValue() {
|
|
5517
|
+
if (this.check("COLON")) this.advance();
|
|
5518
|
+
if (this.check("STRING") || this.check("IDENTIFIER") || this.isKeywordAsIdentifier()) {
|
|
5519
|
+
return this.advance().value;
|
|
5520
|
+
}
|
|
5521
|
+
const value = this.parseValue();
|
|
5522
|
+
return value == null ? "" : String(value);
|
|
5523
|
+
}
|
|
5524
|
+
parseDottedIdentifierValue(message) {
|
|
5525
|
+
let value = this.parseIdentifierOrStringValue();
|
|
5526
|
+
if (!value) {
|
|
5527
|
+
this.error(message);
|
|
5528
|
+
}
|
|
5529
|
+
while (this.check("DOT")) {
|
|
5530
|
+
this.advance();
|
|
5531
|
+
const part = this.parseIdentifierOrStringValue();
|
|
5532
|
+
if (!part) {
|
|
5533
|
+
this.error("Expected property name after dot");
|
|
5534
|
+
break;
|
|
5535
|
+
}
|
|
5536
|
+
value += `.${part}`;
|
|
5537
|
+
}
|
|
5538
|
+
return value;
|
|
5539
|
+
}
|
|
5540
|
+
isIdentifierValue(value) {
|
|
5541
|
+
return (this.current().type === "IDENTIFIER" || this.isKeywordAsIdentifierType(this.current().type)) && this.current().value === value;
|
|
5542
|
+
}
|
|
5543
|
+
parseOptionalBooleanFlag() {
|
|
5544
|
+
if (this.check("COLON")) this.advance();
|
|
5545
|
+
if (this.check("BOOLEAN")) return this.advance().value === "true";
|
|
5546
|
+
if (this.check("IDENTIFIER")) {
|
|
5547
|
+
const value = this.current().value.toLowerCase();
|
|
5548
|
+
if (value === "true" || value === "false") {
|
|
5549
|
+
this.advance();
|
|
5550
|
+
return value === "true";
|
|
5551
|
+
}
|
|
5552
|
+
}
|
|
5553
|
+
return true;
|
|
5554
|
+
}
|
|
5555
|
+
expressionToAnimationConditions(expression) {
|
|
5556
|
+
if (expression.type === "BinaryExpression" && (expression.operator === "&&" || expression.operator === "||")) {
|
|
5557
|
+
const left = this.expressionToAnimationConditions(expression.left);
|
|
5558
|
+
const right = this.expressionToAnimationConditions(expression.right);
|
|
5559
|
+
if (left.length > 0 && right.length > 0) {
|
|
5560
|
+
left[left.length - 1].chain = expression.operator === "||" ? "or" : "and";
|
|
5561
|
+
}
|
|
5562
|
+
return [...left, ...right];
|
|
5563
|
+
}
|
|
5564
|
+
const comparison = this.expressionToAnimationCondition(expression);
|
|
5565
|
+
return comparison ? [comparison] : [];
|
|
5566
|
+
}
|
|
5567
|
+
expressionToAnimationCondition(expression) {
|
|
5568
|
+
const startLoc = expression.loc?.start ?? this.currentLocation();
|
|
5569
|
+
const endLoc = expression.loc?.end ?? this.currentLocation();
|
|
5570
|
+
if (expression.type === "BinaryExpression") {
|
|
5571
|
+
const normalizedOperator = this.normalizeAnimationConditionOperator(expression.operator);
|
|
5572
|
+
if (normalizedOperator) {
|
|
5573
|
+
const parameter = this.expressionToString(expression.left);
|
|
5574
|
+
if (parameter) {
|
|
5575
|
+
return {
|
|
5576
|
+
type: "AnimationTransitionCondition",
|
|
5577
|
+
parameter,
|
|
5578
|
+
operator: normalizedOperator,
|
|
5579
|
+
value: this.expressionLiteralValue(expression.right),
|
|
5580
|
+
loc: { start: startLoc, end: endLoc }
|
|
5581
|
+
};
|
|
5582
|
+
}
|
|
5583
|
+
}
|
|
5584
|
+
}
|
|
5585
|
+
if (expression.type === "Identifier" || expression.type === "MemberExpression") {
|
|
5586
|
+
return {
|
|
5587
|
+
type: "AnimationTransitionCondition",
|
|
5588
|
+
parameter: this.expressionToString(expression),
|
|
5589
|
+
operator: "==",
|
|
5590
|
+
value: true,
|
|
5591
|
+
loc: { start: startLoc, end: endLoc }
|
|
5592
|
+
};
|
|
5593
|
+
}
|
|
5594
|
+
if (expression.type === "UnaryExpression" && expression.operator === "!") {
|
|
5595
|
+
const parameter = this.expressionToString(expression.argument);
|
|
5596
|
+
if (parameter) {
|
|
5597
|
+
return {
|
|
5598
|
+
type: "AnimationTransitionCondition",
|
|
5599
|
+
parameter,
|
|
5600
|
+
operator: "==",
|
|
5601
|
+
value: false,
|
|
5602
|
+
loc: { start: startLoc, end: endLoc }
|
|
5603
|
+
};
|
|
5604
|
+
}
|
|
5605
|
+
}
|
|
5606
|
+
return null;
|
|
5607
|
+
}
|
|
5608
|
+
normalizeAnimationConditionOperator(operator) {
|
|
5609
|
+
if (operator === "===") return "==";
|
|
5610
|
+
if (operator === "!==") return "!=";
|
|
5611
|
+
if (operator === "==" || operator === "!=" || operator === ">" || operator === "<" || operator === ">=" || operator === "<=") {
|
|
5612
|
+
return operator;
|
|
5613
|
+
}
|
|
5614
|
+
return null;
|
|
5615
|
+
}
|
|
5616
|
+
expressionLiteralValue(expression) {
|
|
5617
|
+
if (expression.type === "Literal") {
|
|
5618
|
+
if (expression.value === null) return "null";
|
|
5619
|
+
return expression.value;
|
|
5620
|
+
}
|
|
5621
|
+
const value = this.expressionToString(expression);
|
|
5622
|
+
return value || "";
|
|
5623
|
+
}
|
|
4656
5624
|
parseStateTransitions() {
|
|
5625
|
+
if (this.check("LBRACE")) {
|
|
5626
|
+
this.expect("LBRACE");
|
|
5627
|
+
this.skipNewlines();
|
|
5628
|
+
const transitions2 = [];
|
|
5629
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5630
|
+
this.skipNewlines();
|
|
5631
|
+
if (this.check("RBRACE")) break;
|
|
5632
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
5633
|
+
transitions2.push(this.parseAnimationTransitionShorthand());
|
|
5634
|
+
} else {
|
|
5635
|
+
this.error(`Expected animation transition, got ${this.current().type}`);
|
|
5636
|
+
this.advance();
|
|
5637
|
+
}
|
|
5638
|
+
this.skipNewlines();
|
|
5639
|
+
}
|
|
5640
|
+
this.expect("RBRACE");
|
|
5641
|
+
return transitions2;
|
|
5642
|
+
}
|
|
4657
5643
|
this.expect("LBRACKET");
|
|
4658
5644
|
this.skipNewlines();
|
|
4659
5645
|
const transitions = [];
|
|
4660
5646
|
while (!this.check("RBRACKET") && !this.isAtEnd()) {
|
|
4661
5647
|
this.skipNewlines();
|
|
4662
5648
|
if (this.check("RBRACKET")) break;
|
|
5649
|
+
if (this.isAnimationTransitionShorthandStart()) {
|
|
5650
|
+
transitions.push(this.parseAnimationTransitionShorthand());
|
|
5651
|
+
this.skipNewlines();
|
|
5652
|
+
continue;
|
|
5653
|
+
}
|
|
4663
5654
|
this.expect("LBRACE");
|
|
4664
5655
|
this.skipNewlines();
|
|
4665
5656
|
const transition = {
|
|
@@ -4671,9 +5662,46 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4671
5662
|
if (this.check("RBRACE")) break;
|
|
4672
5663
|
const key = this.expectIdentifier();
|
|
4673
5664
|
this.expect("COLON");
|
|
4674
|
-
if (key === "
|
|
4675
|
-
|
|
4676
|
-
|
|
5665
|
+
if (key === "from") {
|
|
5666
|
+
const from = this.parseValue();
|
|
5667
|
+
transition.from = from.toLowerCase() === "any" ? "any" : from;
|
|
5668
|
+
} else if (key === "target" || key === "to") {
|
|
5669
|
+
transition.target = this.parseValue();
|
|
5670
|
+
} else if (key === "condition" || key === "when") {
|
|
5671
|
+
transition.condition = this.parseExpression();
|
|
5672
|
+
transition.conditions = this.expressionToAnimationConditions(transition.condition);
|
|
5673
|
+
} else if (key === "event" || key === "on") {
|
|
5674
|
+
transition.event = this.parseValue();
|
|
5675
|
+
transition.conditions = [
|
|
5676
|
+
{
|
|
5677
|
+
type: "AnimationTransitionCondition",
|
|
5678
|
+
parameter: transition.event,
|
|
5679
|
+
operator: "==",
|
|
5680
|
+
value: true,
|
|
5681
|
+
loc: transition.loc
|
|
5682
|
+
}
|
|
5683
|
+
];
|
|
5684
|
+
} else if (key === "duration" || key === "over") {
|
|
5685
|
+
const duration = this.parseValue();
|
|
5686
|
+
transition.duration = typeof duration === "number" ? duration : Number(duration) || 0;
|
|
5687
|
+
} else if (key === "easing") {
|
|
5688
|
+
transition.easing = this.parseValue();
|
|
5689
|
+
} else if (key === "exitTime" || key === "exit_time") {
|
|
5690
|
+
const exitTime = this.parseValue();
|
|
5691
|
+
transition.exitTime = typeof exitTime === "number" ? exitTime : Number(exitTime) || 0;
|
|
5692
|
+
transition.hasExitTime = true;
|
|
5693
|
+
} else if (key === "hasExitTime" || key === "has_exit_time") {
|
|
5694
|
+
transition.hasExitTime = Boolean(this.parseValue());
|
|
5695
|
+
} else if (key === "pauseWhenExiting" || key === "pause_when_exiting") {
|
|
5696
|
+
transition.pauseWhenExiting = Boolean(this.parseValue());
|
|
5697
|
+
} else if (key === "priority") {
|
|
5698
|
+
const priority = this.parseValue();
|
|
5699
|
+
transition.priority = typeof priority === "number" ? priority : Number(priority) || 0;
|
|
5700
|
+
} else if (key === "canTransitionToSelf" || key === "can_transition_to_self") {
|
|
5701
|
+
transition.canTransitionToSelf = Boolean(this.parseValue());
|
|
5702
|
+
} else {
|
|
5703
|
+
this.parseValue();
|
|
5704
|
+
}
|
|
4677
5705
|
this.skipNewlines();
|
|
4678
5706
|
}
|
|
4679
5707
|
this.expect("RBRACE");
|
|
@@ -4963,32 +5991,714 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4963
5991
|
isDomainBlockToken() {
|
|
4964
5992
|
return _HoloCompositionParser.DOMAIN_TOKENS.has(this.current().type);
|
|
4965
5993
|
}
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
this.
|
|
5994
|
+
isLooseOnHandlerStart() {
|
|
5995
|
+
return this.check("IDENTIFIER") && this.current().value === "on";
|
|
5996
|
+
}
|
|
5997
|
+
skipLooseOnHandler() {
|
|
5998
|
+
if (!this.isLooseOnHandlerStart()) return;
|
|
5999
|
+
this.advance();
|
|
6000
|
+
while (!this.check("LBRACE") && !this.isAtEnd()) {
|
|
6001
|
+
if (this.check("LPAREN")) {
|
|
6002
|
+
this.skipParens();
|
|
6003
|
+
} else {
|
|
6004
|
+
this.advance();
|
|
6005
|
+
}
|
|
6006
|
+
}
|
|
6007
|
+
if (this.check("LBRACE")) {
|
|
6008
|
+
this.skipBlock();
|
|
6009
|
+
}
|
|
6010
|
+
}
|
|
6011
|
+
isLooseDomainBlockStart() {
|
|
6012
|
+
if (!this.check("IDENTIFIER")) return false;
|
|
6013
|
+
const keyword = this.current().value;
|
|
6014
|
+
if (!/_material$/i.test(keyword)) return false;
|
|
6015
|
+
let index = this.pos + 1;
|
|
6016
|
+
if (this.tokens[index]?.type === "STRING" || this.tokens[index]?.type === "IDENTIFIER") {
|
|
6017
|
+
index++;
|
|
6018
|
+
}
|
|
6019
|
+
while (this.tokens[index]?.type === "AT") {
|
|
6020
|
+
index += 2;
|
|
6021
|
+
if (this.tokens[index]?.type === "LPAREN") {
|
|
6022
|
+
let depth = 1;
|
|
6023
|
+
index++;
|
|
6024
|
+
while (depth > 0 && index < this.tokens.length) {
|
|
6025
|
+
if (this.tokens[index].type === "LPAREN") depth++;
|
|
6026
|
+
else if (this.tokens[index].type === "RPAREN") depth--;
|
|
6027
|
+
index++;
|
|
6028
|
+
}
|
|
6029
|
+
}
|
|
6030
|
+
}
|
|
6031
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
6032
|
+
return this.tokens[index]?.type === "LBRACE";
|
|
6033
|
+
}
|
|
6034
|
+
isLooseNamedDomainBlockStart() {
|
|
6035
|
+
if (!this.check("IDENTIFIER")) return false;
|
|
6036
|
+
const keyword = this.current().value.toLowerCase();
|
|
6037
|
+
if (this.isPrimitiveShape(keyword) || this.isLightPrimitive(keyword) || keyword === "on") {
|
|
6038
|
+
return false;
|
|
6039
|
+
}
|
|
6040
|
+
let index = this.pos + 1;
|
|
6041
|
+
if (this.tokens[index]?.type !== "STRING" && this.tokens[index]?.type !== "IDENTIFIER") {
|
|
6042
|
+
return false;
|
|
6043
|
+
}
|
|
6044
|
+
index++;
|
|
6045
|
+
while (this.tokens[index]?.type === "AT") {
|
|
6046
|
+
index += 2;
|
|
6047
|
+
if (this.tokens[index]?.type === "LPAREN") {
|
|
6048
|
+
let depth = 1;
|
|
6049
|
+
index++;
|
|
6050
|
+
while (depth > 0 && index < this.tokens.length) {
|
|
6051
|
+
if (this.tokens[index].type === "LPAREN") depth++;
|
|
6052
|
+
else if (this.tokens[index].type === "RPAREN") depth--;
|
|
6053
|
+
index++;
|
|
6054
|
+
}
|
|
6055
|
+
}
|
|
6056
|
+
}
|
|
6057
|
+
while (this.tokens[index]?.type === "NEWLINE") index++;
|
|
6058
|
+
return this.tokens[index]?.type === "LBRACE";
|
|
6059
|
+
}
|
|
6060
|
+
// ===========================================================================
|
|
6061
|
+
// MMO/AAA GAME CONSTRUCTS (v6.2 — June 2026)
|
|
6062
|
+
// ===========================================================================
|
|
6063
|
+
/**
|
|
6064
|
+
* Parse a loot_table block with weighted entry sub-blocks and optional
|
|
6065
|
+
* guaranteed drop section.
|
|
6066
|
+
*
|
|
6067
|
+
* Syntax:
|
|
6068
|
+
* loot_table goblin_drops {
|
|
6069
|
+
* entry common_coin { item: "gold_coin" qty: "1..5" weight: 60 }
|
|
6070
|
+
* entry nothing { weight: 10 }
|
|
6071
|
+
* guaranteed { item: "goblin_ear" qty: 1 }
|
|
6072
|
+
* multiplier_on_faction_hostile: "ironveil * 1.5"
|
|
6073
|
+
* }
|
|
6074
|
+
*/
|
|
6075
|
+
parseLootTable() {
|
|
6076
|
+
const startLoc = this.currentLocation();
|
|
6077
|
+
this.pushContext("loot-table");
|
|
6078
|
+
this.advance();
|
|
6079
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6080
|
+
this.expect("LBRACE");
|
|
6081
|
+
this.skipNewlines();
|
|
6082
|
+
const entries = [];
|
|
6083
|
+
let guaranteed;
|
|
6084
|
+
const properties = {};
|
|
6085
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6086
|
+
this.skipNewlines();
|
|
6087
|
+
if (this.check("RBRACE")) break;
|
|
6088
|
+
if (this.check("IDENTIFIER") && this.current().value === "entry") {
|
|
6089
|
+
this.advance();
|
|
6090
|
+
const entryId = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6091
|
+
const entryProps = {};
|
|
6092
|
+
let weight = 0;
|
|
6093
|
+
let itemId;
|
|
6094
|
+
let qty;
|
|
6095
|
+
let rarity;
|
|
6096
|
+
let condition;
|
|
6097
|
+
if (this.check("LBRACE")) {
|
|
6098
|
+
this.advance();
|
|
6099
|
+
this.skipNewlines();
|
|
6100
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6101
|
+
this.skipNewlines();
|
|
6102
|
+
if (this.check("RBRACE")) break;
|
|
6103
|
+
const key = this.expectIdentifier();
|
|
6104
|
+
this.expect("COLON");
|
|
6105
|
+
const val = this.parseValue();
|
|
6106
|
+
if (key === "item") itemId = val;
|
|
6107
|
+
else if (key === "weight") weight = val;
|
|
6108
|
+
else if (key === "qty") qty = val;
|
|
6109
|
+
else if (key === "rarity") rarity = val;
|
|
6110
|
+
else if (key === "condition") condition = val;
|
|
6111
|
+
else entryProps[key] = val;
|
|
6112
|
+
if (this.check("COMMA")) this.advance();
|
|
6113
|
+
this.skipNewlines();
|
|
6114
|
+
}
|
|
6115
|
+
this.expect("RBRACE");
|
|
6116
|
+
}
|
|
6117
|
+
entries.push({
|
|
6118
|
+
type: "LootEntry",
|
|
6119
|
+
id: entryId,
|
|
6120
|
+
itemId,
|
|
6121
|
+
weight,
|
|
6122
|
+
qty,
|
|
6123
|
+
rarity,
|
|
6124
|
+
condition,
|
|
6125
|
+
properties: entryProps
|
|
6126
|
+
});
|
|
6127
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "guaranteed") {
|
|
6128
|
+
this.advance();
|
|
6129
|
+
if (this.check("LBRACE")) {
|
|
6130
|
+
this.advance();
|
|
6131
|
+
this.skipNewlines();
|
|
6132
|
+
guaranteed = {};
|
|
6133
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6134
|
+
this.skipNewlines();
|
|
6135
|
+
if (this.check("RBRACE")) break;
|
|
6136
|
+
const key = this.expectIdentifier();
|
|
6137
|
+
this.expect("COLON");
|
|
6138
|
+
guaranteed[key] = this.parseValue();
|
|
6139
|
+
if (this.check("COMMA")) this.advance();
|
|
6140
|
+
this.skipNewlines();
|
|
6141
|
+
}
|
|
6142
|
+
this.expect("RBRACE");
|
|
6143
|
+
}
|
|
6144
|
+
} else {
|
|
6145
|
+
const key = this.expectIdentifier();
|
|
6146
|
+
this.expect("COLON");
|
|
6147
|
+
properties[key] = this.parseValue();
|
|
6148
|
+
}
|
|
6149
|
+
if (this.check("COMMA")) this.advance();
|
|
6150
|
+
this.skipNewlines();
|
|
6151
|
+
}
|
|
6152
|
+
this.expect("RBRACE");
|
|
6153
|
+
this.popContext();
|
|
6154
|
+
return {
|
|
6155
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6156
|
+
type: "LootTable",
|
|
6157
|
+
name,
|
|
6158
|
+
entries,
|
|
6159
|
+
guaranteed,
|
|
6160
|
+
properties
|
|
6161
|
+
};
|
|
6162
|
+
}
|
|
6163
|
+
/**
|
|
6164
|
+
* Parse a world_chunk block for open-world streaming.
|
|
6165
|
+
*
|
|
6166
|
+
* Syntax:
|
|
6167
|
+
* world_chunk dockside {
|
|
6168
|
+
* bounds: ((-200, 0, -200), (200, 100, 200))
|
|
6169
|
+
* priority: "high"
|
|
6170
|
+
* lod_distances: [50, 150, 400]
|
|
6171
|
+
* biome: "coastal_urban"
|
|
6172
|
+
* npc_roster: ["merchant_alva", "harbor_guard_01"]
|
|
6173
|
+
* streaming { load_radius: 300 unload_radius: 500 budget_kb: 32768 }
|
|
6174
|
+
* }
|
|
6175
|
+
*/
|
|
6176
|
+
parseWorldChunk() {
|
|
6177
|
+
const startLoc = this.currentLocation();
|
|
6178
|
+
this.pushContext("world-chunk");
|
|
6179
|
+
this.advance();
|
|
6180
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6181
|
+
this.expect("LBRACE");
|
|
6182
|
+
this.skipNewlines();
|
|
6183
|
+
const properties = {};
|
|
6184
|
+
let priority;
|
|
6185
|
+
let biome;
|
|
6186
|
+
let lodDistances;
|
|
6187
|
+
let assetManifest;
|
|
6188
|
+
let npcRoster;
|
|
6189
|
+
let spawnPoints;
|
|
6190
|
+
let streaming;
|
|
6191
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6192
|
+
this.skipNewlines();
|
|
6193
|
+
if (this.check("RBRACE")) break;
|
|
6194
|
+
if (this.check("IDENTIFIER") && this.current().value === "streaming") {
|
|
6195
|
+
this.advance();
|
|
6196
|
+
if (this.check("LBRACE")) {
|
|
6197
|
+
this.advance();
|
|
6198
|
+
this.skipNewlines();
|
|
6199
|
+
streaming = {};
|
|
6200
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6201
|
+
this.skipNewlines();
|
|
6202
|
+
if (this.check("RBRACE")) break;
|
|
6203
|
+
const key = this.expectIdentifier();
|
|
6204
|
+
this.expect("COLON");
|
|
6205
|
+
streaming[key] = this.parseValue();
|
|
6206
|
+
if (this.check("COMMA")) this.advance();
|
|
6207
|
+
this.skipNewlines();
|
|
6208
|
+
}
|
|
6209
|
+
this.expect("RBRACE");
|
|
6210
|
+
}
|
|
6211
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "asset_manifest") {
|
|
6212
|
+
this.advance();
|
|
6213
|
+
const val = this.parseValue();
|
|
6214
|
+
assetManifest = Array.isArray(val) ? val : [val];
|
|
6215
|
+
} else {
|
|
6216
|
+
const key = this.expectIdentifier();
|
|
6217
|
+
this.expect("COLON");
|
|
6218
|
+
const val = this.parseValue();
|
|
6219
|
+
if (key === "priority") priority = val;
|
|
6220
|
+
else if (key === "biome") biome = val;
|
|
6221
|
+
else if (key === "lod_distances")
|
|
6222
|
+
lodDistances = Array.isArray(val) ? val : [val];
|
|
6223
|
+
else if (key === "npc_roster") npcRoster = Array.isArray(val) ? val : [val];
|
|
6224
|
+
else if (key === "spawn_points") spawnPoints = val;
|
|
6225
|
+
else properties[key] = val;
|
|
6226
|
+
}
|
|
6227
|
+
if (this.check("COMMA")) this.advance();
|
|
6228
|
+
this.skipNewlines();
|
|
6229
|
+
}
|
|
6230
|
+
this.expect("RBRACE");
|
|
6231
|
+
this.popContext();
|
|
6232
|
+
return {
|
|
6233
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6234
|
+
type: "WorldChunk",
|
|
6235
|
+
name,
|
|
6236
|
+
priority,
|
|
6237
|
+
biome,
|
|
6238
|
+
lodDistances,
|
|
6239
|
+
assetManifest,
|
|
6240
|
+
npcRoster,
|
|
6241
|
+
spawnPoints,
|
|
6242
|
+
streaming,
|
|
6243
|
+
properties
|
|
6244
|
+
};
|
|
6245
|
+
}
|
|
6246
|
+
/**
|
|
6247
|
+
* Parse a world_layer block (P2.4 — phasing).
|
|
6248
|
+
*
|
|
6249
|
+
* Syntax:
|
|
6250
|
+
* world_layer post_awakening {
|
|
6251
|
+
* requires_quest: "main_chapter_1" // visible AFTER the quest is done
|
|
6252
|
+
* npcs: ["restored_keeper"] // forbids_quest = visible BEFORE
|
|
6253
|
+
* objects: ["healed_shrine"]
|
|
6254
|
+
* }
|
|
6255
|
+
*/
|
|
6256
|
+
parseWorldLayer() {
|
|
6257
|
+
const startLoc = this.currentLocation();
|
|
6258
|
+
this.pushContext("world-layer");
|
|
6259
|
+
this.advance();
|
|
6260
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6261
|
+
this.expect("LBRACE");
|
|
6262
|
+
this.skipNewlines();
|
|
6263
|
+
const properties = {};
|
|
6264
|
+
let questId = "";
|
|
6265
|
+
let mustBeCompleted = true;
|
|
6266
|
+
let npcs = [];
|
|
6267
|
+
let objects = [];
|
|
6268
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6269
|
+
this.skipNewlines();
|
|
6270
|
+
if (this.check("RBRACE")) break;
|
|
6271
|
+
const key = this.expectIdentifier();
|
|
6272
|
+
this.expect("COLON");
|
|
6273
|
+
const val = this.parseValue();
|
|
6274
|
+
if (key === "requires_quest") {
|
|
6275
|
+
questId = String(val);
|
|
6276
|
+
mustBeCompleted = true;
|
|
6277
|
+
} else if (key === "forbids_quest") {
|
|
6278
|
+
questId = String(val);
|
|
6279
|
+
mustBeCompleted = false;
|
|
6280
|
+
} else if (key === "npcs") {
|
|
6281
|
+
npcs = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6282
|
+
} else if (key === "objects") {
|
|
6283
|
+
objects = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6284
|
+
} else {
|
|
6285
|
+
properties[key] = val;
|
|
6286
|
+
}
|
|
6287
|
+
if (this.check("COMMA")) this.advance();
|
|
6288
|
+
this.skipNewlines();
|
|
6289
|
+
}
|
|
6290
|
+
this.expect("RBRACE");
|
|
6291
|
+
this.popContext();
|
|
6292
|
+
return {
|
|
6293
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6294
|
+
type: "WorldLayer",
|
|
6295
|
+
name,
|
|
6296
|
+
predicate: { type: "PhasePredicate", kind: "quest_flag", questId, mustBeCompleted },
|
|
6297
|
+
npcs,
|
|
6298
|
+
objects,
|
|
6299
|
+
properties
|
|
6300
|
+
};
|
|
6301
|
+
}
|
|
6302
|
+
/**
|
|
6303
|
+
* Parse a dungeon_instance block (P2.6 — instanced content).
|
|
6304
|
+
*
|
|
6305
|
+
* Syntax:
|
|
6306
|
+
* dungeon_instance shadowfen_keep {
|
|
6307
|
+
* max_instances: 10
|
|
6308
|
+
* party_size: 5
|
|
6309
|
+
* reset_timer: 3600
|
|
6310
|
+
* completion_quest: "shadowfen_cleared"
|
|
6311
|
+
* npcs: ["dungeon_boss"]
|
|
6312
|
+
* }
|
|
6313
|
+
*/
|
|
6314
|
+
parseDungeonInstance() {
|
|
6315
|
+
const startLoc = this.currentLocation();
|
|
6316
|
+
this.pushContext("dungeon-instance");
|
|
6317
|
+
this.advance();
|
|
6318
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6319
|
+
this.expect("LBRACE");
|
|
6320
|
+
this.skipNewlines();
|
|
6321
|
+
const properties = {};
|
|
6322
|
+
let maxInstances = 1;
|
|
6323
|
+
let partySize = 1;
|
|
6324
|
+
let resetTimer = 0;
|
|
6325
|
+
let completionQuest = "";
|
|
6326
|
+
let npcs = [];
|
|
6327
|
+
let objects = [];
|
|
6328
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6329
|
+
this.skipNewlines();
|
|
6330
|
+
if (this.check("RBRACE")) break;
|
|
6331
|
+
const key = this.expectIdentifier();
|
|
6332
|
+
this.expect("COLON");
|
|
6333
|
+
const val = this.parseValue();
|
|
6334
|
+
if (key === "max_instances") maxInstances = Number(val) || 1;
|
|
6335
|
+
else if (key === "party_size") partySize = Number(val) || 1;
|
|
6336
|
+
else if (key === "reset_timer") resetTimer = Number(val) || 0;
|
|
6337
|
+
else if (key === "completion_quest") completionQuest = String(val);
|
|
6338
|
+
else if (key === "npcs") npcs = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6339
|
+
else if (key === "objects")
|
|
6340
|
+
objects = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6341
|
+
else properties[key] = val;
|
|
6342
|
+
if (this.check("COMMA")) this.advance();
|
|
6343
|
+
this.skipNewlines();
|
|
6344
|
+
}
|
|
6345
|
+
this.expect("RBRACE");
|
|
6346
|
+
this.popContext();
|
|
6347
|
+
return {
|
|
6348
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6349
|
+
type: "DungeonInstance",
|
|
6350
|
+
name,
|
|
6351
|
+
maxInstances,
|
|
6352
|
+
partySize,
|
|
6353
|
+
resetTimer,
|
|
6354
|
+
completionQuest,
|
|
6355
|
+
npcs,
|
|
6356
|
+
objects,
|
|
6357
|
+
properties
|
|
6358
|
+
};
|
|
6359
|
+
}
|
|
6360
|
+
/**
|
|
6361
|
+
* Parse a world_shard block (P2.5 — world sharding).
|
|
6362
|
+
*
|
|
6363
|
+
* Syntax:
|
|
6364
|
+
* world_shard north_province {
|
|
6365
|
+
* min: [-1000, 0, -1000]
|
|
6366
|
+
* max: [0, 256, 1000]
|
|
6367
|
+
* neighbors: ["south_province"]
|
|
6368
|
+
* max_players: 200
|
|
6369
|
+
* handoff: "seamless"
|
|
6370
|
+
* }
|
|
6371
|
+
*/
|
|
6372
|
+
parseWorldShard() {
|
|
6373
|
+
const startLoc = this.currentLocation();
|
|
6374
|
+
this.pushContext("world-shard");
|
|
6375
|
+
this.advance();
|
|
6376
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6377
|
+
this.expect("LBRACE");
|
|
6378
|
+
this.skipNewlines();
|
|
6379
|
+
const properties = {};
|
|
6380
|
+
let min = [0, 0, 0];
|
|
6381
|
+
let max = [0, 0, 0];
|
|
6382
|
+
let neighbors = [];
|
|
6383
|
+
let maxPlayers = 100;
|
|
6384
|
+
let handoff = "seamless";
|
|
6385
|
+
const toVec3 = (val) => {
|
|
6386
|
+
const a = (Array.isArray(val) ? val : [val]).map((v) => Number(v) || 0);
|
|
6387
|
+
return [a[0] ?? 0, a[1] ?? 0, a[2] ?? 0];
|
|
6388
|
+
};
|
|
6389
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6390
|
+
this.skipNewlines();
|
|
6391
|
+
if (this.check("RBRACE")) break;
|
|
6392
|
+
const key = this.expectIdentifier();
|
|
6393
|
+
this.expect("COLON");
|
|
6394
|
+
const val = this.parseValue();
|
|
6395
|
+
if (key === "min") min = toVec3(val);
|
|
6396
|
+
else if (key === "max") max = toVec3(val);
|
|
6397
|
+
else if (key === "neighbors")
|
|
6398
|
+
neighbors = (Array.isArray(val) ? val : [val]).map((v) => String(v));
|
|
6399
|
+
else if (key === "max_players") maxPlayers = Number(val) || 100;
|
|
6400
|
+
else if (key === "handoff") handoff = String(val);
|
|
6401
|
+
else properties[key] = val;
|
|
6402
|
+
if (this.check("COMMA")) this.advance();
|
|
6403
|
+
this.skipNewlines();
|
|
6404
|
+
}
|
|
6405
|
+
this.expect("RBRACE");
|
|
6406
|
+
this.popContext();
|
|
6407
|
+
return {
|
|
6408
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6409
|
+
type: "WorldShard",
|
|
6410
|
+
name,
|
|
6411
|
+
min,
|
|
6412
|
+
max,
|
|
6413
|
+
neighbors,
|
|
6414
|
+
maxPlayers,
|
|
6415
|
+
handoff,
|
|
6416
|
+
properties
|
|
6417
|
+
};
|
|
6418
|
+
}
|
|
6419
|
+
/**
|
|
6420
|
+
* Parse a spawn_point block.
|
|
6421
|
+
*
|
|
6422
|
+
* Syntax:
|
|
6423
|
+
* spawn_point village_entry {
|
|
6424
|
+
* faction: "neutral"
|
|
6425
|
+
* max_count: 10
|
|
6426
|
+
* respawn_radius: 5
|
|
6427
|
+
* position: (10, 0, 10)
|
|
6428
|
+
* }
|
|
6429
|
+
*/
|
|
6430
|
+
parseSpawnPoint() {
|
|
6431
|
+
const startLoc = this.currentLocation();
|
|
6432
|
+
this.pushContext("spawn-point");
|
|
6433
|
+
this.advance();
|
|
6434
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6435
|
+
this.expect("LBRACE");
|
|
6436
|
+
this.skipNewlines();
|
|
6437
|
+
const properties = {};
|
|
6438
|
+
let faction;
|
|
6439
|
+
let maxCount;
|
|
6440
|
+
let respawnRadius;
|
|
6441
|
+
let position;
|
|
6442
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6443
|
+
this.skipNewlines();
|
|
6444
|
+
if (this.check("RBRACE")) break;
|
|
6445
|
+
const key = this.expectIdentifier();
|
|
6446
|
+
this.expect("COLON");
|
|
6447
|
+
const val = this.parseValue();
|
|
6448
|
+
if (key === "faction") faction = val;
|
|
6449
|
+
else if (key === "max_count") maxCount = val;
|
|
6450
|
+
else if (key === "respawn_radius") respawnRadius = val;
|
|
6451
|
+
else if (key === "position") {
|
|
6452
|
+
if (Array.isArray(val) && val.length >= 3) {
|
|
6453
|
+
position = { x: val[0], y: val[1], z: val[2] };
|
|
6454
|
+
}
|
|
6455
|
+
} else {
|
|
6456
|
+
properties[key] = val;
|
|
6457
|
+
}
|
|
6458
|
+
if (this.check("COMMA")) this.advance();
|
|
6459
|
+
this.skipNewlines();
|
|
6460
|
+
}
|
|
6461
|
+
this.expect("RBRACE");
|
|
6462
|
+
this.popContext();
|
|
6463
|
+
return {
|
|
6464
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6465
|
+
type: "SpawnPoint",
|
|
6466
|
+
name,
|
|
6467
|
+
faction,
|
|
6468
|
+
maxCount,
|
|
6469
|
+
respawnRadius,
|
|
6470
|
+
position,
|
|
6471
|
+
properties
|
|
6472
|
+
};
|
|
6473
|
+
}
|
|
6474
|
+
/**
|
|
6475
|
+
* Parse a trigger block for MMO interaction volumes.
|
|
6476
|
+
*
|
|
6477
|
+
* Syntax:
|
|
6478
|
+
* trigger dungeon_entrance {
|
|
6479
|
+
* radius: 3
|
|
6480
|
+
* faction_filter: ["alliance", "neutral"]
|
|
6481
|
+
* on_enter { emit("dungeon_enter") }
|
|
6482
|
+
* on_exit { emit("dungeon_exit") }
|
|
6483
|
+
* }
|
|
6484
|
+
*/
|
|
6485
|
+
parseGameTrigger() {
|
|
6486
|
+
const startLoc = this.currentLocation();
|
|
6487
|
+
this.pushContext("game-trigger");
|
|
6488
|
+
this.advance();
|
|
6489
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6490
|
+
this.expect("LBRACE");
|
|
6491
|
+
this.skipNewlines();
|
|
6492
|
+
const properties = {};
|
|
6493
|
+
let radius = 1;
|
|
6494
|
+
let factionFilter;
|
|
6495
|
+
let position;
|
|
6496
|
+
const onEnter = [];
|
|
6497
|
+
const onExit = [];
|
|
6498
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6499
|
+
this.skipNewlines();
|
|
6500
|
+
if (this.check("RBRACE")) break;
|
|
6501
|
+
if (this.check("IDENTIFIER") && this.current().value === "on_enter") {
|
|
6502
|
+
this.advance();
|
|
6503
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6504
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6505
|
+
this.advance();
|
|
6506
|
+
this.skipNewlines();
|
|
6507
|
+
const stmts = this.parseStatementBlock();
|
|
6508
|
+
this.expect("RBRACE");
|
|
6509
|
+
return stmts;
|
|
6510
|
+
})() : [];
|
|
6511
|
+
onEnter.push({ type: "EventHandler", event: "on_enter", parameters: params, body });
|
|
6512
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on_exit") {
|
|
6513
|
+
this.advance();
|
|
6514
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6515
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6516
|
+
this.advance();
|
|
6517
|
+
this.skipNewlines();
|
|
6518
|
+
const stmts = this.parseStatementBlock();
|
|
6519
|
+
this.expect("RBRACE");
|
|
6520
|
+
return stmts;
|
|
6521
|
+
})() : [];
|
|
6522
|
+
onExit.push({ type: "EventHandler", event: "on_exit", parameters: params, body });
|
|
6523
|
+
} else {
|
|
6524
|
+
const key = this.expectIdentifier();
|
|
6525
|
+
this.expect("COLON");
|
|
6526
|
+
const val = this.parseValue();
|
|
6527
|
+
if (key === "radius") radius = val;
|
|
6528
|
+
else if (key === "faction_filter")
|
|
6529
|
+
factionFilter = Array.isArray(val) ? val : [val];
|
|
6530
|
+
else if (key === "position") {
|
|
6531
|
+
if (Array.isArray(val) && val.length >= 3) {
|
|
6532
|
+
position = { x: val[0], y: val[1], z: val[2] };
|
|
6533
|
+
}
|
|
6534
|
+
} else {
|
|
6535
|
+
properties[key] = val;
|
|
6536
|
+
}
|
|
6537
|
+
}
|
|
6538
|
+
if (this.check("COMMA")) this.advance();
|
|
6539
|
+
this.skipNewlines();
|
|
6540
|
+
}
|
|
6541
|
+
this.expect("RBRACE");
|
|
6542
|
+
this.popContext();
|
|
6543
|
+
return {
|
|
6544
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6545
|
+
type: "GameTrigger",
|
|
6546
|
+
name,
|
|
6547
|
+
radius,
|
|
6548
|
+
factionFilter,
|
|
6549
|
+
onEnter: onEnter.length > 0 ? onEnter : void 0,
|
|
6550
|
+
onExit: onExit.length > 0 ? onExit : void 0,
|
|
6551
|
+
position,
|
|
6552
|
+
properties
|
|
6553
|
+
};
|
|
6554
|
+
}
|
|
6555
|
+
/**
|
|
6556
|
+
* Parse a scene-level movement path:
|
|
6557
|
+
* movement_path patrol_route { mode: "patrol" loop: true speed: 2.5
|
|
6558
|
+
* waypoints: [[0,0,0],[10,0,0]] easing: "linear" }
|
|
6559
|
+
*/
|
|
6560
|
+
parseMovementPath() {
|
|
6561
|
+
const startLoc = this.currentLocation();
|
|
6562
|
+
this.pushContext("movement-path");
|
|
6563
|
+
this.advance();
|
|
6564
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6565
|
+
this.expect("LBRACE");
|
|
6566
|
+
this.skipNewlines();
|
|
6567
|
+
const properties = {};
|
|
6568
|
+
let mode;
|
|
6569
|
+
let loop;
|
|
6570
|
+
let speed;
|
|
6571
|
+
let waypoints;
|
|
6572
|
+
let easing;
|
|
6573
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6574
|
+
this.skipNewlines();
|
|
6575
|
+
if (this.check("RBRACE")) break;
|
|
6576
|
+
const key = this.expectIdentifier();
|
|
6577
|
+
this.expect("COLON");
|
|
6578
|
+
const val = this.parseValue();
|
|
6579
|
+
if (key === "mode") mode = val;
|
|
6580
|
+
else if (key === "loop") loop = val;
|
|
6581
|
+
else if (key === "speed") speed = val;
|
|
6582
|
+
else if (key === "waypoints") waypoints = val;
|
|
6583
|
+
else if (key === "easing") easing = val;
|
|
6584
|
+
else properties[key] = val;
|
|
6585
|
+
if (this.check("COMMA")) this.advance();
|
|
6586
|
+
this.skipNewlines();
|
|
6587
|
+
}
|
|
6588
|
+
this.expect("RBRACE");
|
|
6589
|
+
this.popContext();
|
|
6590
|
+
return {
|
|
6591
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6592
|
+
type: "MovementPath",
|
|
6593
|
+
name,
|
|
6594
|
+
mode,
|
|
6595
|
+
loop,
|
|
6596
|
+
speed,
|
|
6597
|
+
waypoints,
|
|
6598
|
+
easing,
|
|
6599
|
+
properties
|
|
6600
|
+
};
|
|
6601
|
+
}
|
|
6602
|
+
/**
|
|
6603
|
+
* Parse a scene-level reaction trigger:
|
|
6604
|
+
* reaction_trigger on_player_enter { target: "player" condition: "..."
|
|
6605
|
+
* on_activate { emit("zone_entered") } on_deactivate { ... } cooldown: 2 }
|
|
6606
|
+
*/
|
|
6607
|
+
parseReactionTrigger() {
|
|
6608
|
+
const startLoc = this.currentLocation();
|
|
6609
|
+
this.pushContext("reaction-trigger");
|
|
6610
|
+
this.advance();
|
|
6611
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
6612
|
+
this.expect("LBRACE");
|
|
6613
|
+
this.skipNewlines();
|
|
6614
|
+
const properties = {};
|
|
6615
|
+
let target;
|
|
6616
|
+
let condition;
|
|
6617
|
+
let cooldown;
|
|
6618
|
+
const onActivate = [];
|
|
6619
|
+
const onDeactivate = [];
|
|
6620
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6621
|
+
this.skipNewlines();
|
|
6622
|
+
if (this.check("RBRACE")) break;
|
|
6623
|
+
if (this.check("IDENTIFIER") && this.current().value === "on_activate") {
|
|
6624
|
+
this.advance();
|
|
6625
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6626
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6627
|
+
this.advance();
|
|
6628
|
+
this.skipNewlines();
|
|
6629
|
+
const stmts = this.parseStatementBlock();
|
|
6630
|
+
this.expect("RBRACE");
|
|
6631
|
+
return stmts;
|
|
6632
|
+
})() : [];
|
|
6633
|
+
onActivate.push({ type: "EventHandler", event: "on_activate", parameters: params, body });
|
|
6634
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "on_deactivate") {
|
|
6635
|
+
this.advance();
|
|
6636
|
+
const params = this.check("LPAREN") ? this.parseParameterList() : [];
|
|
6637
|
+
const body = this.check("LBRACE") ? (() => {
|
|
6638
|
+
this.advance();
|
|
6639
|
+
this.skipNewlines();
|
|
6640
|
+
const stmts = this.parseStatementBlock();
|
|
6641
|
+
this.expect("RBRACE");
|
|
6642
|
+
return stmts;
|
|
6643
|
+
})() : [];
|
|
6644
|
+
onDeactivate.push({
|
|
6645
|
+
type: "EventHandler",
|
|
6646
|
+
event: "on_deactivate",
|
|
6647
|
+
parameters: params,
|
|
6648
|
+
body
|
|
6649
|
+
});
|
|
6650
|
+
} else {
|
|
6651
|
+
const key = this.expectIdentifier();
|
|
6652
|
+
this.expect("COLON");
|
|
6653
|
+
const val = this.parseValue();
|
|
6654
|
+
if (key === "target") target = val;
|
|
6655
|
+
else if (key === "condition") condition = val;
|
|
6656
|
+
else if (key === "cooldown") cooldown = val;
|
|
6657
|
+
else properties[key] = val;
|
|
6658
|
+
}
|
|
6659
|
+
if (this.check("COMMA")) this.advance();
|
|
6660
|
+
this.skipNewlines();
|
|
6661
|
+
}
|
|
6662
|
+
this.expect("RBRACE");
|
|
6663
|
+
this.popContext();
|
|
6664
|
+
return {
|
|
6665
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
6666
|
+
type: "ReactionTrigger",
|
|
6667
|
+
name,
|
|
6668
|
+
target,
|
|
6669
|
+
condition,
|
|
6670
|
+
cooldown,
|
|
6671
|
+
onActivate: onActivate.length > 0 ? onActivate : void 0,
|
|
6672
|
+
onDeactivate: onDeactivate.length > 0 ? onDeactivate : void 0,
|
|
6673
|
+
properties
|
|
6674
|
+
};
|
|
6675
|
+
}
|
|
6676
|
+
// ===========================================================================
|
|
6677
|
+
// NORM LIFECYCLE BLOCKS (v4.5 — March 2026, CRSEC Model)
|
|
6678
|
+
// ===========================================================================
|
|
6679
|
+
/**
|
|
6680
|
+
* Parse a norm block with full CRSEC lifecycle sub-blocks.
|
|
6681
|
+
*
|
|
6682
|
+
* Pattern:
|
|
6683
|
+
* ```
|
|
6684
|
+
* norm "NormName" @trait1 @trait2 {
|
|
6685
|
+
* description: "..."
|
|
6686
|
+
* category: "..."
|
|
6687
|
+
* priority: 8
|
|
6688
|
+
*
|
|
6689
|
+
* creation { ... }
|
|
6690
|
+
* representation { ... }
|
|
6691
|
+
* spreading { ... }
|
|
6692
|
+
* evaluation { ... }
|
|
6693
|
+
* compliance { ... }
|
|
6694
|
+
*
|
|
6695
|
+
* on norm_violated(agent, context) { ... }
|
|
6696
|
+
* }
|
|
6697
|
+
* ```
|
|
6698
|
+
*/
|
|
6699
|
+
parseNormBlock() {
|
|
6700
|
+
const startLoc = this.currentLocation();
|
|
6701
|
+
this.pushContext("norm");
|
|
4992
6702
|
this.advance();
|
|
4993
6703
|
let name = "unnamed";
|
|
4994
6704
|
if (this.check("STRING")) {
|
|
@@ -4996,15 +6706,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
4996
6706
|
} else if (this.check("IDENTIFIER")) {
|
|
4997
6707
|
name = this.expectIdentifier();
|
|
4998
6708
|
}
|
|
4999
|
-
const traits =
|
|
5000
|
-
while (this.check("AT") && this.peek(1)?.type === "IDENTIFIER") {
|
|
5001
|
-
this.advance();
|
|
5002
|
-
traits.push(this.current().value);
|
|
5003
|
-
this.advance();
|
|
5004
|
-
if (this.check("LPAREN")) {
|
|
5005
|
-
this.skipParens();
|
|
5006
|
-
}
|
|
5007
|
-
}
|
|
6709
|
+
const traits = this.parseInlineTraitNamesBeforeBlock();
|
|
5008
6710
|
this.expect("LBRACE");
|
|
5009
6711
|
this.skipNewlines();
|
|
5010
6712
|
const properties = {};
|
|
@@ -5058,6 +6760,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5058
6760
|
body
|
|
5059
6761
|
});
|
|
5060
6762
|
}
|
|
6763
|
+
} else if (this.isPropertyName() && this.peek(1)?.type === "LBRACE") {
|
|
6764
|
+
const key = this.parsePropertyKey();
|
|
6765
|
+
properties[key] = this.parseBlockTraitConfig();
|
|
5061
6766
|
} else if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
5062
6767
|
const key = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
5063
6768
|
this.expect("COLON");
|
|
@@ -5137,15 +6842,7 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5137
6842
|
} else if (this.check("IDENTIFIER")) {
|
|
5138
6843
|
name = this.expectIdentifier();
|
|
5139
6844
|
}
|
|
5140
|
-
const traits =
|
|
5141
|
-
while (this.check("AT") && this.peek(1)?.type === "IDENTIFIER") {
|
|
5142
|
-
this.advance();
|
|
5143
|
-
traits.push(this.current().value);
|
|
5144
|
-
this.advance();
|
|
5145
|
-
if (this.check("LPAREN")) {
|
|
5146
|
-
this.skipParens();
|
|
5147
|
-
}
|
|
5148
|
-
}
|
|
6845
|
+
const traits = this.parseInlineTraitNamesBeforeBlock();
|
|
5149
6846
|
this.expect("LBRACE");
|
|
5150
6847
|
this.skipNewlines();
|
|
5151
6848
|
const properties = {};
|
|
@@ -5187,6 +6884,9 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5187
6884
|
body
|
|
5188
6885
|
});
|
|
5189
6886
|
}
|
|
6887
|
+
} else if (this.isPropertyName() && this.peek(1)?.type === "LBRACE") {
|
|
6888
|
+
const key = this.parsePropertyKey();
|
|
6889
|
+
properties[key] = this.parseBlockTraitConfig();
|
|
5190
6890
|
} else if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
5191
6891
|
const key = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
5192
6892
|
this.expect("COLON");
|
|
@@ -5211,6 +6911,303 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5211
6911
|
eventHandlers: eventHandlers.length > 0 ? eventHandlers : void 0
|
|
5212
6912
|
};
|
|
5213
6913
|
}
|
|
6914
|
+
// ===========================================================================
|
|
6915
|
+
// SIMULATION CONTRACT BLOCK (v6.3)
|
|
6916
|
+
// ===========================================================================
|
|
6917
|
+
/**
|
|
6918
|
+
* Parse a `sim_contract { ... }` block.
|
|
6919
|
+
*
|
|
6920
|
+
* Syntax:
|
|
6921
|
+
* ```
|
|
6922
|
+
* sim_contract {
|
|
6923
|
+
* precondition "name" { expr }
|
|
6924
|
+
* precondition "name" "description" { expr }
|
|
6925
|
+
* invariant "name" { expr }
|
|
6926
|
+
* receipt { field: type, ... }
|
|
6927
|
+
* }
|
|
6928
|
+
* ```
|
|
6929
|
+
*/
|
|
6930
|
+
parseContractBlock() {
|
|
6931
|
+
const startLoc = this.currentLocation();
|
|
6932
|
+
this.pushContext("sim_contract");
|
|
6933
|
+
this.advance();
|
|
6934
|
+
this.expect("LBRACE");
|
|
6935
|
+
this.skipNewlines();
|
|
6936
|
+
const preconditions = [];
|
|
6937
|
+
const invariants = [];
|
|
6938
|
+
const receipt = {};
|
|
6939
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6940
|
+
this.skipNewlines();
|
|
6941
|
+
if (this.check("RBRACE")) break;
|
|
6942
|
+
const tokenLower = this.current().value.toLowerCase();
|
|
6943
|
+
if ((tokenLower === "precondition" || tokenLower === "invariant") && this.check("IDENTIFIER")) {
|
|
6944
|
+
const clauseKind = tokenLower;
|
|
6945
|
+
this.advance();
|
|
6946
|
+
let clauseName = "unnamed";
|
|
6947
|
+
if (this.check("STRING")) {
|
|
6948
|
+
clauseName = this.expectString();
|
|
6949
|
+
} else if (this.check("IDENTIFIER")) {
|
|
6950
|
+
clauseName = this.expectIdentifier();
|
|
6951
|
+
}
|
|
6952
|
+
let description;
|
|
6953
|
+
if (this.check("STRING")) {
|
|
6954
|
+
description = this.expectString();
|
|
6955
|
+
}
|
|
6956
|
+
let expr = "";
|
|
6957
|
+
if (this.check("LBRACE")) {
|
|
6958
|
+
this.advance();
|
|
6959
|
+
const parts = [];
|
|
6960
|
+
let depth = 1;
|
|
6961
|
+
while (depth > 0 && !this.isAtEnd()) {
|
|
6962
|
+
if (this.check("LBRACE")) depth++;
|
|
6963
|
+
if (this.check("RBRACE")) {
|
|
6964
|
+
depth--;
|
|
6965
|
+
if (depth === 0) break;
|
|
6966
|
+
}
|
|
6967
|
+
parts.push(this.current().value);
|
|
6968
|
+
this.advance();
|
|
6969
|
+
}
|
|
6970
|
+
this.expect("RBRACE");
|
|
6971
|
+
expr = parts.join(" ").trim();
|
|
6972
|
+
}
|
|
6973
|
+
const clause = { name: clauseName, expr };
|
|
6974
|
+
if (description !== void 0) clause.description = description;
|
|
6975
|
+
if (clauseKind === "precondition") {
|
|
6976
|
+
preconditions.push(clause);
|
|
6977
|
+
} else {
|
|
6978
|
+
invariants.push(clause);
|
|
6979
|
+
}
|
|
6980
|
+
} else if (tokenLower === "receipt" && this.check("IDENTIFIER")) {
|
|
6981
|
+
this.advance();
|
|
6982
|
+
if (this.check("LBRACE")) {
|
|
6983
|
+
this.advance();
|
|
6984
|
+
this.skipNewlines();
|
|
6985
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
6986
|
+
this.skipNewlines();
|
|
6987
|
+
if (this.check("RBRACE")) break;
|
|
6988
|
+
let fieldName = "";
|
|
6989
|
+
if (this.check("IDENTIFIER")) {
|
|
6990
|
+
fieldName = this.expectIdentifier();
|
|
6991
|
+
} else if (this.check("STRING")) {
|
|
6992
|
+
fieldName = this.expectString();
|
|
6993
|
+
} else {
|
|
6994
|
+
this.advance();
|
|
6995
|
+
continue;
|
|
6996
|
+
}
|
|
6997
|
+
let typeName = "unknown";
|
|
6998
|
+
if (this.check("COLON")) {
|
|
6999
|
+
this.advance();
|
|
7000
|
+
if (this.check("IDENTIFIER")) {
|
|
7001
|
+
typeName = this.expectIdentifier();
|
|
7002
|
+
} else if (this.check("STRING")) {
|
|
7003
|
+
typeName = this.expectString();
|
|
7004
|
+
}
|
|
7005
|
+
}
|
|
7006
|
+
if (fieldName) receipt[fieldName] = typeName;
|
|
7007
|
+
if (this.check("COMMA")) this.advance();
|
|
7008
|
+
this.skipNewlines();
|
|
7009
|
+
}
|
|
7010
|
+
this.expect("RBRACE");
|
|
7011
|
+
}
|
|
7012
|
+
} else {
|
|
7013
|
+
this.advance();
|
|
7014
|
+
}
|
|
7015
|
+
this.skipNewlines();
|
|
7016
|
+
}
|
|
7017
|
+
this.expect("RBRACE");
|
|
7018
|
+
this.popContext();
|
|
7019
|
+
return {
|
|
7020
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7021
|
+
type: "contract",
|
|
7022
|
+
preconditions,
|
|
7023
|
+
invariants,
|
|
7024
|
+
receipt
|
|
7025
|
+
};
|
|
7026
|
+
}
|
|
7027
|
+
// ── Pub/sub messaging primitives (v6.4) ───────────────────────────────────
|
|
7028
|
+
/**
|
|
7029
|
+
* Parse policy_pack Name { ... } as a first-class regulated-AI governance
|
|
7030
|
+
* primitive. Validation lives in policy/PolicyPack.ts so compilers and deploy
|
|
7031
|
+
* gates consume the same schema the parser emits.
|
|
7032
|
+
*/
|
|
7033
|
+
parsePolicyPackBlock() {
|
|
7034
|
+
const startLoc = this.currentLocation();
|
|
7035
|
+
this.pushContext("policy-pack");
|
|
7036
|
+
this.advance();
|
|
7037
|
+
const name = this.check("STRING") ? this.expectString() : this.expectIdentifier();
|
|
7038
|
+
this.expect("LBRACE");
|
|
7039
|
+
this.skipNewlines();
|
|
7040
|
+
const properties = {};
|
|
7041
|
+
let version = "1.0.0";
|
|
7042
|
+
let frameworkId = "";
|
|
7043
|
+
let requiredTests = [];
|
|
7044
|
+
let requiredCompileTargets = [];
|
|
7045
|
+
let auditRetention = {};
|
|
7046
|
+
let monitoringCadence = {};
|
|
7047
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7048
|
+
this.skipNewlines();
|
|
7049
|
+
if (this.check("RBRACE")) break;
|
|
7050
|
+
const key = this.expectIdentifier();
|
|
7051
|
+
if ((key === "audit_retention" || key === "auditRetention") && this.check("LBRACE")) {
|
|
7052
|
+
auditRetention = this.parseBlockTraitConfig();
|
|
7053
|
+
} else if ((key === "monitoring" || key === "monitoring_cadence" || key === "monitoringCadence") && this.check("LBRACE")) {
|
|
7054
|
+
monitoringCadence = this.parseBlockTraitConfig();
|
|
7055
|
+
} else {
|
|
7056
|
+
this.expect("COLON");
|
|
7057
|
+
const value = this.parseValue();
|
|
7058
|
+
if (key === "version") version = typeof value === "string" ? value : String(value);
|
|
7059
|
+
else if (key === "framework_id" || key === "frameworkId") {
|
|
7060
|
+
frameworkId = typeof value === "string" ? value : String(value);
|
|
7061
|
+
} else if (key === "required_tests" || key === "requiredTests") {
|
|
7062
|
+
requiredTests = Array.isArray(value) ? value : [value];
|
|
7063
|
+
} else if (key === "required_compile_targets" || key === "requiredCompileTargets") {
|
|
7064
|
+
requiredCompileTargets = (Array.isArray(value) ? value : [value]).map(
|
|
7065
|
+
(target) => String(target)
|
|
7066
|
+
);
|
|
7067
|
+
} else if (key === "audit_retention" || key === "auditRetention") {
|
|
7068
|
+
auditRetention = this.asRecord(value);
|
|
7069
|
+
} else if (key === "monitoring" || key === "monitoring_cadence" || key === "monitoringCadence") {
|
|
7070
|
+
monitoringCadence = this.asRecord(value);
|
|
7071
|
+
} else {
|
|
7072
|
+
properties[key] = value;
|
|
7073
|
+
}
|
|
7074
|
+
}
|
|
7075
|
+
if (this.check("COMMA")) this.advance();
|
|
7076
|
+
this.skipNewlines();
|
|
7077
|
+
}
|
|
7078
|
+
this.expect("RBRACE");
|
|
7079
|
+
this.popContext();
|
|
7080
|
+
return {
|
|
7081
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7082
|
+
type: "PolicyPack",
|
|
7083
|
+
name,
|
|
7084
|
+
version,
|
|
7085
|
+
frameworkId,
|
|
7086
|
+
requiredTests,
|
|
7087
|
+
requiredCompileTargets,
|
|
7088
|
+
auditRetention,
|
|
7089
|
+
monitoringCadence,
|
|
7090
|
+
properties
|
|
7091
|
+
};
|
|
7092
|
+
}
|
|
7093
|
+
asRecord(value) {
|
|
7094
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || "__bind" in value) {
|
|
7095
|
+
return {};
|
|
7096
|
+
}
|
|
7097
|
+
return value;
|
|
7098
|
+
}
|
|
7099
|
+
/** Parse `topic Name { type: "T" broadcast: true }` */
|
|
7100
|
+
parseTopicBlock() {
|
|
7101
|
+
const startLoc = this.currentLocation();
|
|
7102
|
+
this.advance();
|
|
7103
|
+
const name = this.check("IDENTIFIER") ? this.expectIdentifier() : "unnamed";
|
|
7104
|
+
const metadata = {};
|
|
7105
|
+
let dataType;
|
|
7106
|
+
let broadcast;
|
|
7107
|
+
if (this.check("LBRACE")) {
|
|
7108
|
+
this.advance();
|
|
7109
|
+
this.skipNewlines();
|
|
7110
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7111
|
+
this.skipNewlines();
|
|
7112
|
+
if (this.check("RBRACE") || this.check("NEWLINE")) {
|
|
7113
|
+
if (!this.check("RBRACE")) this.advance();
|
|
7114
|
+
continue;
|
|
7115
|
+
}
|
|
7116
|
+
const key = this.current().value;
|
|
7117
|
+
this.advance();
|
|
7118
|
+
if (this.check("COLON")) this.advance();
|
|
7119
|
+
if (key === "type" || key === "dataType") {
|
|
7120
|
+
dataType = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : (this.advance(), void 0);
|
|
7121
|
+
} else if (key === "broadcast") {
|
|
7122
|
+
broadcast = this.current().value === "true";
|
|
7123
|
+
this.advance();
|
|
7124
|
+
} else if (this.check("LBRACE") || this.check("STRING") || this.check("NUMBER") || this.check("IDENTIFIER") || this.check("LBRACKET")) {
|
|
7125
|
+
metadata[key] = this.parseValue();
|
|
7126
|
+
}
|
|
7127
|
+
if (this.check("COMMA")) this.advance();
|
|
7128
|
+
this.skipNewlines();
|
|
7129
|
+
}
|
|
7130
|
+
this.expect("RBRACE");
|
|
7131
|
+
}
|
|
7132
|
+
const topic = {
|
|
7133
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7134
|
+
type: "Topic",
|
|
7135
|
+
name
|
|
7136
|
+
};
|
|
7137
|
+
if (dataType !== void 0) topic.dataType = dataType;
|
|
7138
|
+
if (broadcast !== void 0) topic.broadcast = broadcast;
|
|
7139
|
+
if (Object.keys(metadata).length > 0) topic.metadata = metadata;
|
|
7140
|
+
return topic;
|
|
7141
|
+
}
|
|
7142
|
+
/** Parse `channel Name { from: A to: B capacity: N }` */
|
|
7143
|
+
parseChannelBlock() {
|
|
7144
|
+
const startLoc = this.currentLocation();
|
|
7145
|
+
this.advance();
|
|
7146
|
+
const name = this.check("IDENTIFIER") ? this.expectIdentifier() : "unnamed";
|
|
7147
|
+
const metadata = {};
|
|
7148
|
+
let from;
|
|
7149
|
+
let to;
|
|
7150
|
+
let capacity;
|
|
7151
|
+
if (this.check("LBRACE")) {
|
|
7152
|
+
this.advance();
|
|
7153
|
+
this.skipNewlines();
|
|
7154
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7155
|
+
this.skipNewlines();
|
|
7156
|
+
if (this.check("RBRACE") || this.check("NEWLINE")) {
|
|
7157
|
+
if (!this.check("RBRACE")) this.advance();
|
|
7158
|
+
continue;
|
|
7159
|
+
}
|
|
7160
|
+
const key = this.current().value;
|
|
7161
|
+
this.advance();
|
|
7162
|
+
if (this.check("COLON")) this.advance();
|
|
7163
|
+
if (key === "from") {
|
|
7164
|
+
from = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : void 0;
|
|
7165
|
+
} else if (key === "to") {
|
|
7166
|
+
to = this.check("STRING") ? this.expectString() : this.check("IDENTIFIER") ? this.expectIdentifier() : void 0;
|
|
7167
|
+
} else if (key === "capacity") {
|
|
7168
|
+
capacity = this.check("NUMBER") ? Number(this.current().value) : void 0;
|
|
7169
|
+
if (capacity !== void 0) this.advance();
|
|
7170
|
+
} else if (this.check("LBRACE") || this.check("STRING") || this.check("NUMBER") || this.check("IDENTIFIER") || this.check("LBRACKET")) {
|
|
7171
|
+
metadata[key] = this.parseValue();
|
|
7172
|
+
}
|
|
7173
|
+
if (this.check("COMMA")) this.advance();
|
|
7174
|
+
this.skipNewlines();
|
|
7175
|
+
}
|
|
7176
|
+
this.expect("RBRACE");
|
|
7177
|
+
}
|
|
7178
|
+
const ch = {
|
|
7179
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7180
|
+
type: "Channel",
|
|
7181
|
+
name
|
|
7182
|
+
};
|
|
7183
|
+
if (from !== void 0) ch.from = from;
|
|
7184
|
+
if (to !== void 0) ch.to = to;
|
|
7185
|
+
if (capacity !== void 0) ch.capacity = capacity;
|
|
7186
|
+
if (Object.keys(metadata).length > 0) ch.metadata = metadata;
|
|
7187
|
+
return ch;
|
|
7188
|
+
}
|
|
7189
|
+
/** Parse `connect Identifier to Identifier [as "edgeType"]` */
|
|
7190
|
+
parseConnectionStmt() {
|
|
7191
|
+
const startLoc = this.currentLocation();
|
|
7192
|
+
this.advance();
|
|
7193
|
+
const from = this.check("IDENTIFIER") ? this.expectIdentifier() : "";
|
|
7194
|
+
if (this.check("IDENTIFIER") && this.current().value === "to") this.advance();
|
|
7195
|
+
const to = this.check("IDENTIFIER") ? this.expectIdentifier() : "";
|
|
7196
|
+
let edgeType;
|
|
7197
|
+
if (this.check("IDENTIFIER") && this.current().value === "as") {
|
|
7198
|
+
this.advance();
|
|
7199
|
+
if (this.check("STRING")) edgeType = this.expectString();
|
|
7200
|
+
else if (this.check("IDENTIFIER")) edgeType = this.expectIdentifier();
|
|
7201
|
+
}
|
|
7202
|
+
const conn = {
|
|
7203
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7204
|
+
type: "Connection",
|
|
7205
|
+
from,
|
|
7206
|
+
to
|
|
7207
|
+
};
|
|
7208
|
+
if (edgeType !== void 0) conn.edgeType = edgeType;
|
|
7209
|
+
return conn;
|
|
7210
|
+
}
|
|
5214
7211
|
/**
|
|
5215
7212
|
* Unified parser for all domain-specific blocks.
|
|
5216
7213
|
* Pattern: KEYWORD NAME @trait1 @trait2 { properties... }
|
|
@@ -5257,27 +7254,27 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5257
7254
|
if (domain === "pipeline" && keyword === "pipeline") {
|
|
5258
7255
|
return this.parsePipelineDomainBlock(name, traits);
|
|
5259
7256
|
}
|
|
7257
|
+
if (token.type === "PCG_GRAPH") {
|
|
7258
|
+
return this.parsePCGGraphDomainBlock(startLoc, name, traits, keyword, domain);
|
|
7259
|
+
}
|
|
5260
7260
|
this.expect("LBRACE");
|
|
5261
7261
|
this.skipNewlines();
|
|
5262
7262
|
const properties = {};
|
|
5263
7263
|
const children = [];
|
|
5264
7264
|
const eventHandlers = [];
|
|
5265
7265
|
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
5266
|
-
this.
|
|
7266
|
+
this.skipBlockMemberSeparators();
|
|
5267
7267
|
if (this.check("RBRACE")) break;
|
|
5268
|
-
if (this.check("OBJECT")
|
|
7268
|
+
if (this.check("OBJECT")) {
|
|
5269
7269
|
children.push(this.parseObject());
|
|
7270
|
+
} else if (this.check("IDENTIFIER") && this.isPrimitiveShape(this.current().value) && this.peek(1).type !== "COLON") {
|
|
7271
|
+
children.push(this.parsePrimitiveObject());
|
|
5270
7272
|
} else if (this.check("IDENTIFIER") && this.current().value.startsWith("on")) {
|
|
5271
7273
|
const evtName = this.current().value;
|
|
5272
7274
|
if (this.tokens[this.pos + 1]?.type === "LPAREN" || this.tokens[this.pos + 1]?.type === "LBRACE") {
|
|
5273
7275
|
this.advance();
|
|
5274
7276
|
if (this.check("LPAREN")) {
|
|
5275
|
-
this.
|
|
5276
|
-
while (!this.check("RPAREN") && !this.isAtEnd()) {
|
|
5277
|
-
this.expectIdentifier();
|
|
5278
|
-
if (this.check("COMMA")) this.advance();
|
|
5279
|
-
}
|
|
5280
|
-
this.expect("RPAREN");
|
|
7277
|
+
this.skipParens();
|
|
5281
7278
|
}
|
|
5282
7279
|
if (this.check("LBRACE")) {
|
|
5283
7280
|
this.skipBlock();
|
|
@@ -5289,13 +7286,51 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5289
7286
|
body: []
|
|
5290
7287
|
});
|
|
5291
7288
|
} else {
|
|
5292
|
-
const key = this.
|
|
7289
|
+
const key = this.parsePropertyKey();
|
|
5293
7290
|
this.expect("COLON");
|
|
5294
7291
|
const value = this.parseValue();
|
|
5295
7292
|
properties[key] = value;
|
|
5296
7293
|
}
|
|
7294
|
+
} else if (this.check("AT")) {
|
|
7295
|
+
this.advance();
|
|
7296
|
+
const traitName = this.parseTraitName();
|
|
7297
|
+
if (traitName) traits.push(traitName);
|
|
7298
|
+
if (this.check("LPAREN") || this.check("LBRACE") || this.check("COLON")) {
|
|
7299
|
+
properties[`@${traitName}`] = this.parseOptionalTraitConfig();
|
|
7300
|
+
}
|
|
7301
|
+
} else if (this.isNamedOrTraitedPropertyBlockStart()) {
|
|
7302
|
+
const { key, value } = this.parseNamedOrTraitedPropertyBlock();
|
|
7303
|
+
properties[key] = value;
|
|
7304
|
+
} else if (this.isPropertyName() && this.peek(1).type === "LBRACE") {
|
|
7305
|
+
const key = this.parsePropertyKey();
|
|
7306
|
+
properties[key] = this.parseBlockTraitConfig();
|
|
7307
|
+
} else if (this.isPropertyName() && (this.peek(1).type === "STRING" || this.peek(1).type === "IDENTIFIER") && this.peek(2).type === "LBRACE") {
|
|
7308
|
+
const key = this.parsePropertyKey();
|
|
7309
|
+
const blockName = this.advance().value;
|
|
7310
|
+
properties[key] = {
|
|
7311
|
+
name: blockName,
|
|
7312
|
+
...this.parseBlockTraitConfig()
|
|
7313
|
+
};
|
|
7314
|
+
} else if (this.isPropertyName() && (this.peek(1).type === "ARROW" || this.peek(1).type === "MINUS" && this.peek(2).type === "GREATER")) {
|
|
7315
|
+
const from = this.parsePropertyKey();
|
|
7316
|
+
if (this.check("ARROW")) {
|
|
7317
|
+
this.advance();
|
|
7318
|
+
} else {
|
|
7319
|
+
this.advance();
|
|
7320
|
+
this.advance();
|
|
7321
|
+
}
|
|
7322
|
+
if (domain === "input") {
|
|
7323
|
+
properties[from] = this.parseValue();
|
|
7324
|
+
if (this.check("COMMA")) this.advance();
|
|
7325
|
+
this.skipNewlines();
|
|
7326
|
+
continue;
|
|
7327
|
+
}
|
|
7328
|
+
const to = this.isBarewordPathToken() ? this.parseBarewordPathValue() : "";
|
|
7329
|
+
const existing = properties.connections;
|
|
7330
|
+
const connection = { from, to };
|
|
7331
|
+
properties.connections = Array.isArray(existing) ? [...existing, connection] : [connection];
|
|
5297
7332
|
} else {
|
|
5298
|
-
const key = this.
|
|
7333
|
+
const key = this.parsePropertyKey();
|
|
5299
7334
|
this.expect("COLON");
|
|
5300
7335
|
const value = this.parseValue();
|
|
5301
7336
|
properties[key] = value;
|
|
@@ -5317,6 +7352,90 @@ var _HoloCompositionParser = class _HoloCompositionParser {
|
|
|
5317
7352
|
eventHandlers: eventHandlers.length > 0 ? eventHandlers : void 0
|
|
5318
7353
|
};
|
|
5319
7354
|
}
|
|
7355
|
+
parsePCGGraphDomainBlock(startLoc, name, traits, keyword, domain) {
|
|
7356
|
+
this.expect("LBRACE");
|
|
7357
|
+
this.skipNewlines();
|
|
7358
|
+
const nodes = [];
|
|
7359
|
+
const properties = {
|
|
7360
|
+
nodes
|
|
7361
|
+
};
|
|
7362
|
+
while (!this.check("RBRACE") && !this.isAtEnd()) {
|
|
7363
|
+
this.skipNewlines();
|
|
7364
|
+
if (this.check("RBRACE")) break;
|
|
7365
|
+
const token = this.current();
|
|
7366
|
+
const next = this.peek(1);
|
|
7367
|
+
if (next?.type === "COLON" && (token.type === "IDENTIFIER" || token.type === "PCG_GRAPH")) {
|
|
7368
|
+
const key = token.value;
|
|
7369
|
+
this.advance();
|
|
7370
|
+
this.expect("COLON");
|
|
7371
|
+
properties[key] = this.parseValue();
|
|
7372
|
+
} else {
|
|
7373
|
+
const kind = token.value;
|
|
7374
|
+
this.advance();
|
|
7375
|
+
const nodeProperties = {};
|
|
7376
|
+
if (this.check("LPAREN")) {
|
|
7377
|
+
this.parsePCGNodeArgs(kind, nodeProperties);
|
|
7378
|
+
}
|
|
7379
|
+
nodes.push({
|
|
7380
|
+
kind,
|
|
7381
|
+
properties: nodeProperties
|
|
7382
|
+
});
|
|
7383
|
+
}
|
|
7384
|
+
this.skipNewlines();
|
|
7385
|
+
if (this.check("ARROW")) {
|
|
7386
|
+
this.advance();
|
|
7387
|
+
} else if (this.check("MINUS") && this.peek(1).type === "GREATER") {
|
|
7388
|
+
this.advance();
|
|
7389
|
+
this.advance();
|
|
7390
|
+
}
|
|
7391
|
+
if (this.check("COMMA")) this.advance();
|
|
7392
|
+
this.skipNewlines();
|
|
7393
|
+
}
|
|
7394
|
+
this.expect("RBRACE");
|
|
7395
|
+
this.popContext();
|
|
7396
|
+
return {
|
|
7397
|
+
loc: { start: startLoc, end: this.currentLocation() },
|
|
7398
|
+
type: "DomainBlock",
|
|
7399
|
+
domain,
|
|
7400
|
+
keyword,
|
|
7401
|
+
name,
|
|
7402
|
+
traits,
|
|
7403
|
+
properties
|
|
7404
|
+
};
|
|
7405
|
+
}
|
|
7406
|
+
parsePCGNodeArgs(kind, properties) {
|
|
7407
|
+
this.expect("LPAREN");
|
|
7408
|
+
const args = [];
|
|
7409
|
+
while (!this.check("RPAREN") && !this.isAtEnd()) {
|
|
7410
|
+
if (this.check("COMMA")) {
|
|
7411
|
+
this.advance();
|
|
7412
|
+
continue;
|
|
7413
|
+
}
|
|
7414
|
+
if (this.check("IDENTIFIER") && this.peek(1).type === "COLON") {
|
|
7415
|
+
const key = this.expectIdentifier();
|
|
7416
|
+
this.expect("COLON");
|
|
7417
|
+
properties[key] = this.parseValue();
|
|
7418
|
+
} else {
|
|
7419
|
+
args.push(this.parsePCGArgumentValue());
|
|
7420
|
+
}
|
|
7421
|
+
if (this.check("COMMA")) this.advance();
|
|
7422
|
+
}
|
|
7423
|
+
this.expect("RPAREN");
|
|
7424
|
+
if (kind === "scatter") {
|
|
7425
|
+
if (args[0] !== void 0) properties["source_mesh"] = args[0];
|
|
7426
|
+
if (args[1] !== void 0) properties["count"] = args[1];
|
|
7427
|
+
} else if (args.length > 0) {
|
|
7428
|
+
properties["args"] = args;
|
|
7429
|
+
}
|
|
7430
|
+
}
|
|
7431
|
+
parsePCGArgumentValue() {
|
|
7432
|
+
if (this.check("STRING") || this.check("NUMBER") || this.check("BOOLEAN") || this.check("NULL") || this.check("LBRACKET")) {
|
|
7433
|
+
return this.parseValue();
|
|
7434
|
+
}
|
|
7435
|
+
const value = this.current().value;
|
|
7436
|
+
this.advance();
|
|
7437
|
+
return value;
|
|
7438
|
+
}
|
|
5320
7439
|
/**
|
|
5321
7440
|
* Parse a pipeline domain block by extracting the raw body text
|
|
5322
7441
|
* and delegating to PipelineParser for structured AST.
|
|
@@ -5455,6 +7574,10 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5455
7574
|
"SIMULATION",
|
|
5456
7575
|
// Perception & simulation layer
|
|
5457
7576
|
"MATERIAL",
|
|
7577
|
+
"MATERIAL_GRAPH",
|
|
7578
|
+
"LIGHT_FIELD",
|
|
7579
|
+
"NAV_FIELD",
|
|
7580
|
+
"PHYSICS_CONTRACT",
|
|
5458
7581
|
"PBR_MATERIAL",
|
|
5459
7582
|
"UNLIT_MATERIAL",
|
|
5460
7583
|
"SHADER",
|
|
@@ -5465,6 +7588,7 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5465
7588
|
"PARTICLES",
|
|
5466
7589
|
"EMITTER",
|
|
5467
7590
|
"VFX",
|
|
7591
|
+
"PARTICLE_FIELD",
|
|
5468
7592
|
"POST_PROCESSING",
|
|
5469
7593
|
"POST_FX",
|
|
5470
7594
|
"AUDIO_SOURCE",
|
|
@@ -5473,6 +7597,7 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5473
7597
|
"WEATHER",
|
|
5474
7598
|
"ATMOSPHERE",
|
|
5475
7599
|
"PROCEDURAL",
|
|
7600
|
+
"PCG_GRAPH",
|
|
5476
7601
|
"SCATTER",
|
|
5477
7602
|
"LOD_BLOCK",
|
|
5478
7603
|
"RENDER",
|
|
@@ -5542,7 +7667,9 @@ _HoloCompositionParser.DOMAIN_TOKENS = /* @__PURE__ */ new Set([
|
|
|
5542
7667
|
"RETRY_BLOCK",
|
|
5543
7668
|
"TIMEOUT_BLOCK",
|
|
5544
7669
|
"FALLBACK_BLOCK",
|
|
5545
|
-
"BULKHEAD_BLOCK"
|
|
7670
|
+
"BULKHEAD_BLOCK",
|
|
7671
|
+
// MMO/AAA game constructs (v6.2) — real_estate only; others handled by dedicated parsers
|
|
7672
|
+
"REAL_ESTATE"
|
|
5546
7673
|
]);
|
|
5547
7674
|
/** Token → domain type mapping */
|
|
5548
7675
|
_HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
@@ -5584,6 +7711,10 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5584
7711
|
SIMULATION: "simulation",
|
|
5585
7712
|
// Perception & simulation layer
|
|
5586
7713
|
MATERIAL: "material",
|
|
7714
|
+
MATERIAL_GRAPH: "material_graph",
|
|
7715
|
+
LIGHT_FIELD: "light_field",
|
|
7716
|
+
NAV_FIELD: "nav_field",
|
|
7717
|
+
PHYSICS_CONTRACT: "physics_contract",
|
|
5587
7718
|
PBR_MATERIAL: "material",
|
|
5588
7719
|
UNLIT_MATERIAL: "material",
|
|
5589
7720
|
SHADER: "material",
|
|
@@ -5594,6 +7725,7 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5594
7725
|
PARTICLES: "vfx",
|
|
5595
7726
|
EMITTER: "vfx",
|
|
5596
7727
|
VFX: "vfx",
|
|
7728
|
+
PARTICLE_FIELD: "particle_field",
|
|
5597
7729
|
POST_PROCESSING: "postfx",
|
|
5598
7730
|
POST_FX: "postfx",
|
|
5599
7731
|
AUDIO_SOURCE: "audio",
|
|
@@ -5602,6 +7734,7 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5602
7734
|
WEATHER: "weather",
|
|
5603
7735
|
ATMOSPHERE: "weather",
|
|
5604
7736
|
PROCEDURAL: "procedural",
|
|
7737
|
+
PCG_GRAPH: "procedural",
|
|
5605
7738
|
SCATTER: "procedural",
|
|
5606
7739
|
LOD_BLOCK: "rendering",
|
|
5607
7740
|
RENDER: "rendering",
|
|
@@ -5671,7 +7804,9 @@ _HoloCompositionParser.TOKEN_DOMAIN_MAP = {
|
|
|
5671
7804
|
RETRY_BLOCK: "resilience",
|
|
5672
7805
|
TIMEOUT_BLOCK: "resilience",
|
|
5673
7806
|
FALLBACK_BLOCK: "resilience",
|
|
5674
|
-
BULKHEAD_BLOCK: "resilience"
|
|
7807
|
+
BULKHEAD_BLOCK: "resilience",
|
|
7808
|
+
// MMO/AAA game constructs (v6.2)
|
|
7809
|
+
REAL_ESTATE: "custom"
|
|
5675
7810
|
};
|
|
5676
7811
|
var HoloCompositionParser = _HoloCompositionParser;
|
|
5677
7812
|
function parseHolo(source, options) {
|
|
@@ -5742,8 +7877,11 @@ function parseHoloPartial(source, options) {
|
|
|
5742
7877
|
}
|
|
5743
7878
|
|
|
5744
7879
|
exports.HoloCompositionParser = HoloCompositionParser;
|
|
7880
|
+
exports.KEYWORDS = KEYWORDS;
|
|
7881
|
+
exports.LIGHT_PRIMITIVES = LIGHT_PRIMITIVES;
|
|
7882
|
+
exports.PRIMITIVE_SHAPES = PRIMITIVE_SHAPES;
|
|
5745
7883
|
exports.parseHolo = parseHolo;
|
|
5746
7884
|
exports.parseHoloPartial = parseHoloPartial;
|
|
5747
7885
|
exports.parseHoloStrict = parseHoloStrict;
|
|
5748
|
-
//# sourceMappingURL=chunk-
|
|
5749
|
-
//# sourceMappingURL=chunk-
|
|
7886
|
+
//# sourceMappingURL=chunk-X75H75UY.cjs.map
|
|
7887
|
+
//# sourceMappingURL=chunk-X75H75UY.cjs.map
|