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 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
.vscode/ .vscode/
data/iw5/ # Output folders
data/iw6/ renamed/
data/iw7/ parsed/
data/iw8/ compiled/
data/h1/ decompiled/
data/h2/ assembled/
data/s1/ disassembled/
data/s2/
data/s4/ data/*
data/t6/
# Version file
include/xsk/version.hpp

4
.gitmodules vendored
View File

@ -1,3 +1,7 @@
[submodule "deps/zlib"] [submodule "deps/zlib"]
path = deps/zlib path = deps/zlib
url = https://github.com/madler/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) ![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) [![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) [![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 # GSC Tool
A utility to compile & decompile IW engine game scripts. A utility to compile & decompile IW engine game scripts.
## Supported Games ## Supported Games
- **IW5** *(Call of Duty: Modern Warfare 3)* - **IW5** *(Call of Duty: Modern Warfare 3)* `PC` `PS3` `Xbox 360`
- **IW6** *(Call of Duty: Ghosts)* - **IW6** *(Call of Duty: Ghosts)* `PC` `PS3` `PS4` `Xbox 360` `Xbox One`
- **IW7** *(Call of Duty: Infinite Warfare)* - **IW7** *(Call of Duty: Infinite Warfare)* `PC` `PS4` `Xbox One`
- **IW8** *(Call of Duty: Modern Warfare (2019))* - **IW8** *(Call of Duty: Modern Warfare (2019) / Warzone)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **S1** *(Call of Duty: Advanced Warfare)* - **IW9** *(Call of Duty: Modern Warfare II (2022) / Warzone 2)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **S2** *(Call of Duty: WWII)* - **S1** *(Call of Duty: Advanced Warfare)* `PC` `PS3` `PS4` `Xbox 360` `Xbox One`
- **S4** *(Call of Duty: Vanguard)* - **S2** *(Call of Duty: WWII)* `PC` `PS4` `Xbox One`
- **H1** *(Call of Duty: Modern Warfare Remastered)* - **S4** *(Call of Duty: Vanguard)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **H2** *(Call of Duty: Modern Warfare 2 Campaign Remastered)* - **H1** *(Call of Duty: Modern Warfare Remastered)* `PC` `PS4` `Xbox One`
- **T4** *(Call of Duty: World at War)* ***\*WIP\**** - **H2** *(Call of Duty: Modern Warfare 2 Campaign Remastered)* `PC` `PS4` `PS5` `Xbox One` `Xbox Series X|S`
- **T5** *(Call of Duty: Black Ops)* ***\*WIP\**** - **T6** *(Call of Duty: Black Ops II)* `PC` `PS3` `Xbox 360` `Wii U`
- **T6** *(Call of Duty: Black Ops II)* - **T7** *(Call of Duty: Black Ops III)* `PC` *(Decompiler)*
- **T7** *(Call of Duty: Black Ops III)* ***\*WIP\**** - **T8** *(Call of Duty: Black Ops 4)* ***\*WIP\****
- **T9** *(Call of Duty: Black Ops Cold War)* ***\*WIP\****
## Usage ## 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 | | 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`| |`disasm` |dissasemble a `file.gscbin`|`file.gscasm`|
|`comp` |compile a `file.gsc` |`file.gscbin`| |`comp` |compile a `file.gsc` |`file.gscbin`|
|`decomp` |decompile a `file.gscbin` |`file.gsc` | |`decomp` |decompile a `file.gscbin` |`file.gsc` |
|`parse` |parse a `file.gsc` |`file.gsc` |
## File Format ## 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). 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 ## 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 ## 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. 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_NONSTDC_NO_DEPRECATE",
"_CRT_SECURE_NO_DEPRECATE", "_CRT_SECURE_NO_DEPRECATE",
} }
if os.istarget("darwin") then
defines "HAVE_UNISTD_H"
end
end end
table.insert(dependencies, zlib) 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 // Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
@ -8,20 +8,19 @@
namespace xsk::arc namespace xsk::arc
{ {
/// A point in a source file.
class position class position
{ {
public: public:
/// Type for file name.
typedef const std::string filename_type; typedef const std::string filename_type;
/// Type for line and column numbers.
typedef int counter_type; 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) explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {} : filename(f), line(l), column(c) {}
/// Initialization.
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1) void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{ {
filename = fn; filename = fn;
@ -29,9 +28,6 @@ public:
column = c; column = c;
} }
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines(counter_type count = 1) void lines(counter_type count = 1)
{ {
if (count) if (count)
@ -41,179 +37,131 @@ public:
} }
} }
/// (column related) Advance to the COUNT next columns.
void columns(counter_type count = 1) void columns(counter_type count = 1)
{ {
column = add_(column, 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: private:
/// Compute max (min, lhs+rhs).
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min) static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{ {
return lhs + rhs < min ? min : lhs + rhs; return lhs + rhs < min ? min : lhs + rhs;
} }
}; };
/// Add \a width columns, in place.
inline position& operator+=(position &res, position::counter_type width) inline position& operator+=(position &res, position::counter_type width)
{ {
res.columns(width); res.columns(width);
return res; return res;
} }
/// Add \a width columns.
inline position operator+(position res, position::counter_type width) inline position operator+(position res, position::counter_type width)
{ {
return res += width; return res += width;
} }
/// Subtract \a width columns, in place.
inline position& operator-=(position &res, position::counter_type width) inline position& operator-=(position &res, position::counter_type width)
{ {
return res += -width; return res += -width;
} }
/// Subtract \a width columns.
inline position operator-(position res, position::counter_type width) inline position operator-(position res, position::counter_type width)
{ {
return res -= width; return res -= width;
} }
/** \brief Intercept output stream redirection. template <typename T>
** \param ostr the destination output stream std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const position &pos)
** \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)
{ {
if (pos.filename) if (pos.filename)
ostr << *pos.filename << ':'; ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column; return ostr << pos.line << '.' << pos.column;
} }
/// Two points in a source file.
class location class location
{ {
public: public:
/// Type for file name.
typedef position::filename_type filename_type; typedef position::filename_type filename_type;
/// Type for line and column numbers.
typedef position::counter_type counter_type; 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) location(const position &b, const position &e)
: begin(b), end(e) {} : begin(b), end(e) {}
/// Construct a 0-width location in \a p.
explicit location(const position &p = position()) explicit location(const position &p = position())
: begin(p), end(p) {} : 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) explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {} : begin(f, l, c), end(f, l, c) {}
/// Initialization.
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1) void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{ {
begin.initialize(f, l, c); begin.initialize(f, l, c);
end = begin; end = begin;
} }
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step() void step()
{ {
begin = end; begin = end;
} }
/// Extend the current location to the COUNT next columns.
void columns(counter_type count = 1) void columns(counter_type count = 1)
{ {
end += count; end += count;
} }
/// Extend the current location to the COUNT next lines.
void lines(counter_type count = 1) void lines(counter_type count = 1)
{ {
end.lines(count); end.lines(count);
} }
/** \} */
public:
auto print() const -> std::string 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 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) inline location& operator+=(location &res, const location &end)
{ {
res.end = end.end; res.end = end.end;
return res; return res;
} }
/// Join two locations.
inline location operator+(location res, const location &end) inline location operator+(location res, const location &end)
{ {
return res += end; return res += end;
} }
/// Add \a width columns to the end position, in place.
inline location& operator+=(location &res, location::counter_type width) inline location& operator+=(location &res, location::counter_type width)
{ {
res.columns(width); res.columns(width);
return res; return res;
} }
/// Add \a width columns to the end position.
inline location operator+(location res, location::counter_type width) inline location operator+(location res, location::counter_type width)
{ {
return res += width; return res += width;
} }
/// Subtract \a width columns to the end position, in place.
inline location& operator-=(location &res, location::counter_type width) inline location& operator-=(location &res, location::counter_type width)
{ {
return res += -width; return res += -width;
} }
/// Subtract \a width columns to the end position.
inline location operator-(location res, location::counter_type width) inline location operator-(location res, location::counter_type width)
{ {
return res -= width; return res -= width;
} }
/** \brief Intercept output stream redirection. template <typename T>
** \param ostr the destination output stream std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const location &loc)
** \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)
{ {
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0; location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin; 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 // Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
@ -8,20 +8,19 @@
namespace xsk::gsc namespace xsk::gsc
{ {
/// A point in a source file.
class position class position
{ {
public: public:
/// Type for file name.
typedef const std::string filename_type; typedef const std::string filename_type;
/// Type for line and column numbers.
typedef int counter_type; 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) explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {} : filename(f), line(l), column(c) {}
/// Initialization.
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1) void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{ {
filename = fn; filename = fn;
@ -29,9 +28,6 @@ public:
column = c; column = c;
} }
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines(counter_type count = 1) void lines(counter_type count = 1)
{ {
if (count) if (count)
@ -41,179 +37,131 @@ public:
} }
} }
/// (column related) Advance to the COUNT next columns.
void columns(counter_type count = 1) void columns(counter_type count = 1)
{ {
column = add_(column, 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: private:
/// Compute max (min, lhs+rhs).
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min) static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{ {
return lhs + rhs < min ? min : lhs + rhs; return lhs + rhs < min ? min : lhs + rhs;
} }
}; };
/// Add \a width columns, in place.
inline position& operator+=(position &res, position::counter_type width) inline position& operator+=(position &res, position::counter_type width)
{ {
res.columns(width); res.columns(width);
return res; return res;
} }
/// Add \a width columns.
inline position operator+(position res, position::counter_type width) inline position operator+(position res, position::counter_type width)
{ {
return res += width; return res += width;
} }
/// Subtract \a width columns, in place.
inline position& operator-=(position &res, position::counter_type width) inline position& operator-=(position &res, position::counter_type width)
{ {
return res += -width; return res += -width;
} }
/// Subtract \a width columns.
inline position operator-(position res, position::counter_type width) inline position operator-(position res, position::counter_type width)
{ {
return res -= width; return res -= width;
} }
/** \brief Intercept output stream redirection. template <typename T>
** \param ostr the destination output stream std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const position &pos)
** \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)
{ {
if (pos.filename) if (pos.filename)
ostr << *pos.filename << ':'; ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column; return ostr << pos.line << '.' << pos.column;
} }
/// Two points in a source file.
class location class location
{ {
public: public:
/// Type for file name.
typedef position::filename_type filename_type; typedef position::filename_type filename_type;
/// Type for line and column numbers.
typedef position::counter_type counter_type; 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) location(const position &b, const position &e)
: begin(b), end(e) {} : begin(b), end(e) {}
/// Construct a 0-width location in \a p.
explicit location(const position &p = position()) explicit location(const position &p = position())
: begin(p), end(p) {} : 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) explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {} : begin(f, l, c), end(f, l, c) {}
/// Initialization.
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1) void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{ {
begin.initialize(f, l, c); begin.initialize(f, l, c);
end = begin; end = begin;
} }
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step() void step()
{ {
begin = end; begin = end;
} }
/// Extend the current location to the COUNT next columns.
void columns(counter_type count = 1) void columns(counter_type count = 1)
{ {
end += count; end += count;
} }
/// Extend the current location to the COUNT next lines.
void lines(counter_type count = 1) void lines(counter_type count = 1)
{ {
end.lines(count); end.lines(count);
} }
/** \} */
public:
auto print() const -> std::string 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 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) inline location& operator+=(location &res, const location &end)
{ {
res.end = end.end; res.end = end.end;
return res; return res;
} }
/// Join two locations.
inline location operator+(location res, const location &end) inline location operator+(location res, const location &end)
{ {
return res += end; return res += end;
} }
/// Add \a width columns to the end position, in place.
inline location& operator+=(location &res, location::counter_type width) inline location& operator+=(location &res, location::counter_type width)
{ {
res.columns(width); res.columns(width);
return res; return res;
} }
/// Add \a width columns to the end position.
inline location operator+(location res, location::counter_type width) inline location operator+(location res, location::counter_type width)
{ {
return res += width; return res += width;
} }
/// Subtract \a width columns to the end position, in place.
inline location& operator-=(location &res, location::counter_type width) inline location& operator-=(location &res, location::counter_type width)
{ {
return res += -width; return res += -width;
} }
/// Subtract \a width columns to the end position.
inline location operator-(location res, location::counter_type width) inline location operator-(location res, location::counter_type width)
{ {
return res -= width; return res -= width;
} }
/** \brief Intercept output stream redirection. template <typename T>
** \param ostr the destination output stream std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const location &loc)
** \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)
{ {
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0; location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin; 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