Compare commits

...

167 Commits

Author SHA1 Message Date
dependabot[bot]
0127237c37 build(deps): bump deps/fmt from e8259c5 to f575089
Bumps [deps/fmt](https://github.com/fmtlib/fmt) from `e8259c5` to `f575089`.
- [Release notes](https://github.com/fmtlib/fmt/releases)
- [Commits](e8259c5298...f575089243)

---
updated-dependencies:
- dependency-name: deps/fmt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-01 18:53:40 +00:00
Edo
0ff101d2b9 build(ci): update workflow (#160) 2023-12-01 15:49:41 +01:00
Edo
5ac36a1ad5 build(std): fix compilation (#159) 2023-12-01 15:48:33 +01:00
INeedGames
0c19a9ac12 fix(arc): assembler label collision (#158) 2023-12-01 00:00:40 +01:00
Xenxo Espasandín
7dafeb2ba7 fix(gsc): file expr paths (#156) 2023-10-24 22:14:44 +02:00
INeedGames
4262836191 feat(arc): add optional arg for filename in gscobj header (#153) 2023-10-02 23:42:14 +02:00
Xenxo Espasandín
2fcbdadc89 build(deps): track zlib master (#154) 2023-10-02 22:43:19 +02:00
Xenxo Espasandín
891d3e32a3 feat(gsc): string literal sizeof (#150) 2023-09-24 14:36:27 +02:00
Xenxo Espasandín
aa2a2d36d9 feat(arc): waittill undefined param (#149) 2023-09-24 14:36:08 +02:00
dependabot[bot]
4a75b5daf2 build(deps): bump deps/zlib from 04f42ce to 79a0e44 (#147)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 09:17:57 +02:00
dependabot[bot]
1885928a90 build(deps): bump deps/fmt from 8a4bec5 to e8259c5 (#148)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 09:17:43 +02:00
quaK
9e14e72fc9 feature(iw6): add all iw6 tokens (#146) 2023-08-16 09:44:17 +02:00
dependabot[bot]
e87d2de342 build(deps): bump deps/fmt from de4705f to 8a4bec5 (#142)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-11 08:55:19 +02:00
Edo
d67f277a74 build: update (#145) 2023-08-11 08:54:57 +02:00
Edo
32b74d95c5 feat(arc): update t6 hash list (#144) 2023-08-11 08:53:59 +02:00
Edo
654ffb2a55 fix(arc): address compiler regression (#141) 2023-07-28 08:22:33 +02:00
dependabot[bot]
91adc1a764 build(deps): bump deps/fmt from 686b335 to de4705f (#140)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 08:22:03 +02:00
Edo
db02851040 build(ci): turn off symbols to save space (#139) 2023-07-01 14:26:49 +02:00
Edo
280b4a4670 build(linux): arm64 - remove mold linker (#137) 2023-06-29 22:11:49 +02:00
Edo
a385156f8a refactor(asset): Use the proper STL function to 0-fill vector (#138) 2023-06-29 20:47:24 +02:00
Edo
ecb9574fc3 fix(h1): swap sayteam and sayall methods (#136) 2023-06-29 17:49:07 +02:00
Edo
5c5c4a32db build(ci): macos arm64 (#134)
Co-authored-by: xensik <xensik@pm.me>
2023-06-25 16:48:45 +02:00
Xenxo Espasandín
b7abc97c06 fix(build): branch name (#131) 2023-06-15 00:02:48 +02:00
Xenxo Espasandín
bc966e5a89 maint(build): github actions deploy (#130) 2023-06-14 23:12:51 +02:00
Xenxo Espasandín
1641e4c1e1 maint(build): new version system (#129) 2023-06-13 15:40:54 +02:00
Xenxo Espasandín
ec340df654 maint(build): use premake actions (#128) 2023-06-12 23:21:43 +02:00
quaK
73e6f83ad1 fix(s1): mislabeled method (#127) 2023-06-11 16:31:17 +02:00
dependabot[bot]
1b923784fc build(deps): bump deps/fmt from 2c991e1 to 686b335 (#126)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-01 23:08:31 +02:00
Xenxo Espasandín
c4dcd0165e fix(arc): assembler use after free (#125) 2023-05-19 13:02:07 +02:00
Xenxo Espasandín
908564a182 fix(arc): refactor regressions & func objects (#123) 2023-05-15 17:33:52 +02:00
Xenxo Espasandín
c1eb9b0c9b fix(t6): assemble hash & endswitch (#122) 2023-05-15 13:08:21 +02:00
Xenxo Espasandín
900fe95462 fix(arc): handle namespaces & hashes (#121) 2023-05-14 17:41:06 +02:00
xensik
40f9e5a4b2 build(ci): only prod for appveyor 2023-05-13 19:46:03 +02:00
Xenxo Espasandín
1b72759cf5 refactor(arc): treyarch games & minor fixes (#119) 2023-05-13 19:24:57 +02:00
dependabot[bot]
5b0867f218 build(deps): bump deps/fmt from e7f6888 to 2c991e1 (#115)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 22:34:44 +02:00
dependabot[bot]
a433dda772 build(deps): bump deps/fmt from 4e3f381 to e7f6888 (#114)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-08 22:29:45 +02:00
Xenxo Espasandín
f85be26ba9 refactor(gsc): simplify and clean ast (#99) 2023-04-05 17:09:21 +02:00
dependabot[bot]
1a127eb342 build(deps): bump deps/fmt from 9869971 to 4e3f381 (#98)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-04 22:00:16 +02:00
Edo
d3690ff006 fix(preprocessor): initialize tm structure (#96) 2023-04-02 21:24:56 +02:00
Edo
cb339d6ae3 feat(preprocessor): date & time macro (#92) 2023-03-29 15:45:50 +02:00
Edo
68ff757f96 maint(cpp): use correct macro detection for format feature (#87) 2023-03-06 12:34:13 +01:00
Xenxo Espasandín
e0dacaab85 refactor(global): headers & arc module (#86) 2023-03-02 16:41:32 +01:00
dependabot[bot]
d27653ad9c build(deps): bump deps/fmt from 3a69529 to 9869971 (#84)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 21:42:57 +01:00
Xenxo Espasandín
456258604e refactor(headers): cleanup (#83) 2023-02-28 16:32:53 +01:00
Edo
d62f9e2c8a maint(api): add iw6 & s1 (#82) 2023-02-28 13:02:29 +01:00
Edo
89a6429913 feat(github): CI linux build (#81) 2023-02-27 23:14:27 +01:00
Xenxo Espasandín
fc1ddeb4e7 refactor(std): use format on windows (#80) 2023-02-27 20:09:31 +01:00
dependabot[bot]
b81f96d209 build(deps): bump deps/fmt from d646fd0 to 3a69529 (#77)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-24 22:24:19 +01:00
Xenxo Espasandín
e69ab1ae9f fix(api): relative paths (#78) 2023-02-24 20:05:21 +01:00
Xenxo Espasandín
a599f04ea7 new(api): include header (#76) 2023-02-24 17:45:56 +01:00
Xenxo Espasandín
164b125bf2 feature(gsc): instance & iw9 path (#73) 2023-02-19 17:57:25 +01:00
dependabot[bot]
8423d296ad build(deps): bump deps/fmt from e03753c to d646fd0 (#72)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-17 21:08:32 +01:00
Xenxo Espasandín
8e7170d058 feature(iw9): compiler builtins (#71) 2023-02-17 18:56:19 +01:00
Xenxo Espasandín
99fb7f24ba feature(preprocessor): function-like macros (#70) 2023-02-17 16:44:38 +01:00
Xenxo Espasandín
4f83e351d8 feature(parser): empty decl (#69) 2023-02-14 20:53:53 +01:00
Xenxo Espasandín
8ccd22131a fix(gsc): wait dump (#68) 2023-02-13 22:48:10 +01:00
dependabot[bot]
6ce07d7ff3 Bump deps/fmt from 655046d to e03753c (#66)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 21:54:05 +01:00
Xenxo Espasandín
576b613188 update(github): funding (#67) 2023-02-13 21:53:04 +01:00
Xenxo Espasandín
1c31089351 fix(gsc): cleanup (#65) 2023-02-12 17:21:58 +01:00
Xenxo Espasandín
f99a56542a fix(gsc): use vector for rawfile (#64) 2023-02-12 15:58:24 +01:00
Xenxo Espasandín
817c07dabf refactor(gsc): remove static allocations (#63) 2023-02-12 12:56:27 +01:00
Xenxo Espasandín
18d2b89358 fix(writer): reset buffer pointer (#62) 2023-02-11 23:52:40 +01:00
Xenxo Espasandín
a05cadf843 fix(compiler): reset scopes (#61) 2023-02-11 22:43:21 +01:00
dependabot[bot]
e108b537e0 Bump deps/fmt from 581c629 to 655046d (#59)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-11 13:26:01 +01:00
Xenxo Espasandín
ed35ad9c73 fix(iw5): console reference opcodes (#60) 2023-02-11 00:16:00 +01:00
dependabot[bot]
db0bf9af24 Bump deps/fmt from 05e3a92 to 581c629 (#58)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-10 12:46:51 +01:00
simon
ccdf404feb feature(iw7): builtins & tokens additions (#47) 2023-02-10 12:45:52 +01:00
Xenxo Espasandín
1307897a1f fix(s1): mislabeled function (#56) 2023-02-04 17:07:26 +01:00
quaK
b2d5efad0b feature(s1): method and function additions/fixes (#55) 2023-02-03 00:49:09 +01:00
Xenxo Espasandín
1dac9413ac feature(tool): rename command (#54) 2023-02-03 00:16:25 +01:00
m
742a7bf2e9 feature(s1): token changes and fixes (#53)
Co-authored-by: quaK <Joel.rautavuori@gmail.com>
2023-02-02 22:28:15 +01:00
m
1581bac571 feature(s1): token list update (#51) 2023-02-01 18:41:26 +01:00
Xenxo Espasandín
5693d3fcd0 feature(parser): deprecate constants & add asserts (#52) 2023-02-01 16:39:46 +01:00
Xenxo Espasandín
bf92756d2b feature(xlabs): export builtin maps (#50) 2023-01-31 14:53:49 +01:00
dependabot[bot]
f7f3a33d0e Bump deps/fmt from 70db193 to 05e3a92 (#49)
Bumps [deps/fmt](https://github.com/fmtlib/fmt) from `70db193` to `05e3a92`.
- [Release notes](https://github.com/fmtlib/fmt/releases)
- [Commits](70db193f09...05e3a9233a)

---
updated-dependencies:
- dependency-name: deps/fmt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 12:26:32 +01:00
xensik
5297742d6a fix deploy 2023-01-30 16:05:26 +01:00
dependabot[bot]
b844c7154b Bump deps/fmt from a337011 to 70db193 (#46)
Bumps [deps/fmt](https://github.com/fmtlib/fmt) from `a337011` to `70db193`.
- [Release notes](https://github.com/fmtlib/fmt/releases)
- [Commits](a33701196a...70db193f09)

---
updated-dependencies:
- dependency-name: deps/fmt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 13:49:35 +01:00
Xenxo Espasandín
8d9bb51039 feature(preprocessor): implement preprocessor & parse command (#48) 2023-01-30 13:48:27 +01:00
xensik
9059f3b04f slash paths and compound stmt 2023-01-24 12:53:39 +01:00
Xenxo Espasandín
b6f089d115 feature(refactor): big update (#41) 2023-01-23 23:31:08 +01:00
xensik
8643771f66 fix workflow 2023-01-16 19:11:45 +01:00
Edo
d755f7788b feature(github): add workflow (#40)
feature(workflow): add GitHub actions
2023-01-10 12:49:05 +01:00
xensik
105297aeaa feat(iw9): file hashes 2022-11-18 15:58:14 +01:00
xensik
0682199e84 feat(iw9): reverse hash generator 2022-11-18 15:57:13 +01:00
xensik
87a36d75a6 fix(iw9): foreach with index 2022-11-18 12:31:30 +01:00
xensik
492c5e7347 fix(iw9): default case & gen hash map 2022-11-17 16:17:22 +01:00
xensik
7357fef577 fix(iw9): new xhash opcodes & thread calls 2022-11-16 23:44:32 +01:00
xensik
bff02e6a75 update readme 2022-11-16 23:42:58 +01:00
xensik
ce69051956 iw9: impl hashing & missing opcodes 2022-11-16 18:23:30 +01:00
xensik
ad29da7bf3 iw9: disassembler & decompiler 2022-11-16 13:52:26 +01:00
xensik
17a0b789c4 iw9: opcode reversing 2022-11-14 16:06:50 +01:00
xensik
57ef733af4 feat(iw9): template 2022-11-14 11:06:41 +01:00
xensik
996aebef38 fix(t6): allow expr for default params 2022-11-10 19:32:57 +01:00
xensik
6986b49547 update h1 data 2022-11-10 19:26:11 +01:00
dependabot[bot]
92dd3eaec4 Bump deps/zlib from 21767c6 to 04f42ce (#35)
Bumps [deps/zlib](https://github.com/madler/zlib) from `21767c6` to `04f42ce`.
- [Release notes](https://github.com/madler/zlib/releases)
- [Commits](21767c654d...04f42ceca4)

---
updated-dependencies:
- dependency-name: deps/zlib
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-01 21:45:31 +01:00
Alex
14b9b4c4da add s1 built-ins and tokens (#37)
* add s1 builtins and tokens
2022-11-01 21:37:18 +01:00
xensik
c285027144 more IW6 tokens 2022-11-01 21:13:35 +01:00
xensik
3e4818c026 add missing flags & keywords 2022-10-21 20:49:27 +02:00
xensik
e9245fdb79 fix t6 export flags 2022-10-21 19:18:07 +02:00
xensik
bf169d78fd add treyarch const locals 2022-10-20 17:19:34 +02:00
xensik
04684d4324 add treyarch visibility flags 2022-10-15 16:20:48 +02:00
xensik
fe1889b243 add treyarch default parameters 2022-10-15 14:49:29 +02:00
xensik
d433fd7d7b add treyarch animtrees & fix nested switches 2022-10-14 19:05:35 +02:00
xensik
5093173549 fix compiler animtree bug 2022-10-04 22:35:56 +02:00
xensik
caef54f50d update h2 symbols 2022-10-04 22:35:24 +02:00
xensik
d59404b67c update iw6 symbols 2022-10-03 20:17:02 +02:00
xensik
92ad066565 fix T6 vectors 2022-10-03 12:46:34 +02:00
xensik
a42c4fa625 fix bugs for PS3 & Xbox 360 games 2022-09-30 19:40:20 +02:00
xensik
7c07251b8c added console string id count 2022-09-28 13:24:59 +02:00
xensik
fba2b92bda console support for iw6 & s1 (need fixes) 2022-09-22 12:57:11 +02:00
xensik
3c57eb9e2e update readme 2022-09-20 17:05:59 +02:00
xensik
2b870a9791 iw5 console symbols 2022-09-19 16:54:22 +02:00
xensik
49c770414a cleanup 2022-09-16 18:05:58 +02:00
xensik
79016a997e update resolvers 2022-09-13 16:22:14 +02:00
Diavolo
089895281f add some tokens to s1 2022-09-13 14:58:36 +02:00
xensik
a286f52fed t6 clean code 2022-09-09 22:56:57 +02:00
xensik
71818f0aa3 h1 methods fix & add builtins 2022-08-30 19:18:21 +02:00
xensik
d8a651a844 fix waitframe opcodes 2022-08-26 00:19:22 +02:00
xensik
f3c707a769 h1 all tokens and meth fixes 2022-08-25 23:48:08 +02:00
xensik
508e0b769f 10k more symbols 2022-08-25 18:30:58 +02:00
xensik
34f530b7ab more h1 symbols 2022-08-25 14:10:33 +02:00
xensik
080a87ba6e h1 func list fixes 2022-08-24 22:13:44 +02:00
xensik
53824824c0 more h1 symbols 2022-08-24 18:43:58 +02:00
xensik
5ab159d5f6 update h1 symbols 2022-08-24 18:15:31 +02:00
xensik
f1d75f329c update supported platforms 2022-08-23 15:59:29 +02:00
xensik
04d9e4848f update README 2022-08-23 14:10:07 +02:00
xensik
b04434a3cb iw5 console interface 2022-08-23 14:07:32 +02:00
xensik
3b53157c6d update build script 2022-08-23 13:49:51 +02:00
xensik
828bce678a rename module 2022-08-23 13:48:57 +02:00
xensik
475c0c323c update gen scripts 2022-08-23 13:47:49 +02:00
xensik
71a3e25be4 ps3 & xbox360 support for iw5 2022-08-22 12:03:44 +02:00
xensik
9f465644d4 fix warning 2022-08-22 12:02:59 +02:00
xensik
baf3f227f1 update iw5 data 2022-08-11 12:45:35 +02:00
xensik
ed6137a7d7 optimize compiler test jumps 2022-08-08 11:55:33 +02:00
xensik
c9986cc25a iw8 compiler encrypted strings support 2022-08-07 22:36:38 +02:00
xensik
7b1fdea6b7 rework endswitch disassemble 2022-08-06 15:53:03 +02:00
xensik
c0580ef14a change float and default case dissasemble 2022-08-06 14:12:29 +02:00
xensik
f197fb160d fix iw8 encrypted switch string 2022-08-05 20:05:40 +02:00
xensik
d8498adbc2 hotfix iw8 encrypted strings 2022-08-03 17:21:34 +02:00
xensik
ec4c23cc7b update iw8 id count 2022-08-03 17:18:04 +02:00
xensik
7d79fa1d91 fix decompiler empty switch cases 2022-07-29 11:43:07 +02:00
xensik
55021cb3ec cleanup + compiler tuple syntax 2022-07-22 20:33:10 +02:00
xensik
628749631b finish decompiler loop statements 2022-07-19 13:50:12 +02:00
xensik
18db7e071a kekw 2022-07-19 13:49:13 +02:00
xensik
15f76542b1 add h2 foreach tokens 2022-07-19 13:49:05 +02:00
xensik
73ed709fed fix h2 jump offsets 2022-07-19 13:48:08 +02:00
xensik
4fec6cda20 h1 files mapped 2022-07-18 18:13:57 +02:00
xensik
66b5c82840 more iw5 symbols 2022-07-17 20:13:28 +02:00
xensik
a16c70bd54 decompiler support for tuples 2022-07-17 13:49:31 +02:00
xensik
328961ee83 improve decompiler empty blocks & do-while bug 2022-07-16 20:58:59 +02:00
xensik
8e5cea1af7 update h2 symbols 2022-07-16 19:57:50 +02:00
xensik
4d6d9916bf update README 2022-07-16 19:55:31 +02:00
xensik
1a5e39fa0e more functions mapping 2022-07-16 10:44:31 +02:00
xensik
de254a1293 update h1 symbols 2022-07-16 09:21:11 +02:00
xensik
dcff855efb more iw5 sp symbols 2022-07-15 16:32:40 +02:00
xensik
bbce74f47a improve decompiler last stmt detection, loop locals 2022-07-15 16:31:05 +02:00
xensik
2c0a5dce18 update gitignore 2022-07-15 16:16:01 +02:00
xensik
89e34cd3a1 fix warnings 2022-07-14 21:23:29 +02:00
xensik
7eed6f45f8 fix decompiler bugs (inf loops, waittillmatch) 2022-07-14 21:17:59 +02:00
xensik
5eb63e3284 improve iw5 decompilation 2022-07-14 19:04:16 +02:00
xensik
05fc8a7421 prepare iw5 sp/so symbols 2022-07-14 15:31:58 +02:00
xensik
ec91109cc3 impl negate expression properly 2022-06-15 17:06:58 +02:00
xensik
0ec0b4d6f5 [IW] added negative variable expression 2022-06-08 12:05:16 +02:00
xensik
6a0419b5bf [T6] added negative variable expression 2022-06-06 15:32:01 +02:00
xensik
f53fb4fe47 t6: fix decompiler loop bug 2022-05-24 20:11:47 +02:00
dependabot[bot]
b6777295a1 Bump deps/zlib from 53ce271 to 21767c6
Bumps [deps/zlib](https://github.com/madler/zlib) from `53ce271` to `21767c6`.
- [Release notes](https://github.com/madler/zlib/releases)
- [Commits](53ce271311...21767c654d)

---
updated-dependencies:
- dependency-name: deps/zlib
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-24 16:48:57 +02:00
Xenxo Espasandín
b1ad170030 Create dependabot.yml 2022-05-24 16:40:24 +02:00
497 changed files with 785710 additions and 259174 deletions

3
.github/FUNDING.yml vendored
View File

@ -1,2 +1,3 @@
github: xensik
ko_fi: xensik
custom: https://www.paypal.me/xensik
custom: paypal.me/xensik

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "gitsubmodule"
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 10

184
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,184 @@
name: Build
on:
push:
branches:
- "**"
tags:
- '[0-9]+.[0-9]+.[0-9]+'
pull_request:
branches:
- "**"
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
env:
PREMAKE_VERSION: "5.0.0-beta2"
jobs:
build-windows:
name: Build Windows
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
config:
- release
arch:
- x86
- x64
include:
- arch: x86
platform: Win32
- arch: x64
platform: x64
steps:
- name: Check out files
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
lfs: false
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.3.1
- name: Add premake5 to PATH
uses: abel0b/setup-premake@v2.3
with:
version: ${{ env.PREMAKE_VERSION }}
- name: Generate project files
run: premake5 vs2022
- name: Set up problem matching
uses: ammaraskar/msvc-problem-matcher@master
- name: Build ${{matrix.arch}} ${{matrix.config}} binaries
run: msbuild /m /v:minimal /p:Configuration=${{matrix.config}} /p:Platform=${{matrix.platform}} build/gsc-tool.sln
- name: Upload ${{matrix.arch}} ${{matrix.config}} binaries
uses: actions/upload-artifact@v3.1.3
with:
name: windows-${{matrix.arch}}-${{matrix.config}}
path: |
build/bin/${{matrix.arch}}/${{matrix.config}}/gsc-tool.exe
build-macos:
name: Build macOS
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
config:
- release
arch:
- x64
- arm64
steps:
- name: Check out files
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
lfs: false
- name: Add premake5 to PATH
uses: abel0b/setup-premake@v2.3
with:
version: ${{ env.PREMAKE_VERSION }}
- name: Generate project files
run: premake5 gmake2
- name: Set up problem matching
uses: ammaraskar/gcc-problem-matcher@master
- name: Build ${{matrix.arch}} ${{matrix.config}} binaries
run: |
pushd build
make config=${{matrix.config}}_${{matrix.arch}} -j$(sysctl -n hw.logicalcpu)
- name: Upload ${{matrix.arch}} ${{matrix.config}} binaries
uses: actions/upload-artifact@v3.1.3
with:
name: macos-${{matrix.arch}}-${{matrix.config}}
path: |
build/bin/${{matrix.arch}}/${{matrix.config}}/gsc-tool
build-linux:
name: Build Linux
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
config:
- release
arch:
- x64
- arm64
steps:
- name: Check out files
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
lfs: false
- name: Install dependencies (arm64)
if: matrix.arch == 'arm64'
run: |
sudo apt-get update
sudo apt-get install crossbuild-essential-arm64 -y
- name: Add premake5 to PATH
uses: abel0b/setup-premake@v2.3
with:
version: ${{ env.PREMAKE_VERSION }}
- name: Generate project files
run: premake5 gmake2
- name: Set up problem matching
uses: ammaraskar/gcc-problem-matcher@master
- name: Build ${{matrix.arch}} ${{matrix.config}} binaries
run: |
pushd build
make config=${{matrix.config}}_${{matrix.arch}} -j$(nproc)
env:
CC: clang
CXX: clang++
- name: Upload ${{matrix.arch}} ${{matrix.config}} binaries
uses: actions/upload-artifact@v3.1.3
with:
name: linux-${{matrix.arch}}-${{matrix.config}}
path: |
build/bin/${{matrix.arch}}/${{matrix.config}}/gsc-tool
deploy:
name: Deploy Release
runs-on: ubuntu-latest
needs: [ build-windows, build-macos, build-linux ]
if: startsWith(github.ref, 'refs/tags/') && (github.event.base_ref == 'refs/heads/prod' || github.event.base_ref == 'refs/heads/dev')
steps:
- name: Check out files
uses: actions/checkout@v4
- name: Download Binaries
uses: actions/download-artifact@v3.0.2
with:
name: windows-x64-release
- name: Create Release
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
draft: true
files: |
gsc-tool.exe

22
.gitignore vendored
View File

@ -149,13 +149,15 @@ user*.bat
# VScode
.vscode/
data/iw5/
data/iw6/
data/iw7/
data/iw8/
data/h1/
data/h2/
data/s1/
data/s2/
data/s4/
data/t6/
# Output folders
renamed/
parsed/
compiled/
decompiled/
assembled/
disassembled/
data/*
# Version file
include/xsk/version.hpp

4
.gitmodules vendored
View File

@ -1,3 +1,7 @@
[submodule "deps/zlib"]
path = deps/zlib
url = https://github.com/madler/zlib
branch = master
[submodule "deps/fmt"]
path = deps/fmt
url = https://github.com/fmtlib/fmt

View File

@ -1,33 +1,41 @@
[![Build status](https://ci.appveyor.com/api/projects/status/defmhg4753c1ap1o?svg=true)](https://ci.appveyor.com/project/xensik/gsc-tool)
[![build](https://github.com/xensik/gsc-tool/workflows/Build/badge.svg)](https://github.com/xensik/gsc-tool/actions)
![license](https://img.shields.io/github/license/xensik/gsc-tool.svg)
[![GitHub issues](https://img.shields.io/github/issues/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/issues)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/releases)
[![issues](https://img.shields.io/github/issues/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/issues)
[![releases](https://img.shields.io/github/v/release/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/releases)
[![paypal](https://img.shields.io/badge/PayPal-support-blue.svg?logo=paypal)](https://www.paypal.me/xensik)
# GSC Tool
A utility to compile & decompile IW engine game scripts.
## Supported Games
- **IW5** *(Call of Duty: Modern Warfare 3)*
- **IW6** *(Call of Duty: Ghosts)*
- **IW7** *(Call of Duty: Infinite Warfare)*
- **IW8** *(Call of Duty: Modern Warfare (2019))*
- **S1** *(Call of Duty: Advanced Warfare)*
- **S2** *(Call of Duty: WWII)*
- **S4** *(Call of Duty: Vanguard)*
- **H1** *(Call of Duty: Modern Warfare Remastered)*
- **H2** *(Call of Duty: Modern Warfare 2 Campaign Remastered)*
- **T4** *(Call of Duty: World at War)* ***\*WIP\****
- **T5** *(Call of Duty: Black Ops)* ***\*WIP\****
- **T6** *(Call of Duty: Black Ops II)*
- **T7** *(Call of Duty: Black Ops III)* ***\*WIP\****
- **IW5** *(Call of Duty: Modern Warfare 3)* `PC` `PS3` `Xbox 360`
- **IW6** *(Call of Duty: Ghosts)* `PC` `PS3` `PS4` `Xbox 360` `Xbox One`
- **IW7** *(Call of Duty: Infinite Warfare)* `PC` `PS4` `Xbox One`
- **IW8** *(Call of Duty: Modern Warfare (2019) / Warzone)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **IW9** *(Call of Duty: Modern Warfare II (2022) / Warzone 2)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **S1** *(Call of Duty: Advanced Warfare)* `PC` `PS3` `PS4` `Xbox 360` `Xbox One`
- **S2** *(Call of Duty: WWII)* `PC` `PS4` `Xbox One`
- **S4** *(Call of Duty: Vanguard)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **H1** *(Call of Duty: Modern Warfare Remastered)* `PC` `PS4` `Xbox One`
- **H2** *(Call of Duty: Modern Warfare 2 Campaign Remastered)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **T6** *(Call of Duty: Black Ops II)* `PC` `PS3` `Xbox 360` `Wii U`
- **T7** *(Call of Duty: Black Ops III)* `PC` *(Decompiler)*
- **T8** *(Call of Duty: Black Ops 4)* ***\*WIP\****
- **T9** *(Call of Duty: Black Ops Cold War)* ***\*WIP\****
## Usage
``./gsc-tool.exe <mode> <game> <path>``
``./gsc-tool.exe <mode> <game> <system> <path>``
**modes**: `asm`, `disasm`, `comp`, `decomp`
**mode**: `asm`, `disasm`, `comp`, `decomp`, `parse`
- *note:* zonetool files (*.cgsc*, *.cgsc.stack*) use: `zasm`, `zdisasm`, `zcomp`, `zdecomp` modes
**games**: `iw5`, `iw6`, `iw7`, `iw8`, `s1`, `s2`, `s4`, `h1`, `h2`, `t6`
**game**: `iw5`, `iw6`, `iw7`, `iw8`, `iw9`, `s1`, `s2`, `s4`, `h1`, `h2`, `t6` `t7` `t8` `t9`
**paths**: `file`, `directory` (recursive process all files inside dir)
**system**: `pc`, `ps3`, `ps4`, `ps5`, `xb2` (*360*), `xb3` (*One*), `xb4` (*Series X|S*), `wiiu`
for zonetool files (*.cgsc*, *.cgsc.stack*) use: `zasm`, `zdisasm`, `zcomp`, `zdecomp` modes
**path**: `file` or `directory` (recursive process all files inside the directory)
Example: ``./gsc-tool.exe comp iw5 pc ./data/iw5/my_fancy_script.gsc``
| Mode |Description | Output |
|:---------|:--------------------------|:------------|
@ -35,17 +43,40 @@ for zonetool files (*.cgsc*, *.cgsc.stack*) use: `zasm`, `zdisasm`, `zcomp`, `zd
|`disasm` |dissasemble a `file.gscbin`|`file.gscasm`|
|`comp` |compile a `file.gsc` |`file.gscbin`|
|`decomp` |decompile a `file.gscbin` |`file.gsc` |
|`parse` |parse a `file.gsc` |`file.gsc` |
## File Format
If you need to extract scripts from fastfiles or game memory, use [Zonetool](https://github.com/ZoneTool/zonetool) or [Jekyll](https://github.com/EthanC/Jekyll).
- gsc-tool ``.gscbin`` format is a serialized ScriptFile struct: ***name***: null-term string, ***compressedLen***: 4 byte uint, ***len***: 4 byte uint, ***bytecodeLen***: 4 byte uint, ***buffer***: byte array[compressedLen], ***bytecode***: byte array[bytecodeLen].
- gsc-tool `.gscbin` format is a serialized ScriptFile struct: <br/>
***name***: null-terminated string <br/>
***compressedLen***: 4 byte uint <br/>
***len***: 4 byte uint <br/>
***bytecodeLen***: 4 byte uint <br/>
***buffer***: byte array[compressedLen] <br/>
***bytecode***: byte array[bytecodeLen] <br/>
- zonetool (IW5) format made of bytecode file ``.cgsc`` and decompressed stack buffer ``.cgsc.stack``.
note: for PS3 & Xbox 360 `.gscbin` files *(compressedLen, len, bytecodeLen)* are saved as little-endian!!
- treyarch (T6) format is a single buffer with gscobj data ``.gsc`` or ``.csc``.
- zonetool (IW5) format made of bytecode file `.cgsc` and decompressed stack buffer `.cgsc.stack`.
- treyarch (T6) format is a single buffer with gscobj data `.gsc` or `.csc`.
## Build
- install [*premake5*](https://premake.github.io) on your system PATH
- clone this repository
- update the submodules ``git submodule update --init --recursive``
- run prebuild script ``premake5 vs2022`` (windows) or ``premake5 gmake2`` (linux/macos)
## Contribute
If you like my work, consider sponsoring/donating! Would allow me to spend more time adding new features & fixing bugs.
BTC: bc1qky7x9kpjlt6nsvt7pckc3wwzk8rk9pgtnmw98u\
ETH: 0x6261BBE1a33F6Fec4b722DbCe2c28B4CC02c9C7B\
[![pypl](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white)](https://www.paypal.me/xensik) [![kofi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/xensik)
## Credits
This project is based on [*RektInator's* gsc-asm](https://github.com/ZoneTool/gsc-asm). Special thanks to **RektInator**, **JTAG** & **Dasfonia**.
This project is based on [*RektInator's* gsc-asm](https://github.com/ZoneTool/gsc-asm). Special thanks to **RektInator**, **JTAG** & **Dasfonia**.
## Disclaimer
This software has been created purely for the purposes of academic research. Project maintainers are not responsible or liable for misuse of the software. Use responsibly.

View File

@ -1,20 +0,0 @@
version: 1.0.{build}
skip_tags: true
image: Visual Studio 2022
configuration: Release
platform: x64
before_build:
- git submodule update --init --recursive
- ps: tools\windows\premake5.exe vs2022
build:
project: build/gsc-tool.sln
verbosity: minimal
test: false
artifacts:
- path: build/bin/release/gsc-tool.exe
deploy:
- provider: GitHub
auth_token:
secure: VTY5eMFd/IOYDIZQeMM0J0uYss+wmTwreE+Hi0lXAQABQ/4igmCvqCFZ5DsrWhY/
on:
branch: prod

1
deps/fmt vendored Submodule

@ -0,0 +1 @@
Subproject commit f5750892436a667fe622e5ecc8a02c15a5d9bc88

31
deps/fmt.lua vendored Normal file
View File

@ -0,0 +1,31 @@
fmt = { base = path.join(dependencies.base, "fmt") }
function fmt:include()
includedirs { path.join(fmt.base, "include") }
end
function fmt:link()
links { "fmt" }
self:include()
end
function fmt:project()
project "fmt"
kind "StaticLib"
language "C++"
self:include()
files
{
path.join(fmt.base, "include/fmt/*.h"),
path.join(fmt.base, "src/*.cc")
}
removefiles
{
path.join(fmt.base, "src/fmt.cc")
}
end
table.insert(dependencies, fmt)

2
deps/zlib vendored

@ -1 +1 @@
Subproject commit 53ce2713117ef2a8ed682d77b944df991c499252
Subproject commit 09155eaa2f9270dc4ed1fa13e2b4b2613e6e4851

4
deps/zlib.lua vendored
View File

@ -29,6 +29,10 @@ function zlib:project()
"_CRT_NONSTDC_NO_DEPRECATE",
"_CRT_SECURE_NO_DEPRECATE",
}
if os.istarget("darwin") then
defines "HAVE_UNISTD_H"
end
end
table.insert(dependencies, zlib)

View File

@ -1 +0,0 @@
# GSC Syntax

10
gen/arc/Makefile Normal file
View File

@ -0,0 +1,10 @@
generate: arc
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
arc: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp ../../include/xsk/arc/
mv parser.cpp ../../src/arc/

1341
gen/arc/parser.ypp Normal file

File diff suppressed because it is too large Load Diff

10
gen/gsc/Makefile Normal file
View File

@ -0,0 +1,10 @@
generate: gsc
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
gsc: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp ../../include/xsk/gsc/
mv parser.cpp ../../src/gsc/

1249
gen/gsc/parser.ypp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +0,0 @@
generate: H1
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
H1: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/h1/xsk/

View File

@ -1,862 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {H1}
%define api.namespace {xsk::gsc::h1}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::h1::lexer& lexer }
%parse-param { xsk::gsc::h1::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "h1.hpp"
namespace xsk::gsc::h1 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::h1::parser::symbol_type H1lex(xsk::gsc::h1::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token WAITFRAME "waitframe"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_waitframe::ptr> stmt_waitframe
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_waitframe { $$.as_waitframe = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_waitframe
: WAITFRAME SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
| WAITFRAME LPAREN RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::h1::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: H2
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
H2: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/h2/xsk/

View File

@ -1,862 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {H2}
%define api.namespace {xsk::gsc::h2}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::h2::lexer& lexer }
%parse-param { xsk::gsc::h2::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "h2.hpp"
namespace xsk::gsc::h2 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::h2::parser::symbol_type H2lex(xsk::gsc::h2::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token WAITFRAME "waitframe"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_waitframe::ptr> stmt_waitframe
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_waitframe { $$.as_waitframe = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_waitframe
: WAITFRAME SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
| WAITFRAME LPAREN RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::h2::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

1
gen/hash/cmd.txt Normal file
View File

@ -0,0 +1 @@
clang++ -Wall -std=c++20 iw9_hash.cpp -o iw9_hash

75105
gen/hash/iw9_hash.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +0,0 @@
generate: IW5
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
IW5: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/iw5/xsk/

View File

@ -1,852 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {IW5}
%define api.namespace {xsk::gsc::iw5}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::iw5::lexer& lexer }
%parse-param { xsk::gsc::iw5::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "iw5.hpp"
namespace xsk::gsc::iw5 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::iw5::parser::symbol_type IW5lex(xsk::gsc::iw5::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::iw5::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: IW6
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
IW6: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/iw6/xsk/

View File

@ -1,852 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {IW6}
%define api.namespace {xsk::gsc::iw6}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::iw6::lexer& lexer }
%parse-param { xsk::gsc::iw6::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "iw6.hpp"
namespace xsk::gsc::iw6 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::iw6::parser::symbol_type IW6lex(xsk::gsc::iw6::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::iw6::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: IW7
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
IW7: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/iw7/xsk/

View File

@ -1,852 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {IW7}
%define api.namespace {xsk::gsc::iw7}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::iw7::lexer& lexer }
%parse-param { xsk::gsc::iw7::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "iw7.hpp"
namespace xsk::gsc::iw7 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::iw7::parser::symbol_type IW7lex(xsk::gsc::iw7::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::iw7::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: IW8
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
IW8: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/iw8/xsk/

View File

@ -1,878 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {IW8}
%define api.namespace {xsk::gsc::iw8}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::iw8::lexer& lexer }
%parse-param { xsk::gsc::iw8::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "iw8.hpp"
namespace xsk::gsc::iw8 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::iw8::parser::symbol_type IW8lex(xsk::gsc::iw8::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token WAITFRAME "waitframe"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token ISDEFINED "isdefined"
%token ISTRUE "istrue"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_waitframe::ptr> stmt_waitframe
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_isdefined::ptr> expr_isdefined
%type <ast::expr_istrue::ptr> expr_istrue
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_waitframe { $$.as_waitframe = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_waitframe
: WAITFRAME SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
| WAITFRAME LPAREN RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_isdefined { $$.as_node = std::move($1); }
| expr_istrue { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_isdefined
: ISDEFINED LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_isdefined>(@$, std::move($3)); }
;
expr_istrue
: ISTRUE LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_istrue>(@$, std::move($3)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::iw8::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: S1
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
S1: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/s1/xsk/

View File

@ -1,862 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {S1}
%define api.namespace {xsk::gsc::s1}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::s1::lexer& lexer }
%parse-param { xsk::gsc::s1::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "s1.hpp"
namespace xsk::gsc::s1 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::s1::parser::symbol_type S1lex(xsk::gsc::s1::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token WAITFRAME "waitframe"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_waitframe::ptr> stmt_waitframe
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_waitframe { $$.as_waitframe = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_waitframe
: WAITFRAME SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
| WAITFRAME LPAREN RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::s1::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: S2
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
S2: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/s2/xsk/

View File

@ -1,862 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {S2}
%define api.namespace {xsk::gsc::s2}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::s2::lexer& lexer }
%parse-param { xsk::gsc::s2::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "s2.hpp"
namespace xsk::gsc::s2 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::s2::parser::symbol_type S2lex(xsk::gsc::s2::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token WAITFRAME "waitframe"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_waitframe::ptr> stmt_waitframe
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_waitframe { $$.as_waitframe = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_waitframe
: WAITFRAME SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
| WAITFRAME LPAREN RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::s2::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: S4
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
S4: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/s4/xsk/

View File

@ -1,878 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {S4}
%define api.namespace {xsk::gsc::s4}
%define api.location.type {xsk::gsc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::gsc::s4::lexer& lexer }
%parse-param { xsk::gsc::s4::lexer& lexer }
%parse-param { xsk::gsc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "s4.hpp"
namespace xsk::gsc::s4 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::gsc;
xsk::gsc::s4::parser::symbol_type S4lex(xsk::gsc::s4::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token WAITFRAME "waitframe"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token BREAKPOINT "breakpoint"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token CHILDTHREAD "childthread"
%token THISTHREAD "thisthread"
%token CALL "call"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token ISDEFINED "isdefined"
%token ISTRUE "istrue"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_waitframe::ptr> stmt_waitframe
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_breakpoint::ptr> stmt_breakpoint
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_add_array::ptr> expr_add_array
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_isdefined::ptr> expr_isdefined
%type <ast::expr_istrue::ptr> expr_istrue
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_thisthread::ptr> expr_thisthread
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc ADD_ARRAY
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_waitframe { $$.as_waitframe = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_breakpoint { $$.as_breakpoint = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_waitframe
: WAITFRAME SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
| WAITFRAME LPAREN RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waitframe>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_breakpoint
: BREAKPOINT SEMICOLON
{ $$ = std::make_unique<ast::stmt_breakpoint>(@$); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_add_array { $$.as_node = std::move($1); }
| expr_isdefined { $$.as_node = std::move($1); }
| expr_istrue { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_thisthread { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
| CHILDTHREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::childthread); }
| CHILDTHREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::childthread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
| CHILDTHREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::childthread); }
| CALL LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::builtin); }
;
expr_add_array
: LBRACKET expr_arguments_no_empty RBRACKET
{ $$ = std::make_unique<ast::expr_add_array>(@$, std::move($2)); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr %prec ADD_ARRAY
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_isdefined
: ISDEFINED LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_isdefined>(@$, std::move($3)); }
;
expr_istrue
: ISTRUE LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_istrue>(@$, std::move($3)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_thisthread
: THISTHREAD
{ $$ = std::make_unique<ast::expr_thisthread>(@$); };
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::gsc::s4::parser::error(const xsk::gsc::location& loc, const std::string& msg)
{
throw xsk::gsc::comp_error(loc, msg);
}

View File

@ -1,9 +0,0 @@
generate: T6
clean:
rm -rf ./parser.hpp
rm -rf ./parser.cpp
T6: parser.ypp
bison parser.ypp -Wcounterexamples
mv parser.hpp parser.cpp ../../src/t6/xsk/

View File

@ -1,984 +0,0 @@
/* Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
*/
%require "3.7"
%skeleton "lalr1.cc"
%language "c++"
%output "parser.cpp"
%defines "parser.hpp"
%define api.prefix {T6}
%define api.namespace {xsk::arc::t6}
%define api.location.type {xsk::arc::location}
%define api.value.type variant
%define api.token.constructor
%define api.token.raw
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
%locations
%lex-param { xsk::arc::t6::lexer& lexer }
%parse-param { xsk::arc::t6::lexer& lexer }
%parse-param { xsk::arc::ast::program::ptr& ast }
%code requires
{
#ifdef _MSC_VER
#pragma warning(disable:4065)
#pragma warning(disable:4127)
#endif
#include "t6.hpp"
namespace xsk::arc::t6 { class lexer; }
}
%code top
{
#include "stdafx.hpp"
#include "parser.hpp"
#include "lexer.hpp"
using namespace xsk::arc;
xsk::arc::t6::parser::symbol_type T6lex(xsk::arc::t6::lexer& lexer);
}
%token SH_DEFINE "#define"
%token SH_UNDEF "#undef"
%token SH_IFDEF "#ifdef"
%token SH_IFNDEF "#ifndef"
%token SH_IF "#if"
%token SH_ELIF "#elif"
%token SH_ELSE "#else"
%token SH_ENDIF "#endif"
%token DEVBEGIN "/#"
%token DEVEND "#/"
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
%token WAITTILL "waittill"
%token WAITTILLMATCH "waittillmatch"
%token WAITTILLFRAMEEND "waittillframeend"
%token IF "if"
%token ELSE "else"
%token DO "do"
%token WHILE "while"
%token FOR "for"
%token FOREACH "foreach"
%token IN "in"
%token SWITCH "switch"
%token CASE "case"
%token DEFAULT "default"
%token BREAK "break"
%token CONTINUE "continue"
%token RETURN "return"
%token PROFBEGIN "prof_begin"
%token PROFEND "prof_end"
%token THREAD "thread"
%token TRUE "true"
%token FALSE "false"
%token UNDEFINED "undefined"
%token SIZE "size"
%token GAME "game"
%token SELF "self"
%token ANIM "anim"
%token LEVEL "level"
%token GETNEXTARRAYKEY "getnextarraykey"
%token GETFIRSTARRAYKEY "getfirstarraykey"
%token GETDVARCOLORALPHA "getdvarcoloralpha"
%token GETDVARCOLORBLUE "getdvarcolorblue"
%token GETDVARCOLORGREEN "getdvarcolorgreen"
%token GETDVARCOLORRED "getdvarcolorred"
%token GETDVARVECTOR "getdvarvector"
%token GETDVARFLOAT "getdvarfloat"
%token GETDVARINT "getdvarint"
%token GETDVAR "getdvar"
%token GETTIME "gettime"
%token ABS "abs"
%token VECTORTOANGLES "vectortoangles"
%token ANGLECLAMP180 "angleclamp180"
%token ANGLESTOFORWARD "anglestoforward"
%token ANGLESTORIGHT "anglestoright"
%token ANGLESTOUP "anglestoup"
%token VECTORSCALE "vectorscale"
%token ISDEFINED "isdefined"
%token LPAREN "("
%token RPAREN ")"
%token LBRACE "{"
%token RBRACE "}"
%token LBRACKET "["
%token RBRACKET "]"
%token COMMA ","
%token DOT "."
%token DOUBLECOLON "::"
%token COLON ":"
%token SEMICOLON ";"
%token QMARK "?"
%token INCREMENT "++"
%token DECREMENT "--"
%token LSHIFT "<<"
%token RSHIFT ">>"
%token OR "||"
%token AND "&&"
%token EQUALITY "=="
%token INEQUALITY "!="
%token LESS_EQUAL "<="
%token GREATER_EQUAL ">="
%token LESS "<"
%token GREATER ">"
%token NOT "!"
%token COMPLEMENT "~"
%token ASSIGN "="
%token ASSIGN_ADD "+="
%token ASSIGN_SUB "-="
%token ASSIGN_MUL "*="
%token ASSIGN_DIV "/="
%token ASSIGN_MOD "%="
%token ASSIGN_BW_OR "|="
%token ASSIGN_BW_AND "&="
%token ASSIGN_BW_EXOR "^="
%token ASSIGN_RSHIFT ">>="
%token ASSIGN_LSHIFT "<<="
%token BITWISE_OR "|"
%token BITWISE_AND "&"
%token BITWISE_EXOR "^"
%token ADD "+"
%token SUB "-"
%token MUL "*"
%token DIV "/"
%token MOD "%"
%token <std::string> PATH "path"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> STRING "string literal"
%token <std::string> ISTRING "localized string"
%token <std::string> HASH "hash"
%token <std::string> FLOAT "float"
%token <std::string> INTEGER "integer"
%type <ast::program::ptr> program
%type <ast::include::ptr> include
%type <ast::decl> declaration
%type <ast::decl_usingtree::ptr> decl_usingtree
%type <ast::decl_constant::ptr> decl_constant
%type <ast::decl_thread::ptr> decl_thread
%type <ast::stmt> stmt
%type <ast::stmt> stmt_or_dev
%type <ast::stmt_list::ptr> stmt_list
%type <ast::stmt_list::ptr> stmt_or_dev_list
%type <ast::stmt_dev::ptr> stmt_dev
%type <ast::stmt_list::ptr> stmt_block
%type <ast::stmt_expr::ptr> stmt_expr
%type <ast::stmt_call::ptr> stmt_call
%type <ast::stmt_assign::ptr> stmt_assign
%type <ast::stmt_endon::ptr> stmt_endon
%type <ast::stmt_notify::ptr> stmt_notify
%type <ast::stmt_wait::ptr> stmt_wait
%type <ast::stmt_waittill::ptr> stmt_waittill
%type <ast::stmt_waittillmatch::ptr> stmt_waittillmatch
%type <ast::stmt_waittillframeend::ptr> stmt_waittillframeend
%type <ast::stmt_if::ptr> stmt_if
%type <ast::stmt_ifelse::ptr> stmt_ifelse
%type <ast::stmt_while::ptr> stmt_while
%type <ast::stmt_dowhile::ptr> stmt_dowhile
%type <ast::stmt_for::ptr> stmt_for
%type <ast::stmt_foreach::ptr> stmt_foreach
%type <ast::stmt_switch::ptr> stmt_switch
%type <ast::stmt_case::ptr> stmt_case
%type <ast::stmt_default::ptr> stmt_default
%type <ast::stmt_break::ptr> stmt_break
%type <ast::stmt_continue::ptr> stmt_continue
%type <ast::stmt_return::ptr> stmt_return
%type <ast::stmt_prof_begin::ptr> stmt_prof_begin
%type <ast::stmt_prof_end::ptr> stmt_prof_end
%type <ast::expr> expr
%type <ast::expr> expr_or_empty
%type <ast::expr> expr_assign
%type <ast::expr> expr_increment
%type <ast::expr> expr_decrement
%type <ast::expr> expr_ternary
%type <ast::expr> expr_binary
%type <ast::expr> expr_primitive
%type <ast::expr_complement::ptr> expr_complement
%type <ast::expr_not::ptr> expr_not
%type <ast::expr_call::ptr> expr_call
%type <ast::expr_method::ptr> expr_method
%type <ast::call> expr_function
%type <ast::call> expr_pointer
%type <ast::expr_parameters::ptr> expr_parameters
%type <ast::expr_arguments::ptr> expr_arguments
%type <ast::expr_arguments::ptr> expr_arguments_no_empty
%type <ast::expr_getnextarraykey::ptr> expr_getnextarraykey
%type <ast::expr_getfirstarraykey::ptr> expr_getfirstarraykey
%type <ast::expr_getdvarcoloralpha::ptr> expr_getdvarcoloralpha
%type <ast::expr_getdvarcolorblue::ptr> expr_getdvarcolorblue
%type <ast::expr_getdvarcolorgreen::ptr> expr_getdvarcolorgreen
%type <ast::expr_getdvarcolorred::ptr> expr_getdvarcolorred
%type <ast::expr_getdvarvector::ptr> expr_getdvarvector
%type <ast::expr_getdvarfloat::ptr> expr_getdvarfloat
%type <ast::expr_getdvarint::ptr> expr_getdvarint
%type <ast::expr_getdvar::ptr> expr_getdvar
%type <ast::expr_gettime::ptr> expr_gettime
%type <ast::expr_abs::ptr> expr_abs
%type <ast::expr_vectortoangles::ptr> expr_vectortoangles
%type <ast::expr_angleclamp180::ptr> expr_angleclamp180
%type <ast::expr_anglestoforward::ptr> expr_anglestoforward
%type <ast::expr_anglestoright::ptr> expr_anglestoright
%type <ast::expr_anglestoup::ptr> expr_anglestoup
%type <ast::expr_vectorscale::ptr> expr_vectorscale
%type <ast::expr_isdefined::ptr> expr_isdefined
%type <ast::expr_reference::ptr> expr_reference
%type <ast::expr_array::ptr> expr_array
%type <ast::expr_field::ptr> expr_field
%type <ast::expr_size::ptr> expr_size
%type <ast::expr_paren::ptr> expr_paren
%type <ast::expr> expr_object
%type <ast::expr_empty_array::ptr> expr_empty_array
%type <ast::expr_undefined::ptr> expr_undefined
%type <ast::expr_game::ptr> expr_game
%type <ast::expr_self::ptr> expr_self
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
%type <ast::expr_istring::ptr> expr_istring
%type <ast::expr_string::ptr> expr_string
%type <ast::expr_vector::ptr> expr_vector
%type <ast::expr_hash::ptr> expr_hash
%type <ast::expr_float::ptr> expr_float
%type <ast::expr_integer::ptr> expr_integer
%type <ast::expr_false::ptr> expr_false
%type <ast::expr_true::ptr> expr_true
%nonassoc SIZEOF
%nonassoc RBRACKET
%nonassoc THEN
%nonassoc ELSE
%nonassoc INCREMENT DECREMENT
%precedence TERN
%right QMARK
%left OR
%left AND
%left BITWISE_OR
%left BITWISE_EXOR
%left BITWISE_AND
%left EQUALITY INEQUALITY
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left LSHIFT RSHIFT
%left ADD SUB
%left MUL DIV MOD
%right NOT COMPLEMENT
%precedence NEG
%precedence ANIMREF
%precedence PREINC PREDEC
%precedence POSTINC POSTDEC
%start root
%%
root
: program { ast = std::move($1); }
| { ast = std::make_unique<ast::program>(@$); }
;
program
: program inline
{ $$ = std::move($1); }
| program include
{ $$ = std::move($1); $$->includes.push_back(std::move($2)); }
| program declaration
{ $$ = std::move($1); $$->declarations.push_back(std::move($2)); }
| inline
{ $$ = std::make_unique<ast::program>(@$); }
| include
{ $$ = std::make_unique<ast::program>(@$); $$->includes.push_back(std::move($1)); }
| declaration
{ $$ = std::make_unique<ast::program>(@$); $$->declarations.push_back(std::move($1)); }
;
inline
: INLINE expr_path SEMICOLON { lexer.push_header($2->value); }
;
include
: INCLUDE expr_path SEMICOLON
{ $$ = std::make_unique<ast::include>(@$, std::move($2)); }
;
declaration
: DEVBEGIN { $$.as_dev_begin = std::make_unique<ast::decl_dev_begin>(@$); }
| DEVEND { $$.as_dev_end = std::make_unique<ast::decl_dev_end>(@$); }
| decl_usingtree { $$.as_usingtree = std::move($1); }
| decl_constant { $$.as_constant = std::move($1); }
| decl_thread { $$.as_thread = std::move($1); }
;
decl_usingtree
: USINGTREE LPAREN expr_string RPAREN SEMICOLON
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_usingtree>(@$, std::move($3)); }
;
decl_constant
: expr_identifier ASSIGN expr SEMICOLON
{ $$ = std::make_unique<ast::decl_constant>(@$, std::move($1), std::move($3)); }
;
decl_thread
: expr_identifier LPAREN expr_parameters RPAREN stmt_block
{ lexer.ban_header(@$); $$ = std::make_unique<ast::decl_thread>(@$, std::move($1), std::move($3), std::move($5)); }
;
stmt
: stmt_block { $$.as_list = std::move($1); }
| stmt_call { $$.as_call = std::move($1); }
| stmt_assign { $$.as_assign = std::move($1); }
| stmt_endon { $$.as_endon = std::move($1); }
| stmt_notify { $$.as_notify = std::move($1); }
| stmt_wait { $$.as_wait = std::move($1); }
| stmt_waittill { $$.as_waittill = std::move($1); }
| stmt_waittillmatch { $$.as_waittillmatch = std::move($1); }
| stmt_waittillframeend { $$.as_waittillframeend = std::move($1); }
| stmt_if { $$.as_if = std::move($1); }
| stmt_ifelse { $$.as_ifelse = std::move($1); }
| stmt_while { $$.as_while = std::move($1); }
| stmt_dowhile { $$.as_dowhile = std::move($1); }
| stmt_for { $$.as_for = std::move($1); }
| stmt_foreach { $$.as_foreach = std::move($1); }
| stmt_switch { $$.as_switch = std::move($1); }
| stmt_case { $$.as_case = std::move($1); }
| stmt_default { $$.as_default = std::move($1); }
| stmt_break { $$.as_break = std::move($1); }
| stmt_continue { $$.as_continue = std::move($1); }
| stmt_return { $$.as_return = std::move($1); }
| stmt_prof_begin { $$.as_prof_begin = std::move($1); }
| stmt_prof_end { $$.as_prof_end = std::move($1); }
;
stmt_or_dev
: stmt { $$ = std::move($1); }
| stmt_dev { $$.as_dev = std::move($1); }
;
stmt_list
: stmt_list stmt
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_or_dev_list
: stmt_or_dev_list stmt_or_dev
{ $$ = std::move($1); $$->list.push_back(std::move($2)); }
| stmt_or_dev
{ $$ = std::make_unique<ast::stmt_list>(@$); $$->list.push_back(std::move($1)); }
;
stmt_dev
: DEVBEGIN stmt_list DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::move($2)); }
| DEVBEGIN DEVEND { $$ = std::make_unique<ast::stmt_dev>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_block
: LBRACE stmt_or_dev_list RBRACE { $$ = std::move($2); }
| LBRACE RBRACE { $$ = std::make_unique<ast::stmt_list>(@$); }
;
stmt_expr
: expr_assign
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_increment
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
| expr_decrement
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::move($1)); }
|
{ $$ = std::make_unique<ast::stmt_expr>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_call
: expr_call SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
| expr_method SEMICOLON
{ $$ = std::make_unique<ast::stmt_call>(@$, ast::expr(std::move($1))); }
;
stmt_assign
: expr_assign SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_increment SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
| expr_decrement SEMICOLON
{ $$ = std::make_unique<ast::stmt_assign>(@$, std::move($1)); }
;
stmt_endon
: expr_object ENDON LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_endon>(@$, std::move($1), std::move($4)); }
;
stmt_notify
: expr_object NOTIFY LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object NOTIFY LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_notify>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_wait
: WAIT expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_wait>(@$, std::move($2)); }
;
stmt_waittill
: expr_object WAITTILL LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILL LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittill>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillmatch
: expr_object WAITTILLMATCH LPAREN expr COMMA expr_arguments_no_empty RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::move($6)); }
| expr_object WAITTILLMATCH LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillmatch>(@$, std::move($1), std::move($4), std::make_unique<ast::expr_arguments>(@$)); }
;
stmt_waittillframeend
: WAITTILLFRAMEEND SEMICOLON
{ $$ = std::make_unique<ast::stmt_waittillframeend>(@$); }
;
stmt_if
: IF LPAREN expr RPAREN stmt %prec THEN
{ $$ = std::make_unique<ast::stmt_if>(@$, std::move($3), std::move($5)); }
;
stmt_ifelse
: IF LPAREN expr RPAREN stmt ELSE stmt
{ $$ = std::make_unique<ast::stmt_ifelse>(@$, std::move($3), std::move($5), std::move($7)); }
;
stmt_while
: WHILE LPAREN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_while>(@$, std::move($3), std::move($5)); }
;
stmt_dowhile
: DO stmt WHILE LPAREN expr RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_dowhile>(@$, std::move($5), std::move($2)); }
;
stmt_for
: FOR LPAREN stmt_expr SEMICOLON expr_or_empty SEMICOLON stmt_expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_for>(@$, ast::stmt(std::move($3)), std::move($5), ast::stmt(std::move($7)), std::move($9)); }
;
stmt_foreach
: FOREACH LPAREN expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), std::move($5), std::move($7)); }
| FOREACH LPAREN expr_identifier COMMA expr_identifier IN expr RPAREN stmt
{ $$ = std::make_unique<ast::stmt_foreach>(@$, ast::expr(std::move($3)), ast::expr(std::move($5)), std::move($7), std::move($9)); }
;
stmt_switch
: SWITCH LPAREN expr RPAREN stmt_block
{ $$ = std::make_unique<ast::stmt_switch>(@$, std::move($3), std::move($5)); }
;
stmt_case
: CASE expr_integer COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
| CASE expr_string COLON
{ $$ = std::make_unique<ast::stmt_case>(@$, ast::expr(std::move($2)), std::make_unique<ast::stmt_list>(@$)); }
;
stmt_default
: DEFAULT COLON
{ $$ = std::make_unique<ast::stmt_default>(@$, std::make_unique<ast::stmt_list>(@$)); }
;
stmt_break
: BREAK SEMICOLON
{ $$ = std::make_unique<ast::stmt_break>(@$); }
;
stmt_continue
: CONTINUE SEMICOLON
{ $$ = std::make_unique<ast::stmt_continue>(@$); }
;
stmt_return
: RETURN expr SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::move($2)); }
| RETURN SEMICOLON
{ $$ = std::make_unique<ast::stmt_return>(@$, std::make_unique<ast::node>(@$)); }
;
stmt_prof_begin
: PROFBEGIN LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_begin>(@$, std::move($3)); }
;
stmt_prof_end
: PROFEND LPAREN expr_arguments RPAREN SEMICOLON
{ $$ = std::make_unique<ast::stmt_prof_end>(@$, std::move($3)); }
;
expr
: expr_ternary { $$ = std::move($1); }
| expr_binary { $$ = std::move($1); }
| expr_primitive { $$ = std::move($1); }
;
expr_or_empty
: expr { $$ = std::move($1); }
| { $$.as_node = std::make_unique<ast::node>(@$); }
;
expr_assign
: expr_object ASSIGN expr
{ $$.as_node = std::make_unique<ast::expr_assign_equal>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_OR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_AND expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_BW_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_assign_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_left>(@$, std::move($1),std::move( $3)); }
| expr_object ASSIGN_RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_assign_shift_right>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_ADD expr
{ $$.as_node = std::make_unique<ast::expr_assign_add>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_SUB expr
{ $$.as_node = std::make_unique<ast::expr_assign_sub>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MUL expr
{ $$.as_node = std::make_unique<ast::expr_assign_mul>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_DIV expr
{ $$.as_node = std::make_unique<ast::expr_assign_div>(@$, std::move($1), std::move($3)); }
| expr_object ASSIGN_MOD expr
{ $$.as_node = std::make_unique<ast::expr_assign_mod>(@$, std::move($1), std::move($3)); }
;
expr_increment
: INCREMENT expr_object %prec PREINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($2), true); }
| expr_object INCREMENT %prec POSTINC
{ $$.as_node = std::make_unique<ast::expr_increment>(@$, std::move($1), false); }
;
expr_decrement
: DECREMENT expr_object %prec PREDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($2), true); }
| expr_object DECREMENT %prec POSTDEC
{ $$.as_node = std::make_unique<ast::expr_decrement>(@$, std::move($1), false); }
;
expr_ternary
: expr QMARK expr COLON expr %prec TERN
{ $$.as_node = std::make_unique<ast::expr_ternary>(@$, std::move($1), std::move($3), std::move($5)); }
;
expr_binary
: expr OR expr
{ $$.as_node = std::make_unique<ast::expr_or>(@$, std::move($1), std::move($3)); }
| expr AND expr
{ $$.as_node = std::make_unique<ast::expr_and>(@$, std::move($1), std::move($3)); }
| expr EQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_equality>(@$, std::move($1), std::move($3)); }
| expr INEQUALITY expr
{ $$.as_node = std::make_unique<ast::expr_inequality>(@$, std::move($1), std::move($3)); }
| expr LESS_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_less_equal>(@$, std::move($1), std::move($3)); }
| expr GREATER_EQUAL expr
{ $$.as_node = std::make_unique<ast::expr_greater_equal>(@$, std::move($1), std::move($3)); }
| expr LESS expr
{ $$.as_node = std::make_unique<ast::expr_less>(@$, std::move($1), std::move($3)); }
| expr GREATER expr
{ $$.as_node = std::make_unique<ast::expr_greater>(@$, std::move($1), std::move($3)); }
| expr BITWISE_OR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_or>(@$, std::move($1), std::move($3)); }
| expr BITWISE_AND expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_and>(@$, std::move($1), std::move($3)); }
| expr BITWISE_EXOR expr
{ $$.as_node = std::make_unique<ast::expr_bitwise_exor>(@$, std::move($1), std::move($3)); }
| expr LSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_left>(@$, std::move($1), std::move($3)); }
| expr RSHIFT expr
{ $$.as_node = std::make_unique<ast::expr_shift_right>(@$, std::move($1), std::move($3)); }
| expr ADD expr
{ $$.as_node = std::make_unique<ast::expr_add>(@$, std::move($1), std::move($3)); }
| expr SUB expr
{ $$.as_node = std::make_unique<ast::expr_sub>(@$, std::move($1), std::move($3)); }
| expr MUL expr
{ $$.as_node = std::make_unique<ast::expr_mul>(@$, std::move($1), std::move($3)); }
| expr DIV expr
{ $$.as_node = std::make_unique<ast::expr_div>(@$, std::move($1), std::move($3)); }
| expr MOD expr
{ $$.as_node = std::make_unique<ast::expr_mod>(@$, std::move($1), std::move($3)); }
;
expr_primitive
: expr_complement { $$.as_node = std::move($1); }
| expr_not { $$.as_node = std::move($1); }
| expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_getnextarraykey { $$.as_node = std::move($1); }
| expr_getfirstarraykey { $$.as_node = std::move($1); }
| expr_getdvarcoloralpha { $$.as_node = std::move($1); }
| expr_getdvarcolorblue { $$.as_node = std::move($1); }
| expr_getdvarcolorgreen { $$.as_node = std::move($1); }
| expr_getdvarcolorred { $$.as_node = std::move($1); }
| expr_getdvarvector { $$.as_node = std::move($1); }
| expr_getdvarfloat { $$.as_node = std::move($1); }
| expr_getdvarint { $$.as_node = std::move($1); }
| expr_getdvar { $$.as_node = std::move($1); }
| expr_gettime { $$.as_node = std::move($1); }
| expr_abs { $$.as_node = std::move($1); }
| expr_vectortoangles { $$.as_node = std::move($1); }
| expr_angleclamp180 { $$.as_node = std::move($1); }
| expr_anglestoforward { $$.as_node = std::move($1); }
| expr_anglestoright { $$.as_node = std::move($1); }
| expr_anglestoup { $$.as_node = std::move($1); }
| expr_vectorscale { $$.as_node = std::move($1); }
| expr_isdefined { $$.as_node = std::move($1); }
| expr_reference { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_size { $$.as_node = std::move($1); }
| expr_paren { $$.as_node = std::move($1); }
| expr_empty_array { $$.as_node = std::move($1); }
| expr_undefined { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
| expr_vector { $$.as_node = std::move($1); }
| expr_hash { $$.as_node = std::move($1); }
| expr_float { $$.as_node = std::move($1); }
| expr_integer { $$.as_node = std::move($1); }
| expr_false { $$.as_node = std::move($1); }
| expr_true { $$.as_node = std::move($1); }
;
expr_complement
: COMPLEMENT expr
{ $$ = std::make_unique<ast::expr_complement>(@$, std::move($2)); }
;
expr_not
: NOT expr
{ $$ = std::make_unique<ast::expr_not>(@$, std::move($2)); }
;
expr_call
: expr_function { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
| expr_pointer { $$ = std::make_unique<ast::expr_call>(@$, std::move($1)); }
;
expr_method
: expr_object expr_function { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
| expr_object expr_pointer { $$ = std::make_unique<ast::expr_method>(@$, std::move($1), std::move($2)); }
;
expr_function
: expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($1), std::move($3), ast::call::mode::normal); }
| expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($1), std::move($3), std::move($5), ast::call::mode::normal); }
| THREAD expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::make_unique<ast::expr_path>(@$), std::move($2), std::move($4), ast::call::mode::thread); }
| THREAD expr_path DOUBLECOLON expr_identifier LPAREN expr_arguments RPAREN
{ $$.as_function = std::make_unique<ast::expr_function>(@$, std::move($2), std::move($4), std::move($6), ast::call::mode::thread); }
;
expr_pointer
: LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($3), std::move($7), ast::call::mode::normal); }
| THREAD LBRACKET LBRACKET expr RBRACKET RBRACKET LPAREN expr_arguments RPAREN
{ $$.as_pointer = std::make_unique<ast::expr_pointer>(@$, std::move($4), std::move($8), ast::call::mode::thread); }
;
expr_parameters
: expr_parameters COMMA expr_identifier
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr_identifier
{ $$ = std::make_unique<ast::expr_parameters>(@$); $$->list.push_back(std::move($1)); }
|
{ $$ = std::make_unique<ast::expr_parameters>(@$); }
;
expr_arguments
: expr_arguments_no_empty
{ $$ = std::move($1); }
|
{ $$ = std::make_unique<ast::expr_arguments>(@$); }
;
expr_arguments_no_empty
: expr_arguments COMMA expr
{ $$ = std::move($1); $$->list.push_back(std::move($3)); }
| expr
{ $$ = std::make_unique<ast::expr_arguments>(@$); $$->list.push_back(std::move($1)); }
;
expr_getnextarraykey
: GETNEXTARRAYKEY LPAREN expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_getnextarraykey>(@$, std::move($3), std::move($5)); }
;
expr_getfirstarraykey
: GETFIRSTARRAYKEY LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getfirstarraykey>(@$, std::move($3)); }
;
expr_getdvarcoloralpha
: GETDVARCOLORALPHA LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvarcoloralpha>(@$, std::move($3)); }
;
expr_getdvarcolorblue
: GETDVARCOLORBLUE LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvarcolorblue>(@$, std::move($3)); }
;
expr_getdvarcolorgreen
: GETDVARCOLORGREEN LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvarcolorgreen>(@$, std::move($3)); }
;
expr_getdvarcolorred
: GETDVARCOLORRED LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvarcolorred>(@$, std::move($3)); }
;
expr_getdvarvector
: GETDVARVECTOR LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvarvector>(@$, std::move($3)); }
;
expr_getdvarfloat
: GETDVARFLOAT LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvarfloat>(@$, std::move($3)); }
;
expr_getdvarint
: GETDVARINT LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvarint>(@$, std::move($3)); }
;
expr_getdvar
: GETDVAR LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_getdvar>(@$, std::move($3)); }
;
expr_gettime
: GETTIME LPAREN RPAREN
{ $$ = std::make_unique<ast::expr_gettime>(@$); }
;
expr_abs
: ABS LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_abs>(@$, std::move($3)); }
;
expr_vectortoangles
: VECTORTOANGLES LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_vectortoangles>(@$, std::move($3)); }
;
expr_angleclamp180
: ANGLECLAMP180 LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_angleclamp180>(@$, std::move($3)); }
;
expr_anglestoforward
: ANGLESTOFORWARD LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_anglestoforward>(@$, std::move($3)); }
;
expr_anglestoright
: ANGLESTORIGHT LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_anglestoright>(@$, std::move($3)); }
;
expr_anglestoup
: ANGLESTOUP LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_anglestoup>(@$, std::move($3)); }
;
expr_vectorscale
: VECTORSCALE LPAREN expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vectorscale>(@$, std::move($3), std::move($5)); }
;
expr_isdefined
: ISDEFINED LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_isdefined>(@$, std::move($3)); }
;
expr_reference
: DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::make_unique<ast::expr_path>(@$), std::move($2)); }
| expr_path DOUBLECOLON expr_identifier
{ $$ = std::make_unique<ast::expr_reference>(@$, std::move($1), std::move($3)); }
;
expr_array
: expr_object LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, std::move($1), std::move($3)); }
| expr_getdvarvector LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, ast::expr(std::move($1)), std::move($3)); }
| expr_vectortoangles LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, ast::expr(std::move($1)), std::move($3)); }
| expr_angleclamp180 LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, ast::expr(std::move($1)), std::move($3)); }
| expr_anglestoforward LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, ast::expr(std::move($1)), std::move($3)); }
| expr_anglestoright LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, ast::expr(std::move($1)), std::move($3)); }
| expr_anglestoup LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, ast::expr(std::move($1)), std::move($3)); }
| expr_vectorscale LBRACKET expr RBRACKET
{ $$ = std::make_unique<ast::expr_array>(@$, ast::expr(std::move($1)), std::move($3)); }
;
expr_field
: expr_object DOT expr_identifier_nosize
{ $$ = std::make_unique<ast::expr_field>(@$, std::move($1), std::move($3)); }
;
expr_size
: expr_object DOT SIZE %prec SIZEOF
{ $$ = std::make_unique<ast::expr_size>(@$, std::move($1)); }
;
expr_paren
: LPAREN expr RPAREN
{ $$ = std::make_unique<ast::expr_paren>(@$, std::move($2)); }
;
expr_object
: expr_call { $$.as_node = std::move($1); }
| expr_method { $$.as_node = std::move($1); }
| expr_array { $$.as_node = std::move($1); }
| expr_field { $$.as_node = std::move($1); }
| expr_game { $$.as_node = std::move($1); }
| expr_self { $$.as_node = std::move($1); }
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
;
expr_empty_array
: LBRACKET RBRACKET
{ $$ = std::make_unique<ast::expr_empty_array>(@$); };
;
expr_undefined
: UNDEFINED
{ $$ = std::make_unique<ast::expr_undefined>(@$); };
;
expr_game
: GAME
{ $$ = std::make_unique<ast::expr_game>(@$); };
;
expr_self
: SELF
{ $$ = std::make_unique<ast::expr_self>(@$); };
;
expr_anim
: ANIM
{ $$ = std::make_unique<ast::expr_anim>(@$); };
;
expr_level
: LEVEL
{ $$ = std::make_unique<ast::expr_level>(@$); };
;
expr_animation
: MOD IDENTIFIER %prec ANIMREF
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
;
expr_identifier
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };
| SIZE
{ $$ = std::make_unique<ast::expr_identifier>(@$, "size"); };
;
expr_path
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
| PATH
{ $$ = std::make_unique<ast::expr_path>(@$, $1); };
;
expr_istring
: ISTRING
{ $$ = std::make_unique<ast::expr_istring>(@$, $1); };
;
expr_string
: STRING
{ $$ = std::make_unique<ast::expr_string>(@$, $1); };
;
expr_vector
: LPAREN expr COMMA expr COMMA expr RPAREN
{ $$ = std::make_unique<ast::expr_vector>(@$, std::move($2), std::move($4), std::move($6)); };
;
expr_hash
: HASH
{ $$ = std::make_unique<ast::expr_hash>(@$, $1); };
;
expr_float
: SUB FLOAT %prec NEG
{ $$ = std::make_unique<ast::expr_float>(@$, "-" + $2); };
| FLOAT
{ $$ = std::make_unique<ast::expr_float>(@$, $1); };
;
expr_integer
: SUB INTEGER %prec NEG
{ $$ = std::make_unique<ast::expr_integer>(@$, "-" + $2); };
| INTEGER
{ $$ = std::make_unique<ast::expr_integer>(@$, $1); };
;
expr_false
: FALSE
{ $$ = std::make_unique<ast::expr_false>(@$); };
;
expr_true
: TRUE
{ $$ = std::make_unique<ast::expr_true>(@$); };
;
%%
void xsk::arc::t6::parser::error(const xsk::arc::location& loc, const std::string& msg)
{
throw xsk::arc::comp_error(loc, msg);
}

View File

@ -0,0 +1,48 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/utils/writer.hpp"
#include "xsk/arc/common/types.hpp"
namespace xsk::arc
{
class assembler
{
context const* ctx_;
function const* func_;
assembly const* assembly_;
utils::writer script_;
std::unordered_map<std::string, u16> strpool_;
std::vector<export_ref> exports_;
std::vector<import_ref> imports_;
std::vector<string_ref> strings_;
std::vector<animtree_ref> anims_;
public:
assembler(context const* ctx);
auto assemble(assembly const& data, std::string const& name = {}) -> buffer;
private:
auto assemble_function(function& func) -> void;
auto assemble_instruction(instruction const& inst) -> void;
auto assemble_localvars(instruction const& inst) -> void;
auto assemble_jump(instruction const& inst) -> void;
auto assemble_switch(instruction const& inst) -> void;
auto assemble_end_switch(instruction const& inst) -> void;
auto process_string(std::string const& data) -> void;
auto process_function(function const& func) -> void;
auto process_instruction(instruction const& inst) -> void;
auto align_instruction(instruction& inst) -> void;
auto resolve_label(std::string const& name) -> i32;
auto resolve_string(std::string const& name) -> u16;
void add_stringref(std::string const& str, string_type type, u32 ref);
void add_importref(std::vector<std::string> const& data, u32 ref);
void add_animref(std::vector<std::string> const& data, u32 ref);
};
} // namespace xsk::arc

View File

@ -0,0 +1,208 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
constexpr usize opcode_count = 143;
enum class opcode : u8
{
OP_Invalid,
OP_End,
OP_Return,
OP_GetUndefined,
OP_GetZero,
OP_GetByte,
OP_GetNegByte,
OP_GetUnsignedShort,
OP_GetNegUnsignedShort,
OP_GetInteger,
OP_GetFloat,
OP_GetString,
OP_GetIString,
OP_GetVector,
OP_GetLevelObject,
OP_GetAnimObject,
OP_GetSelf,
OP_GetLevel,
OP_GetGame,
OP_GetAnim,
OP_GetAnimation,
OP_GetGameRef,
OP_GetFunction,
OP_CreateLocalVariable,
OP_SafeCreateLocalVariables,
OP_RemoveLocalVariables,
OP_EvalLocalVariableCached,
OP_EvalArray,
OP_EvalLocalArrayRefCached,
OP_EvalArrayRef,
OP_ClearArray,
OP_EmptyArray,
OP_GetSelfObject,
OP_EvalFieldVariable,
OP_EvalFieldVariableRef,
OP_ClearFieldVariable,
OP_SafeSetVariableFieldCached,
OP_SafeSetWaittillVariableFieldCached,
OP_ClearParams,
OP_CheckClearParams,
OP_EvalLocalVariableRefCached,
OP_SetVariableField,
OP_CallBuiltin,
OP_CallBuiltinMethod,
OP_Wait,
OP_WaitTillFrameEnd,
OP_PreScriptCall,
OP_ScriptFunctionCall,
OP_ScriptFunctionCallPointer,
OP_ScriptMethodCall,
OP_ScriptMethodCallPointer,
OP_ScriptThreadCall,
OP_ScriptThreadCallPointer,
OP_ScriptMethodThreadCall,
OP_ScriptMethodThreadCallPointer,
OP_DecTop,
OP_CastFieldObject,
OP_CastBool,
OP_BoolNot,
OP_BoolComplement,
OP_JumpOnFalse,
OP_JumpOnTrue,
OP_JumpOnFalseExpr,
OP_JumpOnTrueExpr,
OP_Jump,
OP_JumpBack,
OP_Inc,
OP_Dec,
OP_Bit_Or,
OP_Bit_Xor,
OP_Bit_And,
OP_Equal,
OP_NotEqual,
OP_LessThan,
OP_GreaterThan,
OP_LessThanOrEqualTo,
OP_GreaterThanOrEqualTo,
OP_ShiftLeft,
OP_ShiftRight,
OP_Plus,
OP_Minus,
OP_Multiply,
OP_Divide,
OP_Modulus,
OP_SizeOf,
OP_WaitTillMatch,
OP_WaitTill,
OP_Notify,
OP_EndOn,
OP_VoidCodePos,
OP_Switch,
OP_EndSwitch,
OP_Vector,
OP_GetHash,
OP_RealWait,
OP_VectorConstant,
OP_IsDefined,
OP_VectorScale,
OP_AnglesToUp,
OP_AnglesToRight,
OP_AnglesToForward,
OP_AngleClamp180,
OP_VectorToAngles,
OP_Abs,
OP_GetTime,
OP_GetDvar,
OP_GetDvarInt,
OP_GetDvarFloat,
OP_GetDvarVector,
OP_GetDvarColorRed,
OP_GetDvarColorGreen,
OP_GetDvarColorBlue,
OP_GetDvarColorAlpha,
OP_FirstArrayKey,
OP_NextArrayKey,
OP_ProfileStart,
OP_ProfileStop,
OP_SafeDecTop,
OP_Nop,
OP_Abort,
OP_Object,
OP_ThreadObject,
OP_EvalLocalVariable,
OP_EvalLocalVariableRef,
OP_DevblockBegin,
OP_DevblockEnd,
OP_EvalLocalVariableCachedDebug,
OP_EvalLocalVariableRefCachedDebug,
OP_LevelEvalFieldVariable,
OP_LevelEvalFieldVariableRef,
OP_SelfEvalFieldVariable,
OP_SelfEvalFieldVariableRef,
OP_GetWorld,
OP_GetWorldObject,
OP_GetClasses,
OP_GetClassesObject,
OP_New,
OP_ScriptFunctionCallClass,
OP_ScriptThreadCallClass,
OP_GetUintptr,
OP_SuperEqual,
OP_SuperNotEqual,
OP_GetAPIFunction,
OP_Count,
};
struct instruction
{
using ptr = std::unique_ptr<instruction>;
u32 index;
u32 size;
opcode opcode;
std::vector<std::string> data;
static auto make() -> instruction::ptr
{
return std::unique_ptr<instruction>(new instruction);
}
};
struct function
{
using ptr = std::unique_ptr<function>;
u32 index;
u32 size;
u8 params;
u8 flags;
std::string name;
std::string space;
std::vector<instruction::ptr> instructions;
std::unordered_map<u32, std::string> labels;
static auto make() -> function::ptr
{
return std::unique_ptr<function>(new function);
}
};
struct assembly
{
using ptr = std::unique_ptr<assembly>;
std::vector<std::string> includes;
std::vector<function::ptr> functions;
static auto make() -> assembly::ptr
{
return std::unique_ptr<assembly>(new assembly);
}
};
} // namespace xsk::arc

View File

@ -0,0 +1,127 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
constexpr usize header_size_v1 = 64;
constexpr usize header_size_v2 = 72;
constexpr usize header_size_v3 = 0;
enum class string_type : u8
{
literal = 0,
canonical = 1,
};
enum class param_type : u8
{
value = 0,
reference = 1,
vararg = 2,
};
enum class export_flags : u8
{
export_none = 0x00,
export_public = 0x01,
export_autoexec = 0x02,
export_private = 0x04,
export_codecall = 0x08,
export_private2 = 0x10,
export_varargs = 0x20,
};
enum class import_flags : u8
{
none = 0,
func_reference = 1,
func_call = 2,
func_call_thread = 3,
meth_call = 4,
meth_call_thread = 5,
developer = 0x10,
unk = 0x20, // T7, T8, T9
};
struct header
{
u64 magic;
u32 source_crc;
u32 include_offset;
u32 animtree_offset;
u32 cseg_offset;
u32 stringtablefixup_offset;
u32 devblock_stringtablefixup_offset;
u32 exports_offset;
u32 imports_offset;
u32 fixup_offset;
u32 globalvar_offset;
u32 profile_offset;
u32 cseg_size;
u32 name;
u16 stringtablefixup_count;
u16 exports_count;
u16 imports_count;
u16 fixup_count;
u16 globalvar_count;
u16 profile_count;
u16 devblock_stringtablefixup_count;
u8 include_count;
u8 animtree_count;
u8 flags;
};
struct animation_ref
{
std::string name;
u32 ref;
};
struct animtree_ref
{
using ptr = std::shared_ptr<animtree_ref>;
std::string name;
std::vector<u32> refs;
std::vector<animation_ref> anims;
};
struct string_ref
{
using ptr = std::shared_ptr<string_ref>;
std::string name;
u8 type;
std::vector<u32> refs;
};
struct import_ref
{
using ptr = std::shared_ptr<import_ref>;
std::string space;
std::string name;
u8 params;
u8 flags;
std::vector<u32> refs;
};
struct export_ref
{
using ptr = std::shared_ptr<export_ref>;
std::string space;
std::string name;
u32 checksum;
u32 offset;
u32 size;
u8 params;
u8 flags;
};
} // namespace xsk::arc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
struct buffer
{
u8 const* data;
usize const size;
buffer() : data{ nullptr }, size{ 0 } {}
buffer(u8 const* data, usize size) : data{ data }, size{ size } {}
};
} // namespace xsk::arc

View File

@ -0,0 +1,21 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
struct define
{
enum kind : u8 { PLAIN, BUILTIN, OBJECT, FUNCTION };
kind type;
// bool vararg;
std::vector<token> args;
std::vector<token> exp;
};
} // namespace xsk::arc

View File

@ -0,0 +1,19 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
struct directive
{
enum kind : u8 { IF, IFDEF, IFNDEF, ELIF, ELIFDEF, ELIFNDEF, ELSE, ENDIF, DEFINE, UNDEF, PRAGMA, WARNING, ERROR, LINE, INCLUDE, INLINE, INSERT, USINGTREE };
kind type;
bool skip;
};
} // namespace xsk::arc

View File

@ -0,0 +1,47 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
class error : public std::runtime_error
{
public:
error(std::string const& what);
};
class asm_error : public std::runtime_error
{
public:
asm_error(std::string const& what);
};
class disasm_error : public std::runtime_error
{
public:
disasm_error(std::string const& what);
};
class ppr_error : public std::runtime_error
{
public:
ppr_error(location const& loc, std::string const& what);
};
class comp_error : public std::runtime_error
{
public:
comp_error(location const& loc, std::string const& what);
};
class decomp_error : public std::runtime_error
{
public:
decomp_error(std::string const& what);
};
} // namespace xsk::arc

View File

@ -1,4 +1,4 @@
// Copyright 2022 xensik. All rights reserved.
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
@ -8,20 +8,19 @@
namespace xsk::arc
{
/// A point in a source file.
class position
{
public:
/// Type for file name.
typedef const std::string filename_type;
/// Type for line and column numbers.
typedef int counter_type;
/// Construct a position.
filename_type *filename;
counter_type line;
counter_type column;
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {}
/// Initialization.
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{
filename = fn;
@ -29,9 +28,6 @@ public:
column = c;
}
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines(counter_type count = 1)
{
if (count)
@ -41,179 +37,131 @@ public:
}
}
/// (column related) Advance to the COUNT next columns.
void columns(counter_type count = 1)
{
column = add_(column, count, 1);
}
/** \} */
/// File name to which this position refers.
filename_type *filename;
/// Current line number.
counter_type line;
/// Current column number.
counter_type column;
private:
/// Compute max (min, lhs+rhs).
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{
return lhs + rhs < min ? min : lhs + rhs;
}
};
/// Add \a width columns, in place.
inline position& operator+=(position &res, position::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns.
inline position operator+(position res, position::counter_type width)
{
return res += width;
}
/// Subtract \a width columns, in place.
inline position& operator-=(position &res, position::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns.
inline position operator-(position res, position::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param pos a reference to the position to redirect
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const position &pos)
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const position &pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
/// Two points in a source file.
class location
{
public:
/// Type for file name.
typedef position::filename_type filename_type;
/// Type for line and column numbers.
typedef position::counter_type counter_type;
/// Construct a location from \a b to \a e.
position begin;
position end;
location(const position &b, const position &e)
: begin(b), end(e) {}
/// Construct a 0-width location in \a p.
explicit location(const position &p = position())
: begin(p), end(p) {}
/// Construct a 0-width location in \a f, \a l, \a c.
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {}
/// Initialization.
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{
begin.initialize(f, l, c);
end = begin;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step()
{
begin = end;
}
/// Extend the current location to the COUNT next columns.
void columns(counter_type count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
void lines(counter_type count = 1)
{
end.lines(count);
}
/** \} */
public:
auto print() const -> std::string
{
return *begin.filename + ":" + std::to_string(begin.line) + ":" + std::to_string(begin.column);
return fmt::format("{}:{}:{}", *begin.filename, begin.line, begin.column);
}
auto label() const -> std::string
{
return utils::string::va("loc_%X", begin.line);
return fmt::format("loc_{:X}", begin.line);
}
public:
/// Beginning of the located region.
position begin;
/// End of the located region.
position end;
};
/// Join two locations, in place.
inline location& operator+=(location &res, const location &end)
{
res.end = end.end;
return res;
}
/// Join two locations.
inline location operator+(location res, const location &end)
{
return res += end;
}
/// Add \a width columns to the end position, in place.
inline location& operator+=(location &res, location::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns to the end position.
inline location operator+(location res, location::counter_type width)
{
return res += width;
}
/// Subtract \a width columns to the end position, in place.
inline location& operator-=(location &res, location::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns to the end position.
inline location operator-(location res, location::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param loc a reference to the location to redirect
**
** Avoid duplicate information.
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const location &loc)
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const location &loc)
{
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;

View File

@ -0,0 +1,23 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
struct lookahead
{
char const* buffer_pos;
usize available;
char last_byte;
char curr_byte;
lookahead(char const* data, usize size);
auto advance() -> void;
auto ended() { return available == 0; };
};
} // namespace xsk::arc

View File

@ -0,0 +1,33 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
struct scope
{
using ptr = std::unique_ptr<scope>;
enum abort_type
{
abort_none = 0,
abort_continue = 1,
abort_break = 2,
abort_return = 3,
};
std::string end;
std::string cnt;
std::string brk;
abort_type abort;
bool is_dev;
scope() : abort(abort_type::abort_none), is_dev(false) {}
scope(std::string const& brk, std::string const& cnt) : cnt{ cnt }, brk{ brk }, abort(abort_type::abort_none), is_dev(false) {}
};
} // namespace xsk::arc

View File

@ -0,0 +1,19 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
enum class spacing : u8
{
none = 0, // no space between tokens
null = 1, // token just after new line
back = 2, // token after space
empty = 4, // token after new line + space
};
} // namespace xsk::arc

View File

@ -0,0 +1,43 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
struct token
{
enum kind : u8
{
PLUS, MINUS, STAR, DIV, MOD, BITOR, BITAND, BITEXOR, SHL, SHR,
ASSIGN, PLUSEQ, MINUSEQ, STAREQ, DIVEQ, MODEQ, BITOREQ, BITANDEQ, BITEXOREQ, SHLEQ, SHREQ,
INC, DEC, GT, LT, GE, LE, NE, EQ, OR, AND, TILDE, BANG, QMARK, COLON, SHARP, COMMA, DOT,
DOUBLEDOT, ELLIPSIS, SEMICOLON, DOUBLECOLON, LBRACKET, RBRACKET, LBRACE, RBRACE, LPAREN, RPAREN,
NAME, PATH, STRING, ISTRING, HASHSTR, INT, FLT,
DEVBEGIN, DEVEND, INLINE, INCLUDE, USINGTREE, ANIMTREE, AUTOEXEC, CODECALL, PRIVATE,
ENDON, NOTIFY, WAIT, WAITTILL, WAITTILLMATCH, WAITTILLFRAMEEND, IF, ELSE, DO, WHILE,
FOR, FOREACH, IN, SWITCH, CASE, DEFAULT, BREAK, CONTINUE, RETURN, PROFBEGIN, PROFEND,
THREAD, TRUE, FALSE, UNDEFINED, SIZE, GAME, SELF, ANIM, LEVEL,
CONST, ISDEFINED, VECTORSCALE, ANGLESTOUP, ANGLESTORIGHT, ANGLESTOFORWARD, ANGLECLAMP180,
VECTORTOANGLES, ABS, GETTIME, GETDVAR, GETDVARINT, GETDVARFLOAT, GETDVARVECTOR, GETDVARCOLORRED,
GETDVARCOLORGREEN, GETDVARCOLORBLUE, GETDVARCOLORALPHA, GETFIRSTARRAYKEY, GETNEXTARRAYKEY,
HASH, NEWLINE, EOS, DEFINED, MACROBEGIN, MACROEND, MACROARG, MACROVAOPT, MACROVAARGS, STRINGIZE, PASTE
};
kind type;
spacing space;
location pos;
std::string data;
token(kind type, spacing space, location pos) : type{ type }, space{ space }, pos{ pos }, data{} {}
token(kind type, spacing space, location pos, std::string data) : type{ type }, space{ space }, pos{ pos }, data{ std::move(data) } {}
auto to_string() -> std::string;
};
} // namespace xsk::arc

View File

@ -0,0 +1,119 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/common/asset.hpp"
#include "xsk/arc/common/assembly.hpp"
#include "xsk/arc/common/buffer.hpp"
#include "xsk/arc/common/location.hpp"
#include "xsk/arc/common/exception.hpp"
#include "xsk/arc/common/lookahead.hpp"
#include "xsk/arc/common/directive.hpp"
#include "xsk/arc/common/scope.hpp"
#include "xsk/arc/common/space.hpp"
#include "xsk/arc/common/token.hpp"
#include "xsk/arc/common/define.hpp"
#include "xsk/arc/common/ast.hpp"
namespace xsk::arc
{
enum class instance : u8
{
server,
client,
};
enum class build : u8
{
dev,
prod,
};
enum class endian : u8
{
little,
big,
};
enum class system : u8
{
pc,
ps3,
ps4,
ps5,
xb2,
xb3,
xb4,
wiiu,
};
enum class engine : u8
{
t6,
t7,
t8,
t9,
};
struct props
{
enum values : u32
{
none = 0 << 0,
v2 = 1 << 0,
v3 = 1 << 1,
header64 = 1 << 2,
header72 = 1 << 3,
headerxx = 1 << 4,
size64 = 1 << 5,
hashids = 1 << 6,
devstr = 1 << 7,
spaces = 1 << 8,
globals = 1 << 9,
refvarg = 1 << 10,
foreach = 1 << 11,
};
props(values value) : value_(value) {}
operator values() { return value_; }
operator bool() { return value_ != values::none; }
props::values operator|(props::values rhs) const { return static_cast<props::values>(value_ | rhs); }
props::values operator&(props::values rhs) const { return static_cast<props::values>(value_ & rhs); }
friend props::values operator|(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) | static_cast<std::underlying_type<props::values>::type>(rhs));
}
friend props::values operator&(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) & static_cast<std::underlying_type<props::values>::type>(rhs));
}
private:
values value_;
};
enum class switch_type
{
none,
integer,
string,
};
struct locjmp
{
std::string end;
std::string cnt;
std::string brk;
bool is_dev;
};
// fordward decl for modules ref
class context;
} // namespace xsk::arc

View File

@ -0,0 +1,153 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/common/types.hpp"
namespace xsk::arc
{
class compiler
{
context* ctx_;
assembly::ptr assembly_;
function::ptr function_;
std::vector<std::string> localfuncs_;
std::vector<std::string> stackframe_;
std::vector<scope> scopes_;
std::unordered_map<std::string, expr const*> constants_;
std::string animtree_;
u32 index_;
u32 label_idx_;
bool can_break_;
bool can_continue_;
bool developer_thread_;
public:
compiler(context* ctx);
auto compile(program const& data) -> assembly::ptr;
auto compile(std::string const& file, std::vector<u8>& data) -> assembly::ptr;
private:
auto emit_program(program const& prog) -> void;
auto emit_include(include const& inc) -> void;
auto emit_decl(decl const& dec) -> void;
auto emit_decl_usingtree(decl_usingtree const& animtree) -> void;
auto emit_decl_function(decl_function const& func) -> void;
auto emit_stmt(stmt const& stm) -> void;
auto emit_stmt_list(stmt_list const& stm) -> void;
auto emit_stmt_comp(stmt_comp const& stm) -> void;
auto emit_stmt_dev(stmt_dev const& stm) -> void;
auto emit_stmt_expr(stmt_expr const& stm) -> void;
auto emit_stmt_endon(stmt_endon const& stm) -> void;
auto emit_stmt_notify(stmt_notify const& stm) -> void;
auto emit_stmt_wait(stmt_wait const& stm) -> void;
auto emit_stmt_waittill(stmt_waittill const& stm) -> void;
auto emit_stmt_waittillmatch(stmt_waittillmatch const& stm) -> void;
auto emit_stmt_waittillframeend(stmt_waittillframeend const& stm) -> void;
auto emit_stmt_if(stmt_if const& stm) -> void;
auto emit_stmt_ifelse(stmt_ifelse const& stm) -> void;
auto emit_stmt_while(stmt_while const& stm) -> void;
auto emit_stmt_dowhile(stmt_dowhile const& stm) -> void;
auto emit_stmt_for(stmt_for const& stm) -> void;
auto emit_stmt_foreach(stmt_foreach const& stm) -> void;
auto emit_stmt_switch(stmt_switch const& stm) -> void;
auto emit_stmt_case(stmt_case const& stm) -> void;
auto emit_stmt_default(stmt_default const& stm) -> void;
auto emit_stmt_break(stmt_break const& stm) -> void;
auto emit_stmt_continue(stmt_continue const& stm) -> void;
auto emit_stmt_return(stmt_return const& stm) -> void;
auto emit_stmt_breakpoint(stmt_breakpoint const& stm) -> void;
auto emit_stmt_prof_begin(stmt_prof_begin const& stm) -> void;
auto emit_stmt_prof_end(stmt_prof_end const& stm) -> void;
auto emit_expr(expr const& exp) -> void;
auto emit_expr_const(expr_const const& exp) -> void;
auto emit_expr_assign(expr_assign const& exp) -> void;
auto emit_expr_clear(expr const& exp) -> void;
auto emit_expr_clear_local(expr_identifier const& exp) -> void;
auto emit_expr_increment(expr_increment const& exp, bool is_stmt) -> void;
auto emit_expr_decrement(expr_decrement const& exp, bool is_stmt) -> void;
auto emit_expr_ternary(expr_ternary const& exp) -> void;
auto emit_expr_binary(expr_binary const& exp) -> void;
auto emit_expr_complement(expr_complement const& exp) -> void;
auto emit_expr_negate(expr_negate const& exp) -> void;
auto emit_expr_not(expr_not const& exp) -> void;
auto emit_expr_call(expr_call const& exp, bool is_stmt) -> void;
auto emit_expr_call_pointer(expr_pointer const& exp, bool is_stmt) -> void;
auto emit_expr_call_function(expr_function const& exp, bool is_stmt) -> void;
auto emit_expr_method(expr_method const& exp, bool is_stmt) -> void;
auto emit_expr_method_pointer(expr_pointer const& exp, expr const& obj, bool is_stmt) -> void;
auto emit_expr_method_function(expr_function const& exp, expr const& obj, bool is_stmt) -> void;
auto emit_expr_parameters(expr_parameters const& exp) -> void;
auto emit_expr_arguments(expr_arguments const& exp) -> void;
auto emit_expr_isdefined(expr_isdefined const& exp) -> void;
auto emit_expr_vectorscale(expr_vectorscale const& exp) -> void;
auto emit_expr_anglestoup(expr_anglestoup const& exp) -> void;
auto emit_expr_anglestoright(expr_anglestoright const& exp) -> void;
auto emit_expr_anglestoforward(expr_anglestoforward const& exp) -> void;
auto emit_expr_angleclamp180(expr_angleclamp180 const& exp) -> void;
auto emit_expr_vectortoangles(expr_vectortoangles const& exp) -> void;
auto emit_expr_abs(expr_abs const& exp) -> void;
auto emit_expr_gettime(expr_gettime const& exp) -> void;
auto emit_expr_getdvar(expr_getdvar const& exp) -> void;
auto emit_expr_getdvarint(expr_getdvarint const& exp) -> void;
auto emit_expr_getdvarfloat(expr_getdvarfloat const& exp) -> void;
auto emit_expr_getdvarvector(expr_getdvarvector const& exp) -> void;
auto emit_expr_getdvarcolorred(expr_getdvarcolorred const& exp) -> void;
auto emit_expr_getdvarcolorgreen(expr_getdvarcolorgreen const& exp) -> void;
auto emit_expr_getdvarcolorblue(expr_getdvarcolorblue const& exp) -> void;
auto emit_expr_getdvarcoloralpha(expr_getdvarcoloralpha const& exp) -> void;
auto emit_expr_getfirstarraykey(expr_getfirstarraykey const& exp) -> void;
auto emit_expr_getnextarraykey(expr_getnextarraykey const& exp) -> void;
auto emit_expr_reference(expr_reference const& exp) -> void;
auto emit_expr_size(expr_size const& exp) -> void;
auto emit_expr_variable_ref(expr const& exp, bool set) -> void;
auto emit_expr_array_ref(expr_array const& exp, bool set) -> void;
auto emit_expr_field_ref(expr_field const& exp, bool set) -> void;
auto emit_expr_local_ref(expr_identifier const& exp, bool set) -> void;
auto emit_expr_variable(expr const& exp) -> void;
auto emit_expr_array(expr_array const& exp) -> void;
auto emit_expr_field(expr_field const& exp) -> void;
auto emit_expr_local(expr_identifier const& exp) -> void;
auto emit_expr_object(expr const& exp) -> void;
auto emit_expr_vector(expr_vector const& exp) -> void;
auto emit_expr_animation(expr_animation const& exp) -> void;
auto emit_expr_animtree(expr_animtree const& exp) -> void;
auto emit_expr_istring(expr_istring const& exp) -> void;
auto emit_expr_string(expr_string const& exp) -> void;
auto emit_expr_hash(expr_hash const& exp) -> void;
auto emit_expr_float(expr_float const& exp) -> void;
auto emit_expr_integer(expr_integer const& exp) -> void;
auto emit_expr_false(expr_false const& exp) -> void;
auto emit_expr_true(expr_true const& exp) -> void;
auto emit_opcode(opcode op) -> void;
auto emit_opcode(opcode op, std::string const& data) -> void;
auto emit_opcode(opcode op, std::vector<std::string> const& data) -> void;
auto process_function(decl_function const& func) -> void;
auto process_stmt(stmt const& stm) -> void;
auto process_stmt_list(stmt_list const& stm) -> void;
auto process_stmt_comp(stmt_comp const& stm) -> void;
auto process_stmt_dev(stmt_dev const& stm) -> void;
auto process_stmt_expr(stmt_expr const& stm) -> void;
auto process_stmt_waittill(stmt_waittill const& stm) -> void;
auto process_stmt_if(stmt_if const& stm) -> void;
auto process_stmt_ifelse(stmt_ifelse const& stm) -> void;
auto process_stmt_while(stmt_while const& stm) -> void;
auto process_stmt_dowhile(stmt_dowhile const& stm) -> void;
auto process_stmt_for(stmt_for const& stm) -> void;
auto process_stmt_foreach(stmt_foreach const& stm) -> void;
auto process_stmt_switch(stmt_switch const& stm) -> void;
auto process_expr(expr const& exp) -> void;
auto process_expr_parameters(expr_parameters const& exp) -> void;
auto variable_register(expr_identifier const& exp) -> void;
auto variable_access(expr_identifier const& exp) -> u8;
auto is_constant_condition(expr const& exp) -> bool;
auto insert_label(std::string const& label) -> void;
auto insert_label() -> std::string;
auto create_label() -> std::string;
};
} // namespace xsk::arc

View File

@ -0,0 +1,75 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/common/types.hpp"
#include "xsk/arc/source.hpp"
#include "xsk/arc/assembler.hpp"
#include "xsk/arc/disassembler.hpp"
#include "xsk/arc/compiler.hpp"
#include "xsk/arc/decompiler.hpp"
namespace xsk::arc
{
class context
{
public:
using fs_callback = std::function<std::vector<u8>(std::string const&)>;
context(props props, engine engine, endian endian, system system, u64 magic);
auto props() const -> props { return props_; }
auto build() const -> build { return build_; }
auto engine() const -> engine { return engine_; }
auto endian() const -> endian { return endian_; }
auto system() const -> system { return system_; }
auto instance() const -> instance { return instance_; }
auto magic() const -> u64 { return magic_; }
auto source() -> source& { return source_; }
auto assembler() -> assembler& { return assembler_; }
auto disassembler() -> disassembler& { return disassembler_; }
auto compiler() -> compiler& { return compiler_; }
auto decompiler() -> decompiler& { return decompiler_; }
auto init(arc::build build, fs_callback callback) -> void;
auto cleanup() -> void;
auto engine_name() const -> std::string_view;
auto opcode_size(opcode op) const -> u32;
auto opcode_id(opcode op) const -> u16;
auto opcode_name(opcode op) const -> std::string;
auto opcode_enum(std::string const& name) const -> opcode;
auto opcode_enum(u16 id) const -> opcode;
auto hash_id(std::string const& name) const -> u32;
auto hash_name(u32 id) const -> std::string;
auto make_token(std::string_view str) const -> std::string;
auto load_header(std::string const& name) -> std::tuple<std::string const*, char const*, usize>;
protected:
arc::props props_;
arc::build build_;
arc::engine engine_;
arc::endian endian_;
arc::system system_;
arc::instance instance_;
u64 magic_;
arc::source source_;
arc::assembler assembler_;
arc::disassembler disassembler_;
arc::compiler compiler_;
arc::decompiler decompiler_;
fs_callback fs_callback_;
std::unordered_map<opcode, std::string_view> opcode_map_;
std::unordered_map<std::string_view, opcode> opcode_map_rev_;
std::unordered_map<u16, opcode> code_map_;
std::unordered_map<opcode, u16> code_map_rev_;
std::unordered_map<u32, std::string_view> hash_map_;
std::unordered_map<std::string, std::vector<u8>> header_files_;
};
} // namespace xsk::arc

View File

@ -0,0 +1,106 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/common/types.hpp"
namespace xsk::arc
{
class decompiler
{
context const* ctx_;
program::ptr program_;
decl_function::ptr func_;
std::unordered_set<std::string> vars_;
std::unordered_map<u32, std::string> labels_;
std::vector<std::string> expr_labels_;
std::vector<std::string> tern_labels_;
std::vector<std::string> locals_;
std::vector<param_type> params_;
std::stack<node::ptr> stack_;
std::string namespace_;
locjmp locs_;
bool in_waittill_;
bool retbool_;
public:
decompiler(context const* ctx);
auto decompile(assembly const& data) -> program::ptr;
private:
auto decompile_function(function const& func) -> void;
auto decompile_instruction(instruction const& inst, bool last) -> void;
auto decompile_expressions(instruction const& inst) -> void;
auto decompile_statements(stmt_list& stm) -> void;
auto decompile_infinites(stmt_list& stm) -> void;
auto decompile_loops(stmt_list& stm) -> void;
auto decompile_switches(stmt_list& stm) -> void;
auto decompile_ifelses(stmt_list& stm) -> void;
auto decompile_aborts(stmt_list& stm) -> void;
auto decompile_devblocks(stmt_list& stm) -> void;
auto decompile_if(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_ifelse(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_inf(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_loop(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_while(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_dowhile(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_for(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_foreach(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_switch(stmt_list& stm, usize begin, usize end) -> void;
auto find_location_reference(stmt_list const& stm, usize begin, usize end, std::string const& loc) -> bool;
auto find_location_index(stmt_list const& stm, std::string const& loc) -> usize;
auto last_location_index(stmt_list const& stm, usize index) -> bool;
auto lvalues_match(stmt_expr const& stm1, stmt_expr const& stm2) -> bool;
auto resolve_label(std::string const& name) -> u32;
auto process_function(decl_function& func) -> void;
auto process_stmt(stmt& stm) -> void;
auto process_stmt_list(stmt_list& stm) -> void;
auto process_stmt_comp(stmt_comp& stm) -> void;
auto process_stmt_dev(stmt_dev& stm) -> void;
auto process_stmt_expr(stmt_expr& stm) -> void;
auto process_stmt_endon(stmt_endon& stm) -> void;
auto process_stmt_notify(stmt_notify& stm) -> void;
auto process_stmt_wait(stmt_wait& stm) -> void;
auto process_stmt_waittill(stmt_waittill& stm) -> void;
auto process_stmt_waittillmatch(stmt_waittillmatch& stm) -> void;
auto process_stmt_waitrealtime(stmt_waitrealtime& stm) -> void;
auto process_stmt_if(stmt_if& stm) -> void;
auto process_stmt_ifelse(stmt_ifelse& stm) -> void;
auto process_stmt_while(stmt_while& stm) -> void;
auto process_stmt_dowhile(stmt_dowhile& stm) -> void;
auto process_stmt_for(stmt_for& stm) -> void;
auto process_stmt_foreach(stmt_foreach& stm) -> void;
auto process_stmt_switch(stmt_switch& stm) -> void;
auto process_stmt_break(stmt_break& stm) -> void;
auto process_stmt_continue(stmt_continue& stm) -> void;
auto process_stmt_return(stmt_return& stm) -> void;
auto process_expr(expr::ptr& exp) -> void;
auto process_expr_increment(expr_increment& exp) -> void;
auto process_expr_decrement(expr_decrement& exp) -> void;
auto process_expr_assign(expr_assign::ptr& exp) -> void;
auto process_expr_ternary(expr_ternary& exp) -> void;
auto process_expr_binary(expr_binary& exp) -> void;
auto process_expr_complement(expr_complement& exp) -> void;
auto process_expr_not(expr_not& exp) -> void;
auto process_expr_call(expr_call& exp) -> void;
auto process_expr_method(expr_method& exp) -> void;
auto process_expr_call_member(expr_member& exp) -> void;
auto process_expr_call_pointer(expr_pointer& exp) -> void;
auto process_expr_call_function(expr_function& exp) -> void;
auto process_expr_method_pointer(expr_pointer& exp, expr::ptr& obj) -> void;
auto process_expr_method_function(expr_function& exp, expr::ptr& obj) -> void;
auto process_expr_parameters(expr_parameters& exp) -> void;
auto process_expr_arguments(expr_arguments& exp) -> void;
auto process_expr_reference(expr_reference& exp) -> void;
auto process_expr_array(expr_array& exp) -> void;
auto process_expr_field(expr_field& exp) -> void;
auto process_expr_size(expr_size& exp) -> void;
auto process_expr_vector(expr_vector& exp) -> void;
auto process_expr_identifier(expr_identifier& exp) -> void;
};
} // namespace xsk::arc

View File

@ -0,0 +1,44 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/utils/reader.hpp"
#include "xsk/arc/common/types.hpp"
namespace xsk::arc
{
class disassembler
{
context const* ctx_;
function::ptr func_;
assembly::ptr assembly_;
utils::reader script_;
std::map<u32, import_ref::ptr> import_refs_;
std::map<u32, string_ref::ptr> string_refs_;
std::map<u32, animtree_ref::ptr> anim_refs_;
public:
disassembler(context const* ctx);
auto disassemble(buffer const& data) -> assembly::ptr;
auto disassemble(std::vector<u8> const& data) -> assembly::ptr;
auto disassemble(u8 const* data, usize data_size) -> assembly::ptr;
private:
auto disassemble_function(function& func) -> void;
auto disassemble_instruction(instruction& inst) -> void;
auto disassemble_name(instruction& inst) -> void;
auto disassemble_params(instruction& inst) -> void;
auto disassemble_import(instruction& inst) -> void;
auto disassemble_string(instruction& inst) -> void;
auto disassemble_animtree(instruction& inst) -> void;
auto disassemble_animation(instruction& inst) -> void;
auto disassemble_jump(instruction& inst) -> void;
auto disassemble_switch(instruction& inst) -> void;
auto disassemble_end_switch(instruction& inst) -> void;
};
} // namespace xsk::arc

View File

@ -0,0 +1,17 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t6
{
constexpr usize code_count = 125;
constexpr usize hash_count = 3331;
} // namespace xsk::arc::t6

View File

@ -0,0 +1,21 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/engine/t6.hpp"
namespace xsk::arc::t6::pc
{
constexpr u64 header_magic = 0x06000A0D43534780;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t6::pc

View File

@ -0,0 +1,21 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/engine/t6.hpp"
namespace xsk::arc::t6::ps3
{
constexpr u64 header_magic = 0x804753430D0A0006;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t6::ps3

View File

@ -0,0 +1,21 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/engine/t6.hpp"
namespace xsk::arc::t6::wiiu
{
constexpr u64 header_magic = 0x804753430D0A0006;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t6::wiiu

View File

@ -0,0 +1,21 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/engine/t6.hpp"
namespace xsk::arc::t6::xb2
{
constexpr u64 header_magic = 0x804753430D0A0006;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t6::xb2

View File

@ -0,0 +1,24 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t7
{
constexpr usize code_count = 16384;
constexpr usize hash_count = 178806;
constexpr u64 header_magic = 0x1C000A0D43534780;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t7

View File

@ -0,0 +1,24 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t8
{
constexpr usize code_count = 0;
constexpr usize hash_count = 0;
constexpr u64 header_magic = 0x36000A0D43534780;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t8

View File

@ -0,0 +1,24 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t9
{
constexpr usize code_count = 0;
constexpr usize hash_count = 0;
constexpr u64 header_magic = 0x38000A0D43534780;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t9

33
include/xsk/arc/lexer.hpp Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/common/types.hpp"
namespace xsk::arc
{
class lexer
{
context const* ctx_;
lookahead reader_;
location loc_;
usize buflen_;
spacing spacing_;
bool indev_;
std::array<char, 0x1000> buffer_;
public:
lexer(context const* ctx, std::string const& name, char const* data, usize size);
auto lex() -> token;
private:
auto push(char c) -> void;
auto advance() -> void;
auto linewrap() -> void;
};
} // namespace xsk::arc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/common/types.hpp"
#include "xsk/arc/lexer.hpp"
namespace xsk::arc
{
class preprocessor
{
context* ctx_;
std::stack<lexer> lexer_;
std::stack<directive> indents_;
std::vector<std::string> includes_;
std::unordered_map<std::string_view, directive::kind> directives_;
std::unordered_map<std::string, define> defines_;
std::set<std::string> reject_;
std::deque<token> tokens_;
std::vector<token> expr_;
std::string date_;
std::string time_;
usize curr_expr_;
u32 expand_;
u32 skip_;
public:
preprocessor(context* ctx, std::string const& name, char const* data, usize size);
auto process() -> token;
auto push_header(std::string const& file) -> void;
auto pop_header() -> void;
auto ban_header(location const& loc) -> void;
private:
auto skip_line() -> void;
auto next_token() -> token;
auto read_token() -> token;
auto read_directive(token& tok) -> void;
auto read_directive_if(token& tok) -> void;
auto read_directive_ifdef(token& tok) -> void;
auto read_directive_ifndef(token& tok) -> void;
auto read_directive_elif(token& tok) -> void;
auto read_directive_elifdef(token& tok) -> void;
auto read_directive_elifndef(token& tok) -> void;
auto read_directive_else(token& tok) -> void;
auto read_directive_endif(token& tok) -> void;
auto read_directive_define(token& tok) -> void;
auto read_directive_undef(token& tok) -> void;
auto read_directive_pragma(token& tok) -> void;
auto read_directive_warning(token& tok) -> void;
auto read_directive_error(token& tok) -> void;
auto read_directive_line(token& tok) -> void;
auto read_directive_include(token& hash, token& name) -> void;
auto read_directive_inline(token& hash, token& name) -> void;
auto read_directive_usingtree(token& hash, token& name) -> void;
auto read_hashtoken(token& hash) -> void;
auto read_hashtoken_animtree(token& hash, token& name) -> void;
auto read_hashtoken_hashstr(token& hash, token& name) -> void;
auto expand(token& tok, define& def) -> void;
auto expand_params(token& tok, define& def) -> std::vector<std::vector<token>>;
auto expect(token& tok, token::kind expected, spacing space = spacing::none) -> void;
auto evaluate() -> bool;
auto eval_next() -> token&;
auto eval_peek() -> token&;
auto eval_prev() -> token&;
auto eval_atend() -> bool;
auto eval_check(token::kind type) -> bool;
auto eval_match(token::kind type) -> bool;
auto eval_consume(token::kind type, std::string_view msg);
auto eval_expr() -> i32;
auto eval_expr_or() -> i32;
auto eval_expr_and() -> i32;
auto eval_expr_bwor() -> i32;
auto eval_expr_bwexor() -> i32;
auto eval_expr_bwand() -> i32;
auto eval_expr_eq() -> i32;
auto eval_expr_lge() -> i32;
auto eval_expr_shift() -> i32;
auto eval_expr_add() -> i32;
auto eval_expr_factor() -> i32;
auto eval_expr_unary() -> i32;
auto eval_expr_primary() -> i32;
auto get_local_time(std::tm& ltime) -> void;
auto get_date_define(std::tm* time_p) -> void;
auto get_time_define(std::tm* time_p) -> void;
};
} // namespace xsk::arc

145
include/xsk/arc/source.hpp Normal file
View File

@ -0,0 +1,145 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/arc/common/types.hpp"
namespace xsk::arc
{
class source
{
context* ctx_;
std::vector<u8> buf_;
u32 indent_;
public:
source(context* ctx);
auto parse_assembly(buffer const& data) -> assembly::ptr;
auto parse_assembly(std::vector<u8> const& data) -> assembly::ptr;
auto parse_assembly(u8 const* data, usize size) -> assembly::ptr;
auto parse_program(std::string const& name, buffer const& data) -> program::ptr;
auto parse_program(std::string const& name, std::vector<u8> const& data) -> program::ptr;
auto parse_program(std::string const& name, u8 const* data, usize size) -> program::ptr;
auto dump(assembly const& data) -> std::vector<u8>;
auto dump(program const& data) -> std::vector<u8>;
private:
auto dump_assembly(assembly const& data) -> void;
auto dump_function(function const& func) -> void;
auto dump_instruction(instruction const& inst) -> void;
auto dump_program(program const& data) -> void;
auto dump_include(include const& inc) -> void;
auto dump_decl(decl const& dec) -> void;
auto dump_decl_dev_begin(decl_dev_begin const& dec) -> void;
auto dump_decl_dev_end(decl_dev_end const& dec) -> void;
auto dump_decl_namespace(decl_namespace const& dec) -> void;
auto dump_decl_usingtree(decl_usingtree const& dec) -> void;
auto dump_decl_function(decl_function const& dec) -> void;
auto dump_decl_empty(decl_empty const& dec) -> void;
auto dump_stmt(stmt const& stm) -> void;
auto dump_stmt_empty(stmt_empty const& stm) -> void;
auto dump_stmt_list(stmt_list const& stm) -> void;
auto dump_stmt_comp(stmt_comp const& stm) -> void;
auto dump_stmt_dev(stmt_dev const& stm) -> void;
auto dump_stmt_expr(stmt_expr const& stm) -> void;
auto dump_stmt_endon(stmt_endon const& stm) -> void;
auto dump_stmt_notify(stmt_notify const& stm) -> void;
auto dump_stmt_wait(stmt_wait const& stm) -> void;
auto dump_stmt_waittill(stmt_waittill const& stm) -> void;
auto dump_stmt_waittillmatch(stmt_waittillmatch const& stm) -> void;
auto dump_stmt_waittillframeend(stmt_waittillframeend const& stm) -> void;
auto dump_stmt_waitrealtime(stmt_waitrealtime const& stm) -> void;
auto dump_stmt_if(stmt_if const& stm) -> void;
auto dump_stmt_ifelse(stmt_ifelse const& stm) -> void;
auto dump_stmt_while(stmt_while const& stm) -> void;
auto dump_stmt_dowhile(stmt_dowhile const& stm) -> void;
auto dump_stmt_for(stmt_for const& stm) -> void;
auto dump_stmt_foreach(stmt_foreach const& stm) -> void;
auto dump_stmt_switch(stmt_switch const& stm) -> void;
auto dump_stmt_case(stmt_case const& stm) -> void;
auto dump_stmt_default(stmt_default const& stm) -> void;
auto dump_stmt_break(stmt_break const& stm) -> void;
auto dump_stmt_continue(stmt_continue const& stm) -> void;
auto dump_stmt_return(stmt_return const& stm) -> void;
auto dump_stmt_breakpoint(stmt_breakpoint const& stm) -> void;
auto dump_stmt_prof_begin(stmt_prof_begin const& stm) -> void;
auto dump_stmt_prof_end(stmt_prof_end const& stm) -> void;
auto dump_stmt_jmp(stmt_jmp const& stm) -> void;
auto dump_stmt_jmp_back(stmt_jmp_back const& stm) -> void;
auto dump_stmt_jmp_cond(stmt_jmp_cond const& stm) -> void;
auto dump_stmt_jmp_true(stmt_jmp_true const& stm) -> void;
auto dump_stmt_jmp_false(stmt_jmp_false const& stm) -> void;
auto dump_stmt_jmp_switch(stmt_jmp_switch const& stm) -> void;
auto dump_stmt_jmp_endswitch(stmt_jmp_endswitch const& stm) -> void;
auto dump_stmt_jmp_dev(stmt_jmp_dev const& stm) -> void;
auto dump_expr(expr const& exp) -> void;
auto dump_expr_increment(expr_increment const& exp) -> void;
auto dump_expr_decrement(expr_decrement const& exp) -> void;
auto dump_expr_assign(expr_assign const& exp) -> void;
auto dump_expr_const(expr_const const& exp) -> void;
auto dump_expr_ternary(expr_ternary const& exp) -> void;
auto dump_expr_binary(expr_binary const& exp) -> void;
auto dump_expr_not(expr_not const& exp) -> void;
auto dump_expr_negate(expr_negate const& exp) -> void;
auto dump_expr_complement(expr_complement const& exp) -> void;
auto dump_expr_new(expr_new const& exp) -> void;
auto dump_expr_call(expr_call const& exp) -> void;
auto dump_expr_method(expr_method const& exp) -> void;
auto dump_call(call const& exp) -> void;
auto dump_expr_function(expr_function const& exp) -> void;
auto dump_expr_pointer(expr_pointer const& exp) -> void;
auto dump_expr_member(expr_member const& exp) -> void;
auto dump_expr_parameters(expr_parameters const& exp) -> void;
auto dump_expr_arguments(expr_arguments const& exp) -> void;
auto dump_expr_isdefined(expr_isdefined const& exp) -> void;
auto dump_expr_vectorscale(expr_vectorscale const& exp) -> void;
auto dump_expr_anglestoup(expr_anglestoup const& exp) -> void;
auto dump_expr_anglestoright(expr_anglestoright const& exp) -> void;
auto dump_expr_anglestoforward(expr_anglestoforward const& exp) -> void;
auto dump_expr_angleclamp180(expr_angleclamp180 const& exp) -> void;
auto dump_expr_vectortoangles(expr_vectortoangles const& exp) -> void;
auto dump_expr_abs(expr_abs const& exp) -> void;
auto dump_expr_gettime(expr_gettime const& exp) -> void;
auto dump_expr_getdvar(expr_getdvar const& exp) -> void;
auto dump_expr_getdvarint(expr_getdvarint const& exp) -> void;
auto dump_expr_getdvarfloat(expr_getdvarfloat const& exp) -> void;
auto dump_expr_getdvarvector(expr_getdvarvector const& exp) -> void;
auto dump_expr_getdvarcolorred(expr_getdvarcolorred const& exp) -> void;
auto dump_expr_getdvarcolorgreen(expr_getdvarcolorgreen const& exp) -> void;
auto dump_expr_getdvarcolorblue(expr_getdvarcolorblue const& exp) -> void;
auto dump_expr_getdvarcoloralpha(expr_getdvarcoloralpha const& exp) -> void;
auto dump_expr_getfirstarraykey(expr_getfirstarraykey const& exp) -> void;
auto dump_expr_getnextarraykey(expr_getnextarraykey const& exp) -> void;
auto dump_expr_reference(expr_reference const& exp) -> void;
auto dump_expr_array(expr_array const& exp) -> void;
auto dump_expr_field(expr_field const& exp) -> void;
auto dump_expr_size(expr_size const& exp) -> void;
auto dump_expr_paren(expr_paren const& exp) -> void;
auto dump_expr_ellipsis(expr_ellipsis const& exp) -> void;
auto dump_expr_empty_array(expr_empty_array const& exp) -> void;
auto dump_expr_undefined(expr_undefined const& exp) -> void;
auto dump_expr_game(expr_game const& exp) -> void;
auto dump_expr_self(expr_self const& exp) -> void;
auto dump_expr_anim(expr_anim const& exp) -> void;
auto dump_expr_level(expr_level const& exp) -> void;
auto dump_expr_world(expr_world const& exp) -> void;
auto dump_expr_classes(expr_classes const& exp) -> void;
auto dump_expr_animation(expr_animation const& exp) -> void;
auto dump_expr_animtree(expr_animtree const& exp) -> void;
auto dump_expr_identifier(expr_identifier const& exp) -> void;
auto dump_expr_path(expr_path const& exp) -> void;
auto dump_expr_istring(expr_istring const& exp) -> void;
auto dump_expr_string(expr_string const& exp) -> void;
auto dump_expr_hash(expr_hash const& exp) -> void;
auto dump_expr_vector(expr_vector const& exp) -> void;
auto dump_expr_float(expr_float const& exp) -> void;
auto dump_expr_integer(expr_integer const& exp) -> void;
auto dump_expr_false(expr_false const& exp) -> void;
auto dump_expr_true(expr_true const& exp) -> void;
};
} // namespace xsk::arc

View File

@ -0,0 +1,43 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/utils/writer.hpp"
#include "xsk/gsc/common/types.hpp"
namespace xsk::gsc
{
class assembler
{
context const* ctx_;
function const* func_;
assembly const* assembly_;
utils::writer script_;
utils::writer stack_;
public:
assembler(context const* ctx);
auto assemble(assembly const& data) -> std::pair<buffer, buffer>;
private:
auto assemble_function(function const& func) -> void;
auto assemble_instruction(instruction const& inst) -> void;
auto assemble_builtin_call(instruction const& inst, bool method, bool args) -> void;
auto assemble_local_call(instruction const& inst, bool thread) -> void;
auto assemble_far_call(instruction const& inst, bool thread) -> void;
auto assemble_switch(instruction const& inst) -> void;
auto assemble_end_switch(instruction const& inst) -> void;
auto assemble_field_variable(instruction const& inst) -> void;
auto assemble_formal_params(instruction const& inst) -> void;
auto assemble_jump(instruction const& inst, bool expr, bool back) -> void;
auto assemble_offset(i32 offs) -> void;
auto resolve_function(std::string const& name) -> i32;
auto resolve_label(std::string const& name) -> i32;
auto encrypt_string(std::string const& str) -> std::string;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,267 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
constexpr usize opcode_count = 205;
enum class opcode : u8
{
vm_invalid,
OP_CastFieldObject,
OP_SetLocalVariableFieldCached,
OP_plus,
OP_RemoveLocalVariables,
OP_EvalSelfFieldVariableRef,
OP_ScriptFarMethodChildThreadCall,
OP_GetGameRef,
OP_EvalAnimFieldVariable,
OP_EvalLevelFieldVariableRef,
OP_GetThisthread,
OP_greater,
OP_waittillmatch,
OP_shift_right,
OP_dec,
OP_JumpOnTrue,
OP_bit_or,
OP_equality,
OP_ClearLocalVariableFieldCached0,
OP_notify,
OP_GetVector,
OP_ScriptMethodChildThreadCallPointer,
OP_PreScriptCall,
OP_GetByte,
OP_ScriptFarThreadCall,
OP_SetSelfFieldVariableField,
OP_JumpOnFalseExpr,
OP_GetUndefined,
OP_jumpback,
OP_JumpOnTrueExpr,
OP_CallBuiltin0,
OP_CallBuiltin1,
OP_CallBuiltin2,
OP_CallBuiltin3,
OP_CallBuiltin4,
OP_CallBuiltin5,
OP_CallBuiltin,
OP_SetLocalVariableFieldCached0,
OP_ClearFieldVariable,
OP_GetLevel,
OP_size,
OP_SafeSetWaittillVariableFieldCached,
OP_ScriptLocalMethodThreadCall,
OP_AddArray,
OP_endon,
OP_EvalFieldVariable,
OP_shift_left,
OP_EvalLocalArrayRefCached0,
OP_Return,
OP_CreateLocalVariable,
OP_SafeSetVariableFieldCached0,
OP_GetBuiltinFunction,
OP_ScriptLocalMethodCall,
OP_CallBuiltinMethodPointer,
OP_ScriptLocalChildThreadCall,
OP_GetSelfObject,
OP_GetGame,
OP_SetLevelFieldVariableField,
OP_EvalArray,
OP_GetSelf,
OP_End,
OP_EvalSelfFieldVariable,
OP_less_equal,
OP_EvalLocalVariableCached0,
OP_EvalLocalVariableCached1,
OP_EvalLocalVariableCached2,
OP_EvalLocalVariableCached3,
OP_EvalLocalVariableCached4,
OP_EvalLocalVariableCached5,
OP_EvalLocalVariableCached,
OP_EvalNewLocalArrayRefCached0,
OP_ScriptChildThreadCallPointer,
OP_EvalLocalVariableObjectCached,
OP_ScriptLocalThreadCall,
OP_GetInteger,
OP_ScriptMethodCallPointer,
OP_checkclearparams,
OP_SetAnimFieldVariableField,
OP_waittillmatch2,
OP_minus,
OP_ScriptLocalFunctionCall2,
OP_GetNegUnsignedShort,
OP_GetNegByte,
OP_SafeCreateVariableFieldCached,
OP_greater_equal,
OP_vector,
OP_GetBuiltinMethod,
OP_endswitch,
OP_ClearArray,
OP_DecTop,
OP_CastBool,
OP_EvalArrayRef,
OP_SetNewLocalVariableFieldCached0,
OP_GetZero,
OP_wait,
OP_waittill,
OP_GetIString,
OP_ScriptFarFunctionCall,
OP_GetAnimObject,
OP_GetAnimTree,
OP_EvalLocalArrayCached,
OP_mod,
OP_ScriptFarMethodThreadCall,
OP_GetUnsignedShort,
OP_clearparams,
OP_ScriptMethodThreadCallPointer,
OP_ScriptFunctionCallPointer,
OP_EmptyArray,
OP_SafeSetVariableFieldCached,
OP_ClearVariableField,
OP_EvalFieldVariableRef,
OP_ScriptLocalMethodChildThreadCall,
OP_EvalNewLocalVariableRefCached0,
OP_GetFloat,
OP_EvalLocalVariableRefCached,
OP_JumpOnFalse,
OP_BoolComplement,
OP_ScriptThreadCallPointer,
OP_ScriptFarFunctionCall2,
OP_less,
OP_BoolNot,
OP_waittillFrameEnd,
OP_waitframe,
OP_GetString,
OP_EvalLevelFieldVariable,
OP_GetLevelObject,
OP_inc,
OP_CallBuiltinMethod0,
OP_CallBuiltinMethod1,
OP_CallBuiltinMethod2,
OP_CallBuiltinMethod3,
OP_CallBuiltinMethod4,
OP_CallBuiltinMethod5,
OP_CallBuiltinMethod,
OP_GetAnim,
OP_switch,
OP_SetVariableField,
OP_divide,
OP_GetLocalFunction,
OP_ScriptFarChildThreadCall,
OP_multiply,
OP_ClearLocalVariableFieldCached,
OP_EvalAnimFieldVariableRef,
OP_EvalLocalArrayRefCached,
OP_EvalLocalVariableRefCached0,
OP_bit_and,
OP_GetAnimation,
OP_GetFarFunction,
OP_CallBuiltinPointer,
OP_jump,
OP_voidCodepos,
OP_ScriptFarMethodCall,
OP_inequality,
OP_ScriptLocalFunctionCall,
OP_bit_ex_or,
OP_NOP,
OP_abort,
OP_object,
OP_thread_object,
OP_EvalLocalVariable,
OP_EvalLocalVariableRef,
OP_prof_begin,
OP_prof_end,
OP_breakpoint,
OP_assignmentBreakpoint,
OP_manualAndAssignmentBreakpoint,
OP_BoolNotAfterAnd,
OP_FormalParams,
OP_IsDefined,
OP_IsTrue,
OP_NativeGetLocalFunction,
OP_NativeLocalFunctionCall,
OP_NativeLocalFunctionCall2,
OP_NativeLocalMethodCall,
OP_NativeLocalFunctionThreadCall,
OP_NativeLocalMethodThreadCall,
OP_NativeLocalFunctionChildThreadCall,
OP_NativeLocalMethodChildThreadCall,
OP_NativeGetFarFunction,
OP_NativeFarFunctionCall,
OP_NativeFarFunctionCall2,
OP_NativeFarMethodCall,
OP_NativeFarFunctionThreadCall,
OP_NativeFarMethodThreadCall,
OP_NativeFarFunctionChildThreadCall,
OP_NativeFarMethodChildThreadCall,
OP_EvalNewLocalArrayRefCached0_Precompiled,
OP_SetNewLocalVariableFieldCached0_Precompiled,
OP_CreateLocalVariable_Precompiled,
OP_SafeCreateVariableFieldCached_Precompiled,
OP_FormalParams_Precompiled,
OP_GetStatHash,
OP_GetUnkxHash,
OP_GetEnumHash,
OP_GetDvarHash,
OP_GetUnsignedInt,
OP_GetNegUnsignedInt,
OP_GetInteger64,
OP_iw9_139,
OP_iw9_140,
OP_iw9_141,
OP_iw9_142,
OP_iw9_143,
OP_iw9_144,
OP_iw9_166,
OP_count,
};
struct instruction
{
using ptr = std::unique_ptr<instruction>;
u32 index;
u32 size;
opcode opcode;
std::vector<std::string> data;
static auto make() -> instruction::ptr
{
return std::unique_ptr<instruction>(new instruction);
}
};
struct function
{
using ptr = std::unique_ptr<function>;
u32 index;
u32 size;
u32 id;
std::string name;
std::vector<instruction::ptr> instructions;
std::unordered_map<u32, std::string> labels;
static auto make() -> function::ptr
{
return std::unique_ptr<function>(new function);
}
};
struct assembly
{
using ptr = std::unique_ptr<assembly>;
std::vector<function::ptr> functions;
static auto make() -> assembly::ptr
{
return std::unique_ptr<assembly>(new assembly);
}
};
} // namespace xsk::gsc

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct asset
{
using ptr = std::unique_ptr<asset>;
std::string name;
u32 compressedLen;
u32 len;
u32 bytecodeLen;
std::vector<u8> buffer;
std::vector<u8> bytecode;
auto serialize() -> std::vector<u8>;
auto deserialize(std::vector<u8> const& data) -> void;
};
} // namespace xsk::gsc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct buffer
{
u8 const* data;
usize const size;
buffer() : data{ nullptr }, size{ 0 } {}
buffer(u8 const* data, usize size) : data{ data }, size{ size } {}
};
} // namespace xsk::gsc

View File

@ -0,0 +1,21 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct define
{
enum kind : u8 { PLAIN, BUILTIN, OBJECT, FUNCTION };
kind type;
// bool vararg;
std::vector<token> args;
std::vector<token> exp;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,19 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct directive
{
enum kind : u8 { IF, IFDEF, IFNDEF, ELIF, ELIFDEF, ELIFNDEF, ELSE, ENDIF, DEFINE, UNDEF, PRAGMA, WARNING, ERROR, LINE, INCLUDE, INLINE, INSERT, USINGTREE };
kind type;
bool skip;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,47 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
class error : public std::runtime_error
{
public:
error(std::string const& what);
};
class asm_error : public std::runtime_error
{
public:
asm_error(std::string const& what);
};
class disasm_error : public std::runtime_error
{
public:
disasm_error(std::string const& what);
};
class ppr_error : public std::runtime_error
{
public:
ppr_error(location const& loc, std::string const& what);
};
class comp_error : public std::runtime_error
{
public:
comp_error(location const& loc, std::string const& what);
};
class decomp_error : public std::runtime_error
{
public:
decomp_error(std::string const& what);
};
} // namespace xsk::gsc

View File

@ -1,4 +1,4 @@
// Copyright 2022 xensik. All rights reserved.
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
@ -8,20 +8,19 @@
namespace xsk::gsc
{
/// A point in a source file.
class position
{
public:
/// Type for file name.
typedef const std::string filename_type;
/// Type for line and column numbers.
typedef int counter_type;
/// Construct a position.
filename_type *filename;
counter_type line;
counter_type column;
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {}
/// Initialization.
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{
filename = fn;
@ -29,9 +28,6 @@ public:
column = c;
}
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines(counter_type count = 1)
{
if (count)
@ -41,179 +37,131 @@ public:
}
}
/// (column related) Advance to the COUNT next columns.
void columns(counter_type count = 1)
{
column = add_(column, count, 1);
}
/** \} */
/// File name to which this position refers.
filename_type *filename;
/// Current line number.
counter_type line;
/// Current column number.
counter_type column;
private:
/// Compute max (min, lhs+rhs).
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{
return lhs + rhs < min ? min : lhs + rhs;
}
};
/// Add \a width columns, in place.
inline position& operator+=(position &res, position::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns.
inline position operator+(position res, position::counter_type width)
{
return res += width;
}
/// Subtract \a width columns, in place.
inline position& operator-=(position &res, position::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns.
inline position operator-(position res, position::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param pos a reference to the position to redirect
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const position &pos)
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const position &pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
/// Two points in a source file.
class location
{
public:
/// Type for file name.
typedef position::filename_type filename_type;
/// Type for line and column numbers.
typedef position::counter_type counter_type;
/// Construct a location from \a b to \a e.
position begin;
position end;
location(const position &b, const position &e)
: begin(b), end(e) {}
/// Construct a 0-width location in \a p.
explicit location(const position &p = position())
: begin(p), end(p) {}
/// Construct a 0-width location in \a f, \a l, \a c.
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {}
/// Initialization.
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{
begin.initialize(f, l, c);
end = begin;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step()
{
begin = end;
}
/// Extend the current location to the COUNT next columns.
void columns(counter_type count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
void lines(counter_type count = 1)
{
end.lines(count);
}
/** \} */
public:
auto print() const -> std::string
{
return *begin.filename + ":" + std::to_string(begin.line) + ":" + std::to_string(begin.column);
return fmt::format("{}:{}:{}", *begin.filename, begin.line, begin.column);
}
auto label() const -> std::string
{
return utils::string::va("loc_%X", begin.line);
return fmt::format("loc_{:X}", begin.line);
}
public:
/// Beginning of the located region.
position begin;
/// End of the located region.
position end;
};
/// Join two locations, in place.
inline location& operator+=(location &res, const location &end)
{
res.end = end.end;
return res;
}
/// Join two locations.
inline location operator+(location res, const location &end)
{
return res += end;
}
/// Add \a width columns to the end position, in place.
inline location& operator+=(location &res, location::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns to the end position.
inline location operator+(location res, location::counter_type width)
{
return res += width;
}
/// Subtract \a width columns to the end position, in place.
inline location& operator-=(location &res, location::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns to the end position.
inline location operator-(location res, location::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param loc a reference to the location to redirect
**
** Avoid duplicate information.
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const location &loc)
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const location &loc)
{
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;

View File

@ -0,0 +1,23 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct lookahead
{
char const* buffer_pos;
usize available;
char last_byte;
char curr_byte;
lookahead(char const* data, usize size);
auto advance() -> void;
auto ended() { return available == 0; };
};
} // namespace xsk::gsc

View File

@ -0,0 +1,64 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct locjmp
{
std::string end;
std::string cnt;
std::string brk;
bool last;
};
struct scope
{
using ptr = std::unique_ptr<scope>;
enum abort_type
{
abort_none = 0,
abort_continue = 1,
abort_break = 2,
abort_return = 3,
};
struct var
{
std::string name;
u8 create;
bool init;
};
abort_type abort;
std::string loc_end;
std::string loc_cont;
std::string loc_break;
u32 create_count;
u32 public_count;
std::vector<var> vars;
bool is_last;
scope();
auto transfer_dec(scope::ptr const& child) -> void;
auto transfer(scope::ptr const& child) -> void;
auto copy(scope::ptr const& child) -> void;
auto append_dec(scope::ptr const& child) -> void;
auto append(std::vector<scope*> const& childs) -> void;
auto merge(std::vector<scope*> const& childs) -> void;
auto init(scope::ptr const& child) -> void;
auto init(std::vector<scope*> const& childs) -> void;
auto find(usize start, std::string const& name) -> i32;
};
inline auto make_scope() -> std::unique_ptr<scope>
{
return std::unique_ptr<scope>(new scope);
}
} // namespace xsk::gsc

View File

@ -0,0 +1,19 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
enum class spacing : u8
{
none = 0, // no space between tokens
null = 1, // token just after new line
back = 2, // token after space
empty = 4, // token after new line + space
};
} // namespace xsk::gsc

View File

@ -0,0 +1,41 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct token
{
enum kind : u8
{
PLUS, MINUS, STAR, DIV, MOD, BITOR, BITAND, BITEXOR, SHL, SHR,
ASSIGN, PLUSEQ, MINUSEQ, STAREQ, DIVEQ, MODEQ, BITOREQ, BITANDEQ, BITEXOREQ, SHLEQ, SHREQ,
INC, DEC, GT, LT, GE, LE, NE, EQ, OR, AND, TILDE, BANG, QMARK, COLON, SHARP, COMMA, DOT,
DOUBLEDOT, ELLIPSIS, SEMICOLON, DOUBLECOLON, LBRACKET, RBRACKET, LBRACE, RBRACE, LPAREN, RPAREN,
NAME, PATH, STRING, ISTRING, INT, FLT,
DEVBEGIN, DEVEND, INLINE, INCLUDE, USINGTREE, ANIMTREE, ENDON, NOTIFY, WAIT,
WAITTILL, WAITTILLMATCH, WAITTILLFRAMEEND, WAITFRAME, IF, ELSE, DO, WHILE,
FOR, FOREACH, IN, SWITCH, CASE, DEFAULT, BREAK, CONTINUE, RETURN, BREAKPOINT,
PROFBEGIN, PROFEND, ASSERT, ASSERTEX, ASSERTMSG, THREAD, CHILDTHREAD, THISTHREAD,
CALL, TRUE, FALSE, UNDEFINED, SIZE, GAME, SELF, ANIM, LEVEL, ISDEFINED, ISTRUE,
HASH, NEWLINE, EOS, DEFINED, MACROBEGIN, MACROEND, MACROARG, MACROVAOPT, MACROVAARGS, STRINGIZE, PASTE
};
kind type;
spacing space;
location pos;
std::string data;
token(kind type, spacing space, location pos) : type{ type }, space{ space }, pos{ pos }, data{} {}
token(kind type, spacing space, location pos, std::string data) : type{ type }, space{ space }, pos{ pos }, data{ std::move(data) } {}
auto to_string() -> std::string;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,111 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/gsc/common/asset.hpp"
#include "xsk/gsc/common/scope.hpp"
#include "xsk/gsc/common/buffer.hpp"
#include "xsk/gsc/common/assembly.hpp"
#include "xsk/gsc/common/location.hpp"
#include "xsk/gsc/common/exception.hpp"
#include "xsk/gsc/common/lookahead.hpp"
#include "xsk/gsc/common/directive.hpp"
#include "xsk/gsc/common/space.hpp"
#include "xsk/gsc/common/token.hpp"
#include "xsk/gsc/common/define.hpp"
#include "xsk/gsc/common/ast.hpp"
namespace xsk::gsc
{
enum class instance : u8
{
server,
client,
};
enum class build : u8
{
dev,
prod,
};
enum class endian : u8
{
little,
big,
};
enum class system : u8
{
pc,
ps3,
xb2,
};
enum class engine : u8
{
iw5,
iw6,
iw7,
iw8,
iw9,
s1,
s2,
s4,
h1,
h2,
};
struct props
{
enum values : u32
{
none = 0 << 0,
str4 = 1 << 0, // strings size 4
tok4 = 1 << 1, // tokenid size 4
waitframe = 1 << 2, // waitframe opcode
params = 1 << 3, // packed func params
boolfuncs = 1 << 4, // isdefined, istrue
boolnotand = 1 << 5, // !&& expr opcode
offs8 = 1 << 6, // offset shift by 8
offs9 = 1 << 7, // offset shift by 9
hash = 1 << 9, // iw9 identifiers
farcall = 1 << 9, // iw9 new call system
foreach = 1 << 10, // iw9 foreach
};
props(values value) : value_(value) {}
operator values() { return value_; }
operator bool() { return value_ != values::none; }
props::values operator|(props::values rhs) const { return static_cast<props::values>(value_ | rhs); }
props::values operator&(props::values rhs) const { return static_cast<props::values>(value_ & rhs); }
friend props::values operator|(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) | static_cast<std::underlying_type<props::values>::type>(rhs));
}
friend props::values operator&(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) & static_cast<std::underlying_type<props::values>::type>(rhs));
}
private:
values value_;
};
enum class switch_type
{
none,
integer,
string,
};
// fordward decl for modules ref
class context;
} // namespace xsk::gsc

View File

@ -0,0 +1,154 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/gsc/common/types.hpp"
namespace xsk::gsc
{
class compiler
{
context* ctx_;
assembly::ptr assembly_;
function::ptr function_;
std::vector<std::string> localfuncs_;
std::vector<std::string> stackframe_;
std::unordered_map<std::string, expr const*> constants_;
std::unordered_map<node*, scope::ptr> scopes_;
std::vector<scope*> break_blks_;
std::vector<scope*> continue_blks_;
std::string animname_;
u32 index_;
u32 label_idx_;
bool can_break_;
bool can_continue_;
bool developer_thread_;
bool animload_;
public:
compiler(context* ctx);
auto compile(program const& data) -> assembly::ptr;
auto compile(std::string const& file, std::vector<u8>& data) -> assembly::ptr;
private:
auto emit_program(program const& prog) -> void;
auto emit_decl(decl const& dec) -> void;
auto emit_decl_usingtree(decl_usingtree const& animtree) -> void;
auto emit_decl_constant(decl_constant const& constant) -> void;
auto emit_decl_function(decl_function const& func) -> void;
auto emit_stmt(stmt const& stm, scope& scp, bool last) -> void;
auto emit_stmt_list(stmt_list const& stm, scope& scp, bool last) -> void;
auto emit_stmt_comp(stmt_comp const& stm, scope& scp, bool last) -> void;
auto emit_stmt_dev(stmt_dev const& stm, scope& scp, bool last) -> void;
auto emit_stmt_expr(stmt_expr const& stm, scope& scp) -> void;
auto emit_stmt_endon(stmt_endon const& stm, scope& scp) -> void;
auto emit_stmt_notify(stmt_notify const& stm, scope& scp) -> void;
auto emit_stmt_wait(stmt_wait const& stm, scope& scp) -> void;
auto emit_stmt_waittill(stmt_waittill const& stm, scope& scp) -> void;
auto emit_stmt_waittillmatch(stmt_waittillmatch const& stm, scope& scp) -> void;
auto emit_stmt_waittillframeend(stmt_waittillframeend const& stm, scope& scp) -> void;
auto emit_stmt_waitframe(stmt_waitframe const& stm, scope& scp) -> void;
auto emit_stmt_if(stmt_if const& stm, scope& scp, bool last) -> void;
auto emit_stmt_ifelse(stmt_ifelse const& stm, scope& scp, bool last) -> void;
auto emit_stmt_while(stmt_while const& stm, scope& scp) -> void;
auto emit_stmt_dowhile(stmt_dowhile const& stm, scope& scp) -> void;
auto emit_stmt_for(stmt_for const& stm, scope& scp) -> void;
auto emit_stmt_foreach(stmt_foreach const& stm, scope& scp) -> void;
auto emit_stmt_switch(stmt_switch const& stm, scope& scp) -> void;
auto emit_stmt_case(stmt_case const& stm, scope& scp) -> void;
auto emit_stmt_default(stmt_default const& stm, scope& scp) -> void;
auto emit_stmt_break(stmt_break const& stm, scope& scp) -> void;
auto emit_stmt_continue(stmt_continue const& stm, scope& scp) -> void;
auto emit_stmt_return(stmt_return const& stm, scope& scp) -> void;
auto emit_stmt_breakpoint(stmt_breakpoint const& stm, scope& scp) -> void;
auto emit_stmt_prof_begin(stmt_prof_begin const& stm, scope& scp) -> void;
auto emit_stmt_prof_end(stmt_prof_end const& stm, scope& scp) -> void;
auto emit_stmt_assert(stmt_assert const& stm, scope& scp) -> void;
auto emit_stmt_assertex(stmt_assertex const& stm, scope& scp) -> void;
auto emit_stmt_assertmsg(stmt_assertmsg const& stm, scope& scp) -> void;
auto emit_expr(expr const& exp, scope& scp) -> void;
auto emit_expr_assign(expr_assign const& exp, scope& scp) -> void;
auto emit_expr_clear(expr const& exp, scope& scp) -> void;
auto emit_expr_clear_local(expr_identifier const& exp, scope& scp) -> void;
auto emit_expr_increment(expr_increment const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_decrement(expr_decrement const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_ternary(expr_ternary const& exp, scope& scp) -> void;
auto emit_expr_binary(expr_binary const& exp, scope& scp) -> void;
auto emit_expr_complement(expr_complement const& exp, scope& scp) -> void;
auto emit_expr_negate(expr_negate const& exp, scope& scp) -> void;
auto emit_expr_not(expr_not const& exp, scope& scp) -> void;
auto emit_expr_call(expr_call const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_call_pointer(expr_pointer const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_call_function(expr_function const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_method(expr_method const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_method_pointer(expr_pointer const& exp, expr const& obj, scope& scp, bool is_stmt) -> void;
auto emit_expr_method_function(expr_function const& exp, expr const& obj, scope& scp, bool is_stmt) -> void;
auto emit_expr_add_array(expr_add_array const& exp, scope& scp) -> void;
auto emit_expr_parameters(expr_parameters const& exp, scope& scp) -> void;
auto emit_expr_arguments(expr_arguments const& exp, scope& scp) -> void;
auto emit_expr_isdefined(expr_isdefined const& exp, scope& scp) -> void;
auto emit_expr_istrue(expr_istrue const& exp, scope& scp) -> void;
auto emit_expr_reference(expr_reference const& exp, scope& scp) -> void;
auto emit_expr_size(expr_size const& exp, scope& scp) -> void;
auto emit_expr_tuple(expr_tuple const& exp, scope& scp) -> void;
auto emit_expr_variable_ref(expr const& exp, scope& scp, bool set) -> void;
auto emit_expr_array_ref(expr_array const& exp, scope& scp, bool set) -> void;
auto emit_expr_field_ref(expr_field const& exp, scope& scp, bool set) -> void;
auto emit_expr_local_ref(expr_identifier const& exp, scope& scp, bool set) -> void;
auto emit_expr_variable(expr const& exp, scope& scp) -> void;
auto emit_expr_array(expr_array const& exp, scope& scp) -> void;
auto emit_expr_field(expr_field const& exp, scope& scp) -> void;
auto emit_expr_local(expr_identifier const& exp, scope& scp) -> void;
auto emit_expr_object(expr const& exp, scope& scp) -> void;
auto emit_expr_vector(expr_vector const& exp, scope& scp) -> void;
auto emit_expr_animation(expr_animation const& exp) -> void;
auto emit_expr_animtree(expr_animtree const& exp) -> void;
auto emit_expr_istring(expr_istring const& exp) -> void;
auto emit_expr_string(expr_string const& exp) -> void;
auto emit_expr_float(expr_float const& exp) -> void;
auto emit_expr_integer(expr_integer const& exp) -> void;
auto emit_expr_false(expr_false const& exp) -> void;
auto emit_expr_true(expr_true const& exp) -> void;
auto emit_create_local_vars(scope& scp) -> void;
auto emit_remove_local_vars(scope& scp) -> void;
auto emit_opcode(opcode op) -> void;
auto emit_opcode(opcode op, std::string const& data) -> void;
auto emit_opcode(opcode op, std::vector<std::string> const& data) -> void;
auto process_function(decl_function const& func) -> void;
auto process_stmt(stmt const& stm, scope& scp) -> void;
auto process_stmt_list(stmt_list const& stm, scope& scp) -> void;
auto process_stmt_comp(stmt_comp const& stm, scope& scp) -> void;
auto process_stmt_dev(stmt_dev const& stm, scope& scp) -> void;
auto process_stmt_expr(stmt_expr const& stm, scope& scp) -> void;
auto process_stmt_waittill(stmt_waittill const& stm, scope& scp) -> void;
auto process_stmt_if(stmt_if const& stm, scope& scp) -> void;
auto process_stmt_ifelse(stmt_ifelse const& stm, scope& scp) -> void;
auto process_stmt_while(stmt_while const& stm, scope& scp) -> void;
auto process_stmt_dowhile(stmt_dowhile const& stm, scope& scp) -> void;
auto process_stmt_for(stmt_for const& stm, scope& scp) -> void;
auto process_stmt_foreach(stmt_foreach const& stm, scope& scp) -> void;
auto process_stmt_switch(stmt_switch const& stm, scope& scp) -> void;
auto process_stmt_break(stmt_break const& stm, scope& scp) -> void;
auto process_stmt_continue(stmt_continue const& stm, scope& scp) -> void;
auto process_stmt_return(stmt_return const& stm, scope& scp) -> void;
auto process_expr(expr const& exp, scope& scp) -> void;
auto process_expr_tuple(expr_tuple const& exp, scope& scp) -> void;
auto process_expr_parameters(expr_parameters const& exp, scope& scp) -> void;
auto variable_register(expr_identifier const& exp, scope& scp) -> void;
auto variable_initialized(expr_identifier const& exp, scope& scp) -> bool;
auto variable_initialize(expr_identifier const& exp, scope& scp) -> u8;
auto variable_create(expr_identifier const& exp, scope& scp) -> u8;
auto variable_access(expr_identifier const& exp, scope& scp) -> u8;
auto resolve_function_type(expr_function const& exp, std::string& path) -> call::type;
auto resolve_reference_type(expr_reference const& exp, std::string& path, bool& method) -> call::type;
auto is_constant_condition(expr const& exp) -> bool;
auto insert_label(std::string const& label) -> void;
auto create_label() -> std::string;
auto insert_label() -> std::string;
};
} // namespace xsk::gsc

149
include/xsk/gsc/context.hpp Normal file
View File

@ -0,0 +1,149 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/gsc/common/types.hpp"
#include "xsk/gsc/source.hpp"
#include "xsk/gsc/assembler.hpp"
#include "xsk/gsc/disassembler.hpp"
#include "xsk/gsc/compiler.hpp"
#include "xsk/gsc/decompiler.hpp"
namespace xsk::gsc
{
class context
{
public:
using fs_callback = std::function<std::pair<buffer, std::vector<u8>>(std::string const&)>;
context(props props, engine engine, endian endian, system system, u32 str_count);
auto props() const -> props { return props_; }
auto build() const -> build { return build_; }
auto engine() const -> engine { return engine_; }
auto endian() const -> endian { return endian_; }
auto system() const -> system { return system_; }
auto instance() const -> instance { return instance_; }
auto str_count() const -> u32 { return str_count_; }
auto source() -> source& { return source_; }
auto assembler() -> assembler& { return assembler_; }
auto disassembler() -> disassembler& { return disassembler_; }
auto compiler() -> compiler& { return compiler_; }
auto decompiler() -> decompiler& { return decompiler_; }
auto func_map() const -> std::unordered_map<std::string_view, u16> const& { return func_map_rev_; }
auto meth_map() const -> std::unordered_map<std::string_view, u16> const& { return meth_map_rev_; }
auto init(gsc::build build, fs_callback callback) -> void;
auto cleanup() -> void;
auto engine_name() const -> std::string_view;
auto opcode_size(opcode op) const -> u32;
auto opcode_id(opcode op) const -> u8;
auto opcode_name(opcode op) const -> std::string;
auto opcode_enum(std::string const& name) const -> opcode;
auto opcode_enum(u8 id) const -> opcode;
auto func_id(std::string const& name) const -> u16;
auto func_name(u16 id) const -> std::string;
auto func2_id(std::string const& name) const -> u64;
auto func2_name(u64 id) const -> std::string;
auto func_exists(std::string const& name) const -> bool;
auto func_add(std::string const& name, u16 id) -> void;
auto meth_id(std::string const& name) const -> u16;
auto meth_name(u16 id) const -> std::string;
auto meth2_id(std::string const& name) const -> u64;
auto meth2_name(u64 id) const -> std::string;
auto meth_exists(std::string const& name) const -> bool;
auto meth_add(std::string const& name, u16 id) -> void;
auto token_id(std::string const& name) const -> u32;
auto token_name(u32 id) const -> std::string;
auto path_id(std::string const& name) const -> u64;
auto path_name(u64 id) const -> std::string;
auto hash_id(std::string const& name) const -> u64;
auto hash_name(u64 id) const -> std::string;
auto make_token(std::string_view str) const -> std::string;
auto load_header(std::string const& name) -> std::tuple<std::string const*, char const*, usize>;
auto load_include(std::string const& name) -> bool;
auto init_includes() -> void;
auto is_includecall(std::string const& name, std::string& path) -> bool;
protected:
gsc::props props_;
gsc::build build_;
gsc::engine engine_;
gsc::endian endian_;
gsc::system system_;
gsc::instance instance_;
u32 str_count_;
gsc::source source_;
gsc::assembler assembler_;
gsc::disassembler disassembler_;
gsc::compiler compiler_;
gsc::decompiler decompiler_;
fs_callback fs_callback_;
std::unordered_map<opcode, std::string_view> opcode_map_;
std::unordered_map<std::string_view, opcode> opcode_map_rev_;
std::unordered_map<u8, opcode> code_map_;
std::unordered_map<opcode, u8> code_map_rev_;
std::unordered_map<u16, std::string_view> func_map_;
std::unordered_map<std::string_view, u16> func_map_rev_;
std::unordered_map<u16, std::string_view> meth_map_;
std::unordered_map<std::string_view, u16> meth_map_rev_;
std::unordered_map<u32, std::string_view> token_map_;
std::unordered_map<std::string_view, u32> token_map_rev_;
std::unordered_map<u64, std::string_view> func_map2_;
std::unordered_map<u64, std::string_view> meth_map2_;
std::unordered_map<u64, std::string_view> path_map_;
std::unordered_map<u64, std::string_view> hash_map_;
std::unordered_map<std::string, std::vector<u8>> header_files_;
std::unordered_set<std::string_view> includes_;
std::unordered_map<std::string, std::vector<std::string>> include_cache_;
std::unordered_set<std::string> new_func_map_;
std::unordered_set<std::string> new_meth_map_;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,100 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/gsc/common/types.hpp"
namespace xsk::gsc
{
class decompiler
{
context const* ctx_;
program::ptr program_;
decl_function::ptr func_;
std::unordered_map<u32, std::string> labels_;
std::vector<std::string> expr_labels_;
std::vector<std::string> tern_labels_;
std::stack<node::ptr> stack_;
bool in_waittill_;
locjmp locs_;
public:
decompiler(context const* ctx);
auto decompile(assembly const& data) -> program::ptr;
private:
auto decompile_function(function const& func) -> void;
auto decompile_instruction(instruction const& inst) -> void;
auto decompile_expressions(instruction const& inst) -> void;
auto decompile_statements(stmt_list& stm) -> void;
auto decompile_loops(stmt_list& stm) -> void;
auto decompile_switches(stmt_list& stm) -> void;
auto decompile_ifelses(stmt_list& stm) -> void;
auto decompile_aborts(stmt_list& stm) -> void;
auto decompile_tuples(stmt_list& stm) -> void;
auto decompile_if(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_ifelse(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_ifelse_end(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_inf(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_loop(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_while(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_dowhile(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_for(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_foreach(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_switch(stmt_list& stm, usize begin, usize end) -> void;
auto find_location_reference(stmt_list const& stm, usize begin, usize end, std::string const& loc) -> bool;
auto find_location_index(stmt_list const& stm, std::string const& loc) -> usize;
auto last_location_index(stmt_list const& stm, usize index) -> bool;
auto process_function(decl_function& func) -> void;
auto process_stmt(stmt& stm, scope& scp) -> void;
auto process_stmt_list(stmt_list& stm, scope& scp) -> void;
auto process_stmt_comp(stmt_comp& stm, scope& scp) -> void;
auto process_stmt_dev(stmt_dev& stm, scope& scp) -> void;
auto process_stmt_expr(stmt_expr& stm, scope& scp) -> void;
auto process_stmt_endon(stmt_endon& stm, scope& scp) -> void;
auto process_stmt_notify(stmt_notify& stm, scope& scp) -> void;
auto process_stmt_wait(stmt_wait& stm, scope& scp) -> void;
auto process_stmt_waittill(stmt_waittill& stm, scope& scp) -> void;
auto process_stmt_waittillmatch(stmt_waittillmatch& stm, scope& scp) -> void;
auto process_stmt_if(stmt_if& stm, scope& scp) -> void;
auto process_stmt_ifelse(stmt_ifelse& stm, scope& scp) -> void;
auto process_stmt_while(stmt_while& stm, scope& scp) -> void;
auto process_stmt_dowhile(stmt_dowhile& stm, scope& scp) -> void;
auto process_stmt_for(stmt_for& stm, scope& scp) -> void;
auto process_stmt_foreach(stmt_foreach& stm, scope& scp) -> void;
auto process_stmt_switch(stmt_switch& stm, scope& scp) -> void;
auto process_stmt_break(stmt_break& stm, scope& scp) -> void;
auto process_stmt_continue(stmt_continue& stm, scope& scp) -> void;
auto process_stmt_return(stmt_return& stm, scope& scp) -> void;
auto process_stmt_create(stmt_create& stm, scope& scp) -> void;
auto process_stmt_remove(stmt_remove& stm, scope& scp) -> void;
auto process_expr(expr::ptr& exp, scope& scp) -> void;
auto process_expr_increment(expr_increment& exp, scope& scp) -> void;
auto process_expr_decrement(expr_decrement& exp, scope& scp) -> void;
auto process_expr_assign(expr_assign::ptr& exp, scope& scp) -> void;
auto process_expr_ternary(expr_ternary& exp, scope& scp) -> void;
auto process_expr_binary(expr_binary& exp, scope& scp) -> void;
auto process_expr_complement(expr_complement& exp, scope& scp) -> void;
auto process_expr_not(expr_not& exp, scope& scp) -> void;
auto process_expr_call(expr_call& exp, scope& scp) -> void;
auto process_expr_method(expr_method& exp, scope& scp) -> void;
auto process_expr_call_pointer(expr_pointer& exp, scope& scp) -> void;
auto process_expr_call_function(expr_function& exp, scope& scp) -> void;
auto process_expr_method_pointer(expr_pointer& exp, expr::ptr& obj, scope& scp) -> void;
auto process_expr_method_function(expr_function& exp, expr::ptr& obj, scope& scp) -> void;
auto process_expr_arguments(expr_arguments& exp, scope& scp) -> void;
auto process_expr_add_array(expr_add_array& exp, scope& scp) -> void;
auto process_expr_size(expr_size& exp, scope& scp) -> void;
auto process_expr_tuple(expr_tuple& exp, scope& scp) -> void;
auto process_expr_array(expr_array& exp, scope& scp) -> void;
auto process_expr_field(expr_field& exp, scope& scp) -> void;
auto process_expr_vector(expr_vector& exp, scope& scp) -> void;
auto process_expr_var_create(expr::ptr& exp, scope& scp) -> void;
auto process_expr_var_access(expr::ptr& exp, scope& scp) -> void;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,45 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/utils/reader.hpp"
#include "xsk/gsc/common/types.hpp"
namespace xsk::gsc
{
class disassembler
{
context const* ctx_;
function::ptr func_;
assembly::ptr assembly_;
utils::reader script_;
utils::reader stack_;
public:
disassembler(context const* ctx);
auto disassemble(buffer const& script, buffer const& stack) -> assembly::ptr;
auto disassemble(std::vector<u8> const& script, std::vector<u8> const& stack) -> assembly::ptr;
auto disassemble(u8 const* script, usize script_size, u8 const* stack, usize stack_size) -> assembly::ptr;
private:
auto dissasemble_function(function& func) -> void;
auto dissasemble_instruction(instruction& inst) -> void;
auto disassemble_builtin_call(instruction& inst, bool method, bool args) -> void;
auto disassemble_local_call(instruction& inst, bool thread) -> void;
auto disassemble_far_call(instruction& inst, bool thread) -> void;
auto disassemble_switch(instruction& inst) -> void;
auto disassemble_end_switch(instruction& inst) -> void;
auto disassemble_field_variable(instruction& inst) -> void;
auto disassemble_formal_params(instruction& inst) -> void;
auto disassemble_jump(instruction& inst, bool expr, bool back) -> void;
auto disassemble_offset() -> i32;
auto resolve_functions() -> void;
auto resolve_function(std::string const& index) -> std::string;
auto decrypt_string(std::string const& str) -> std::string;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::h1
{
// H1 PC 1.15.1251288
constexpr usize code_count = 154;
constexpr usize func_count = 778;
constexpr usize meth_count = 1415;
constexpr usize token_count = 42947;
constexpr u32 max_string_id = 42989;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::h1

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::h2
{
// H2 PC 1.0.1280159
constexpr usize code_count = 154;
constexpr usize func_count = 800;
constexpr usize meth_count = 1491;
constexpr usize token_count = 42524;
constexpr u32 max_string_id = 54743;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::h2

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw5_pc
{
// IW5 PC 1.9.388110
constexpr usize code_count = 153;
constexpr usize func_count = 455;
constexpr usize meth_count = 780;
constexpr usize token_count = 6306;
constexpr u32 max_string_id = 33386;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw5_pc

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw5_ps
{
// IW5 PS
constexpr usize code_count = 153;
constexpr usize func_count = 452;
constexpr usize meth_count = 777;
constexpr usize token_count = 14221;
constexpr u32 max_string_id = 33360;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw5_ps

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw5_xb
{
// IW5 XB 1.8.388110
constexpr usize code_count = 153;
constexpr usize func_count = 455;
constexpr usize meth_count = 779;
constexpr usize token_count = 14221;
constexpr u32 max_string_id = 33386;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw5_xb

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw6_pc
{
// IW6 PC 3.15.146
constexpr usize code_count = 153;
constexpr usize func_count = 605;
constexpr usize meth_count = 1066;
constexpr usize token_count = 38306;
constexpr u32 max_string_id = 38305;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw6_pc

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw6_ps
{
constexpr usize code_count = 153;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0x95A1;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw6_ps

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw6_xb
{
constexpr usize code_count = 153;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0x8EFA;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw6_xb

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw7
{
constexpr usize code_count = 153;
constexpr usize func_count = 807;
constexpr usize meth_count = 1500;
constexpr usize token_count = 682;
constexpr u32 max_string_id = 0x13FCC;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw7

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw8
{
constexpr usize code_count = 190;
constexpr usize func_count = 1065;
constexpr usize meth_count = 2032;
constexpr usize token_count = 72014;
constexpr u32 max_string_id = 0x1472F;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw8

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw9
{
constexpr usize code_count = 167;
constexpr usize func_count = 905;
constexpr usize meth_count = 1469;
constexpr usize path_count = 1467;
constexpr usize hash_count = 73500;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw9

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s1_pc
{
constexpr usize code_count = 154;
constexpr usize func_count = 735;
constexpr usize meth_count = 1389;
constexpr usize token_count = 42942;
constexpr u32 max_string_id = 0xA7DC;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s1_pc

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s1_ps
{
constexpr usize code_count = 154;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0xA51D; // TODO
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s1_ps

View File

@ -0,0 +1,26 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s1_xb
{
constexpr usize code_count = 154;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0xA51D;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s1_xb

Some files were not shown because too many files have changed in this diff Show More