Finished up Langium stuffs and more more more

This commit is contained in:
Rolf Martin Glomsrud 2024-05-11 16:09:03 +02:00
parent f2e7912f0b
commit 8ddffdf3d7
42 changed files with 938 additions and 867 deletions

View file

@ -4,14 +4,14 @@
"version": "2.0.0",
"tasks": [
{
"label": "Build js-transform-lang",
"label": "Build jstql",
"command": "npm run langium:generate && npm run build",
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Langium: Generate grammar and build the js-transform-lang language",
"detail": "Langium: Generate grammar and build the jstql language",
"icon": {
"color": "terminal.ansiGreen",
"id": "server-process"

12
JSTQL/langium-config.json Normal file
View file

@ -0,0 +1,12 @@
{
"projectName": "Jstql",
"languages": [{
"id": "jstql",
"grammar": "src/language/jstql.langium",
"fileExtensions": [".jstql"],
"textMate": {
"out": "syntaxes/jstql.tmLanguage.json"
}
}],
"out": "src/language/generated"
}

View file

@ -6,10 +6,10 @@ This folder contains all necessary files for your language extension.
* `package.json` - the manifest file in which you declare your language support.
* `language-configuration.json` - the language configuration used in the VS Code editor, defining the tokens that are used for comments and brackets.
* `src/extension/main.ts` - the main code of the extension, which is responsible for launching a language server and client.
* `src/language/js-transform-lang.langium` - the grammar definition of your language.
* `src/language/jstql.langium` - the grammar definition of your language.
* `src/language/main.ts` - the entry point of the language server process.
* `src/language/js-transform-lang-module.ts` - the dependency injection module of your language implementation. Use this to register overridden and added services.
* `src/language/js-transform-lang-validator.ts` - an example validator. You should change it to reflect the semantics of your language.
* `src/language/jstql-module.ts` - the dependency injection module of your language implementation. Use this to register overridden and added services.
* `src/language/jstql-validator.ts` - an example validator. You should change it to reflect the semantics of your language.
* `src/cli/main.ts` - the entry point of the command line interface (CLI) of your language.
* `src/cli/generator.ts` - the code generator used by the CLI to write output files from DSL documents.
* `src/cli/cli-util.ts` - utility code for the CLI.

View file

@ -1,11 +1,11 @@
{
"name": "didactic-chainsaw-dsl",
"name": "JSTQL",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "didactic-chainsaw-dsl",
"name": "JSTQL",
"version": "0.0.1",
"dependencies": {
"chalk": "~5.3.0",
@ -15,7 +15,7 @@
"vscode-languageserver": "~9.0.1"
},
"bin": {
"js-transform-lang-cli": "bin/cli.js"
"jstql-cli": "bin/cli.js"
},
"devDependencies": {
"@types/node": "~16.18.41",
@ -33,19 +33,10 @@
"vscode": "^1.67.0"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
"integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz",
"integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz",
"integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==",
"dev": true,
"dependencies": {
"regenerator-runtime": "^0.14.0"
@ -88,10 +79,26 @@
"resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz",
"integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ=="
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
"integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.8.tgz",
"integrity": "sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz",
"integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==",
"cpu": [
"arm"
],
@ -105,9 +112,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz",
"integrity": "sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz",
"integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==",
"cpu": [
"arm64"
],
@ -121,9 +128,9 @@
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.8.tgz",
"integrity": "sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz",
"integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==",
"cpu": [
"x64"
],
@ -137,9 +144,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz",
"integrity": "sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz",
"integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==",
"cpu": [
"arm64"
],
@ -153,9 +160,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.8.tgz",
"integrity": "sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz",
"integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==",
"cpu": [
"x64"
],
@ -169,9 +176,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.8.tgz",
"integrity": "sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz",
"integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==",
"cpu": [
"arm64"
],
@ -185,9 +192,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.8.tgz",
"integrity": "sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz",
"integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==",
"cpu": [
"x64"
],
@ -201,9 +208,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.8.tgz",
"integrity": "sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz",
"integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==",
"cpu": [
"arm"
],
@ -217,9 +224,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.8.tgz",
"integrity": "sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz",
"integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==",
"cpu": [
"arm64"
],
@ -233,9 +240,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.8.tgz",
"integrity": "sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz",
"integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==",
"cpu": [
"ia32"
],
@ -249,9 +256,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.8.tgz",
"integrity": "sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz",
"integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==",
"cpu": [
"loong64"
],
@ -265,9 +272,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.8.tgz",
"integrity": "sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz",
"integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==",
"cpu": [
"mips64el"
],
@ -281,9 +288,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.8.tgz",
"integrity": "sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz",
"integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==",
"cpu": [
"ppc64"
],
@ -297,9 +304,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.8.tgz",
"integrity": "sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz",
"integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==",
"cpu": [
"riscv64"
],
@ -313,9 +320,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.8.tgz",
"integrity": "sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz",
"integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==",
"cpu": [
"s390x"
],
@ -329,9 +336,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.8.tgz",
"integrity": "sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz",
"integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==",
"cpu": [
"x64"
],
@ -345,9 +352,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.8.tgz",
"integrity": "sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz",
"integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==",
"cpu": [
"x64"
],
@ -361,9 +368,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.8.tgz",
"integrity": "sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz",
"integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==",
"cpu": [
"x64"
],
@ -377,9 +384,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.8.tgz",
"integrity": "sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz",
"integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==",
"cpu": [
"x64"
],
@ -393,9 +400,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.8.tgz",
"integrity": "sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz",
"integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==",
"cpu": [
"arm64"
],
@ -409,9 +416,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.8.tgz",
"integrity": "sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz",
"integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==",
"cpu": [
"ia32"
],
@ -425,9 +432,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.8.tgz",
"integrity": "sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz",
"integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==",
"cpu": [
"x64"
],
@ -488,22 +495,22 @@
}
},
"node_modules/@eslint/js": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz",
"integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==",
"version": "8.57.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
"integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.13",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
"integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
"integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
"dev": true,
"dependencies": {
"@humanwhocodes/object-schema": "^2.0.1",
"debug": "^4.1.1",
"@humanwhocodes/object-schema": "^2.0.2",
"debug": "^4.3.1",
"minimatch": "^3.0.5"
},
"engines": {
@ -524,9 +531,9 @@
}
},
"node_modules/@humanwhocodes/object-schema": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"dev": true
},
"node_modules/@nodelib/fs.scandir": {
@ -571,15 +578,15 @@
"dev": true
},
"node_modules/@types/node": {
"version": "16.18.67",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.67.tgz",
"integrity": "sha512-gUa0tDO9oxyAYO9V9tqxDJguVMDpqUwH5I5Q9ASYBCso+8CUdJlKPKDYS1YSS9kyZWIduDafZvucGM0zGNKFjg==",
"version": "16.18.97",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.97.tgz",
"integrity": "sha512-4muilE1Lbfn57unR+/nT9AFjWk0MtWi5muwCEJqnOvfRQDbSfLCUdN7vCIg8TYuaANfhLOV85ve+FNpiUsbSRg==",
"dev": true
},
"node_modules/@types/semver": {
"version": "7.5.6",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz",
"integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==",
"version": "7.5.8",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
"dev": true
},
"node_modules/@types/vscode": {
@ -778,9 +785,9 @@
}
},
"node_modules/acorn": {
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
"integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@ -1109,9 +1116,9 @@
"dev": true
},
"node_modules/esbuild": {
"version": "0.19.8",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.8.tgz",
"integrity": "sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==",
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
"integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
"dev": true,
"hasInstallScript": true,
"bin": {
@ -1121,34 +1128,35 @@
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/android-arm": "0.19.8",
"@esbuild/android-arm64": "0.19.8",
"@esbuild/android-x64": "0.19.8",
"@esbuild/darwin-arm64": "0.19.8",
"@esbuild/darwin-x64": "0.19.8",
"@esbuild/freebsd-arm64": "0.19.8",
"@esbuild/freebsd-x64": "0.19.8",
"@esbuild/linux-arm": "0.19.8",
"@esbuild/linux-arm64": "0.19.8",
"@esbuild/linux-ia32": "0.19.8",
"@esbuild/linux-loong64": "0.19.8",
"@esbuild/linux-mips64el": "0.19.8",
"@esbuild/linux-ppc64": "0.19.8",
"@esbuild/linux-riscv64": "0.19.8",
"@esbuild/linux-s390x": "0.19.8",
"@esbuild/linux-x64": "0.19.8",
"@esbuild/netbsd-x64": "0.19.8",
"@esbuild/openbsd-x64": "0.19.8",
"@esbuild/sunos-x64": "0.19.8",
"@esbuild/win32-arm64": "0.19.8",
"@esbuild/win32-ia32": "0.19.8",
"@esbuild/win32-x64": "0.19.8"
"@esbuild/aix-ppc64": "0.19.12",
"@esbuild/android-arm": "0.19.12",
"@esbuild/android-arm64": "0.19.12",
"@esbuild/android-x64": "0.19.12",
"@esbuild/darwin-arm64": "0.19.12",
"@esbuild/darwin-x64": "0.19.12",
"@esbuild/freebsd-arm64": "0.19.12",
"@esbuild/freebsd-x64": "0.19.12",
"@esbuild/linux-arm": "0.19.12",
"@esbuild/linux-arm64": "0.19.12",
"@esbuild/linux-ia32": "0.19.12",
"@esbuild/linux-loong64": "0.19.12",
"@esbuild/linux-mips64el": "0.19.12",
"@esbuild/linux-ppc64": "0.19.12",
"@esbuild/linux-riscv64": "0.19.12",
"@esbuild/linux-s390x": "0.19.12",
"@esbuild/linux-x64": "0.19.12",
"@esbuild/netbsd-x64": "0.19.12",
"@esbuild/openbsd-x64": "0.19.12",
"@esbuild/sunos-x64": "0.19.12",
"@esbuild/win32-arm64": "0.19.12",
"@esbuild/win32-ia32": "0.19.12",
"@esbuild/win32-x64": "0.19.12"
}
},
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"dev": true,
"engines": {
"node": ">=6"
@ -1382,9 +1390,9 @@
"dev": true
},
"node_modules/fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
"dev": true,
"dependencies": {
"reusify": "^1.0.4"
@ -1445,9 +1453,9 @@
}
},
"node_modules/flatted": {
"version": "3.2.9",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
"dev": true
},
"node_modules/fs-extra": {
@ -1512,9 +1520,9 @@
}
},
"node_modules/globals": {
"version": "13.23.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
"integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
"version": "13.24.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@ -1568,9 +1576,9 @@
}
},
"node_modules/ignore": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
"dev": true,
"engines": {
"node": ">= 4"
@ -1822,17 +1830,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -1889,17 +1886,17 @@
}
},
"node_modules/optionator": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
"integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
"dependencies": {
"@aashutoshrathi/word-wrap": "^1.2.3",
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
"type-check": "^0.4.0"
"type-check": "^0.4.0",
"word-wrap": "^1.2.5"
},
"engines": {
"node": ">= 0.8.0"
@ -2040,9 +2037,9 @@
"dev": true
},
"node_modules/regenerator-runtime": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"dev": true
},
"node_modules/require-directory": {
@ -2121,12 +2118,9 @@
}
},
"node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
"bin": {
"semver": "bin/semver.js"
},
@ -2260,12 +2254,12 @@
}
},
"node_modules/ts-api-utils": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
"integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
"integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
"dev": true,
"engines": {
"node": ">=16.13.0"
"node": ">=16"
},
"peerDependencies": {
"typescript": ">=4.2.0"
@ -2422,6 +2416,15 @@
"node": ">= 8"
}
},
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@ -2454,11 +2457,6 @@
"node": ">=10"
}
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",

View file

@ -1,5 +1,5 @@
{
"name": "didactic-chainsaw-dsl",
"name": "JSTQL",
"description": "Please enter a brief description here",
"version": "0.0.1",
"files": [
@ -32,7 +32,7 @@
"concurrently": "~8.2.1",
"esbuild": "~0.19.2"
},
"displayName": "didactic-chainsaw-dsl",
"displayName": "JSTQL",
"engines": {
"vscode": "^1.67.0",
"node": ">=16.0.0"
@ -43,28 +43,28 @@
"contributes": {
"languages": [
{
"id": "js-transform-lang",
"id": "jstql",
"aliases": [
"js-transform-lang",
"js-transform-lang"
"JSTQL",
"jstql"
],
"extensions": [".jstl"],
"extensions": [".jstql"],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "js-transform-lang",
"scopeName": "source.js-transform-lang",
"path": "syntaxes/js-transform-lang.tmLanguage.json"
"language": "jstql",
"scopeName": "source.jstql",
"path": "syntaxes/jstql.tmLanguage.json"
}
]
},
"activationEvents": [
"onLanguage:js-transform-lang"
"onLanguage:jstql"
],
"main": "./out/extension/main.cjs",
"bin": {
"js-transform-lang-cli": "./bin/cli.js"
"jstql-cli": "./bin/cli.js"
}
}

View file

@ -1,8 +1,8 @@
import type { Model } from '../language/generated/ast.js';
import chalk from 'chalk';
import { Command } from 'commander';
import { JsTransformLangLanguageMetaData } from '../language/generated/module.js';
import { createJsTransformLangServices } from '../language/js-transform-lang-module.js';
import { JstqlLanguageMetaData } from '../language/generated/module.js';
import { createJstqlServices } from '../language/jstql-module.js';
import { extractAstNode } from './cli-util.js';
import { generateJavaScript } from './generator.js';
import { NodeFileSystem } from 'langium/node';
@ -15,7 +15,7 @@ const packagePath = path.resolve(__dirname, '..', '..', 'package.json');
const packageContent = await fs.readFile(packagePath, 'utf-8');
export const generateAction = async (fileName: string, opts: GenerateOptions): Promise<void> => {
const services = createJsTransformLangServices(NodeFileSystem).JsTransformLang;
const services = createJstqlServices(NodeFileSystem).Jstql;
const model = await extractAstNode<Model>(fileName, services);
const generatedFilePath = generateJavaScript(model, fileName, opts.destination);
console.log(chalk.green(`JavaScript code generated successfully: ${generatedFilePath}`));
@ -30,7 +30,7 @@ export default function(): void {
program.version(JSON.parse(packageContent).version);
const fileExtensions = JsTransformLangLanguageMetaData.fileExtensions.join(', ');
const fileExtensions = JstqlLanguageMetaData.fileExtensions.join(', ');
program
.command('generate')
.argument('<file>', `source file (possible file extensions: ${fileExtensions})`)

View file

@ -32,12 +32,12 @@ function startLanguageClient(context: vscode.ExtensionContext): LanguageClient {
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
};
const fileSystemWatcher = vscode.workspace.createFileSystemWatcher('**/*.jstl');
const fileSystemWatcher = vscode.workspace.createFileSystemWatcher('**/*.jstql');
context.subscriptions.push(fileSystemWatcher);
// Options to control the language client
const clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: 'file', language: 'js-transform-lang' }],
documentSelector: [{ scheme: 'file', language: 'jstql' }],
synchronize: {
// Notify the server about file changes to files contained in the workspace
fileEvents: fileSystemWatcher
@ -46,8 +46,8 @@ function startLanguageClient(context: vscode.ExtensionContext): LanguageClient {
// Create the language client and start the client.
const client = new LanguageClient(
'js-transform-lang',
'js-transform-lang',
'jstql',
'JSTQL',
serverOptions,
clientOptions
);

View file

@ -0,0 +1,63 @@
import type { DefaultSharedModuleContext, LangiumServices, LangiumSharedServices, Module, PartialLangiumServices } from 'langium';
import { createDefaultModule, createDefaultSharedModule, inject } from 'langium';
import { JstqlGeneratedModule, JstqlGeneratedSharedModule } from './generated/module.js';
import { JstqlValidator, registerValidationChecks } from './jstql-validator.js';
/**
* Declaration of custom services - add your own service classes here.
*/
export type JstqlAddedServices = {
validation: {
JstqlValidator: JstqlValidator
}
}
/**
* Union of Langium default services and your custom services - use this as constructor parameter
* of custom service classes.
*/
export type JstqlServices = LangiumServices & JstqlAddedServices
/**
* Dependency injection module that overrides Langium default services and contributes the
* declared custom services. The Langium defaults can be partially specified to override only
* selected services, while the custom services must be fully specified.
*/
export const JstqlModule: Module<JstqlServices, PartialLangiumServices & JstqlAddedServices> = {
validation: {
JstqlValidator: () => new JstqlValidator()
}
};
/**
* Create the full set of services required by Langium.
*
* First inject the shared services by merging two modules:
* - Langium default shared services
* - Services generated by langium-cli
*
* Then inject the language-specific services by merging three modules:
* - Langium default language-specific services
* - Services generated by langium-cli
* - Services specified in this file
*
* @param context Optional module context with the LSP connection
* @returns An object wrapping the shared services and the language-specific services
*/
export function createJstqlServices(context: DefaultSharedModuleContext): {
shared: LangiumSharedServices,
Jstql: JstqlServices
} {
const shared = inject(
createDefaultSharedModule(context),
JstqlGeneratedSharedModule
);
const Jstql = inject(
createDefaultModule({ shared }),
JstqlGeneratedModule,
JstqlModule
);
shared.ServiceRegistry.register(Jstql);
registerValidationChecks(Jstql);
return { shared, Jstql };
}

View file

@ -0,0 +1,124 @@
import type { ValidationAcceptor, ValidationChecks } from "langium";
import type { JstqlAstType, Pair } from "./generated/ast.js";
import type { JstqlServices } from "./jstql-module.js";
/**
* Register custom validation checks.
*/
export function registerValidationChecks(services: JstqlServices) {
const registry = services.validation.ValidationRegistry;
const validator = services.validation.JstqlValidator;
const checks: ValidationChecks<JstqlAstType> = {
Pair: validator.validateWildcardAplTo,
};
registry.register(checks, validator);
}
/**
* Implementation of custom validations.
*/
export class JstqlValidator {
validateWildcardAplTo(pair: Pair, accept: ValidationAcceptor): void {
let validationResultAplTo = validateWildcardAplTo(
collectWildcard(pair.aplTo.apl_to_code.split(""))
);
if (validationResultAplTo.errors.length != 0) {
accept("error", validationResultAplTo.errors.join("\n"), {
node: pair.aplTo,
property: "apl_to_code",
});
}
let validationResultTraTo = validateWildcardTraTo(
collectWildcard(pair.traTo.transform_to_code.split("")),
validationResultAplTo.env
);
if (validationResultTraTo.length != 0) {
accept("error", validationResultTraTo.join("\n"), {
node: pair.traTo,
property: "transform_to_code",
});
}
}
}
function validateWildcardTraTo(wildcards: string[], env: string[]): string[] {
let errors: string[] = [];
for (let wildcard of wildcards) {
if (!env.includes(wildcard)) {
errors.push(
"Wildcard " +
wildcard +
" Is not declared in applicable to block"
);
}
}
return errors;
}
interface ValidationResultAplTo {
env: string[];
errors: string[];
}
function validateWildcardAplTo(wildcards: string[]): ValidationResultAplTo {
let env = [];
let errors = [];
for (let wildcard of wildcards) {
let [identifier, types, ..._] = wildcard.split(":");
env.push(identifier);
if (_.length > 0) {
errors.push("Too many : in wildcard");
}
if (!types) {
errors.push("No types given for value");
}
}
return { env, errors };
}
function collectWildcard(code: string[]): string[] {
let flag = false;
let wildcards: string[] = [];
let wildcard = "";
for (let i = 0; i < code.length; i++) {
if (i != code.length && code[i] === ">" && code[i + 1] === ">") {
flag = false;
wildcards.push(wildcard.replace(/\s/g, ""));
wildcard = "";
i += 1;
}
if (flag) {
wildcard += code[i];
}
if (i != code.length - 1 && code[i] === "<" && code[i + 1] === "<") {
flag = true;
i += 1;
}
}
console.log(wildcards);
return wildcards;
}
function testValidator() {
let res = validateWildcardAplTo(
collectWildcard(
`() => {
<<blockStatements: anyStatementList>>
return << returnExpr: Expr >>
}`.split("")
)
);
console.log(res);
let res2 = validateWildcardTraTo(
collectWildcard(
`<< blockStatements >>
<< returnExpr >>`.split("")
),
res.env
);
console.log(res2);
}
testValidator();

View file

@ -0,0 +1,27 @@
grammar Jstql
entry Model:
(proposals+=Proposal)*;
Proposal:
'proposal' name=ID "{"
(pair+=Pair)+
"}";
Pair:
"pair" name=ID "{"
aplTo=ApplicableTo
traTo=TraTo
"}";
ApplicableTo:
"applicable" "to" "{"
apl_to_code=STRING
"}";
TraTo:
"transform" "to" "{"
transform_to_code=STRING
"}";
hidden terminal WS: /\s+/;
terminal ID: /[_a-zA-Z][\w_]*/;
terminal STRING: /"[^"]*"|'[^']*'/;

View file

@ -1,13 +1,13 @@
import { startLanguageServer } from 'langium';
import { NodeFileSystem } from 'langium/node';
import { createConnection, ProposedFeatures } from 'vscode-languageserver/node.js';
import { createJsTransformLangServices } from './js-transform-lang-module.js';
import { createJstqlServices } from './jstql-module.js';
// Create a connection to the client
const connection = createConnection(ProposedFeatures.all);
// Inject the shared services and language-specific services
const { shared } = createJsTransformLangServices({ connection, ...NodeFileSystem });
const { shared } = createJstqlServices({ connection, ...NodeFileSystem });
// Start the language server with the shared services
startLanguageServer(shared);

1
babel

@ -1 +0,0 @@
Subproject commit 2f9c48d4eda2d69908fc53ea285f47ed2c540f7e

BIN
bun.lockb

Binary file not shown.

View file

@ -1,14 +0,0 @@
{
"projectName": "JsTransformLang",
"languages": [
{
"id": "js-transform-lang",
"grammar": "src/language/js-transform-lang.langium",
"fileExtensions": [".jstl"],
"textMate": {
"out": "syntaxes/js-transform-lang.tmLanguage.json"
}
}
],
"out": "src/language/generated"
}

View file

@ -1,18 +0,0 @@
grammar JsTransformLang
terminal ID: /[_a-zA-Z][\w_]*/;
terminal STRING: /"(\\.|[^"\\])*"|'(\\.|[^'\\])*'/;
entry Model:
proposals+=Proposal*;
Proposal:
"proposal" proposalName=ID "{"
"applicable" "to" "{"
code=STRING
"}"
"replace" "with" "{"
code=STRING
"}"
"}";

View file

@ -1,85 +0,0 @@
import type {
DefaultSharedModuleContext,
LangiumServices,
LangiumSharedServices,
Module,
PartialLangiumServices,
} from "langium";
import {
createDefaultModule,
createDefaultSharedModule,
inject,
} from "langium";
import {
JsTransformLangGeneratedModule,
JsTransformLangGeneratedSharedModule,
} from "./generated/module.js";
import {
JsTransformLangValidator,
registerValidationChecks,
} from "./js-transform-lang-validator.js";
/**
* Declaration of custom services - add your own service classes here.
*/
export type JsTransformLangAddedServices = {
validation: {
JsTransformLangValidator: JsTransformLangValidator;
};
};
/**
* Union of Langium default services and your custom services - use this as constructor parameter
* of custom service classes.
*/
export type JsTransformLangServices = LangiumServices &
JsTransformLangAddedServices;
/**
* Dependency injection module that overrides Langium default services and contributes the
* declared custom services. The Langium defaults can be partially specified to override only
* selected services, while the custom services must be fully specified.
*/
export const JsTransformLangModule: Module<
JsTransformLangServices,
PartialLangiumServices & JsTransformLangAddedServices
> = {
validation: {
JsTransformLangValidator: () => new JsTransformLangValidator(),
},
};
/**
* Create the full set of services required by Langium.
*
* First inject the shared services by merging two modules:
* - Langium default shared services
* - Services generated by langium-cli
*
* Then inject the language-specific services by merging three modules:
* - Langium default language-specific services
* - Services generated by langium-cli
* - Services specified in this file
*
* @param context Optional module context with the LSP connection
* @returns An object wrapping the shared services and the language-specific services
*/
export function createJsTransformLangServices(
context: DefaultSharedModuleContext
): {
shared: LangiumSharedServices;
JsTransformLang: JsTransformLangServices;
} {
const shared = inject(
createDefaultSharedModule(context),
JsTransformLangGeneratedSharedModule
);
const JsTransformLang = inject(
createDefaultModule({ shared }),
JsTransformLangGeneratedModule,
JsTransformLangModule
);
shared.ServiceRegistry.register(JsTransformLang);
registerValidationChecks(JsTransformLang);
return { shared, JsTransformLang };
}

View file

@ -1,36 +0,0 @@
import type { ValidationChecks } from "langium";
import type { JsTransformLangAstType } from "./generated/ast.js";
import type { JsTransformLangServices } from "./js-transform-lang-module.js";
/**
* Register custom validation checks.
*/
export function registerValidationChecks(services: JsTransformLangServices) {
const registry = services.validation.ValidationRegistry;
const validator = services.validation.JsTransformLangValidator;
const checks: ValidationChecks<JsTransformLangAstType> = {
//Person: validator.checkPersonStartsWithCapital,
};
registry.register(checks, validator);
}
/**
* Implementation of custom validations.
*/
export class JsTransformLangValidator {
/*
checkPersonStartsWithCapital(
proposal: Proposal,
accept: ValidationAcceptor
): void {
if (proposal.code) {
if (proposal.code === "") {
accept("warning", "You are running with empty code here", {
node: proposal,
property: "code",
});
}
}
}
*/
}

View file

@ -1,32 +0,0 @@
grammar JsTransformLang
entry Model:
(proposals+=Proposal)*;
Proposal:
'proposal' name=ID "{"
"applicable" "to" "{"
code=RICH_TEXT
"}"
"replace" "with" "{"
"}"
"}";
hidden terminal WS: /\s+/;
terminal ID: /[_a-zA-Z][\w_]*/;
terminal fragment IN_RICH_STRING:
"''" !('«'|"'")
| "'" !('«'|"'");
//| !('«'|"'");
terminal STRING: /"(\\.|[^"\\])*"|'(\\.|[^'\\])*'/;
hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
terminal RICH_TEXT: "'''" IN_RICH_STRING* ("'''"| ("'" "'"?)? );
terminal RICH_TEXT_START: "'''" IN_RICH_STRING* ("'" "'"?)? '«';
terminal RICH_TEXT_END: '»' IN_RICH_STRING* ("'''"| ("'" "'"?)? );
terminal RICH_TEXT_INBETWEEN: '»' IN_RICH_STRING* ("'" "'"?)? '«';
terminal COMMENT_RICH_TEXT_INBETWEEN: "««" !('\n'|'\r')* ('\r'? '\n' IN_RICH_STRING* ("'" "'"?)? '«')?;
terminal COMMENT_RICH_TEXT_END: "««" !('\n'|'\r')* (('\r'? '\n' IN_RICH_STRING* ("'''"| ("'" "'"?)? )) );

32
dsl_files/test.jstql Normal file
View file

@ -0,0 +1,32 @@
proposal DoExpression{
pair arrowFunction{
applicable to {
"() => {
<<blockStatements: anyStatementList>>
return << returnExpr: Expr >>
}"
}
transform to {
"do {
<< blockStatementsss >>
<< returnExpr >>
}"
}
}
pair immediatelyInvokedUnnamedFunction {
applicable to {
"function(){
<<blockStatements: anyNStatements>>
return << returnExpr: Expr >>
}();"
}
transform to {
"do {
<< blockStatements >>
<< returnExpr >>
}"
}
}
}

View file

@ -1,19 +1,11 @@
proposal p1 {
applicable to {
"let a = 0;"
}
replace with {
"SOMETHING"
}
}
proposal p2 {
applicable to {
"let a = 0;"
}
replace with {
"SOMETHING"
pair something{
applicable to {
"let a = 0;"
}
transform to {
""
}
}
}

120
output.js
View file

@ -1,120 +0,0 @@
require("@risingstack/trace");
const Discord = require("discord.js");
const ytdl = require("ytdl-core");
const bot = new Discord.Client();
const fs = new require("fs");
const path = require("path");
const probe = require("pmx").probe();
const jsonfile = require("jsonfile");
const commandCooldown = require("./helpers/commandCooldown.js");
let cleverbot = require("cleverbot.io"),
clever = new cleverbot("jp6wu9XZbYdoICmo", "54jV1VcMNxGQyc2cdKUFUpjkPVo3bTr2");
const log = require("./helpers/log.js");
bot.on("ready", () => {
bot.user.setGame(".help");
(function loop(i) {
setTimeout(function () {
bot.guilds.size |> guilds.set(%);
if (true) {
loop(i);
}
}, 1000);
})(10);
log(`Ready to serve ${bot.users.size} users, in ${bot.channels.size} channels of ${bot.guilds.size} servers.`);
});
fs.readFile("config.json", (err, data) => {
if (err) {
log("Config file does not exist, creating one.");
let obj = {
discordToken: "TOKEN",
discordBotsToken: "TOKEN"
};
jsonfile.spaces = 4;
jsonfile.writeFile("config.json", obj, err => {
err |> console.log(%);
});
process.exit(1);
} else {
config = require("./config.json");
config.discordToken |> bot.login(%);
}
});
global.skips = {};
global.queue = {
test: "test"
};
global.dispatchers = new Map();
global.connections = new Map();
global.voices = new Map();
global.streams = new Map();
let config = "ERR";
global.allstreams = 0;
global.counter = probe.counter({
name: "Streams"
});
let guilds = probe.metric({
name: "Guilds"
});
let userCooldown = new Map();
bot.commands = new Discord.Collection();
bot.aliases = new Discord.Collection();
fs.readdir("./commands/", (err, files) => {
if (err) err |> console.error(%);
log(`Loading a total of ${files.length} commands.`);
files.forEach(f => {
let props = require(`./commands/${f}`);
log(`Loading Command: ${props.info.name}. :ok_hand:`);
bot.commands.set(props.info.name, props);
/*
props.conf.aliases.forEach(alias => {
bot.aliases.set(alias, props.info.name);
});
*/
});
});
bot.on("message", msg => {
const prefix = ".";
let id = bot.user.id;
let clevername = new RegExp(`^<@!?${id}>`);
if (msg.content.startsWith(prefix)) {} else if (clevername.test(msg.content)) {} else return;
if (msg.author.bot) return;
if (msg.guild) {
if (!queue[msg.guild.id]) {
queue[msg.guild.id] = [];
}
} else return;
let command = msg.content.split(" ")[0].slice(prefix.length);
let params = msg.content.split(" ").slice(1);
//let perms = bot.elevation(msg);
let cmd;
if (!userCooldown.get(msg.author.id)) {
userCooldown.set(msg.author.id, 0);
}
if (bot.commands.has(command)) {
if (!commandCooldown(userCooldown.get(msg.author.id))) {
userCooldown.set(msg.author.id, Date.now());
cmd = bot.commands.get(command);
} else msg.channel.sendMessage("You're sending commands too quickly!");
} else if (bot.aliases.has(command)) {
cmd = bot.commands.get(bot.aliases.get(command));
}
if (cmd) {
cmd.run(bot, msg, params);
}
if (clevername.test(msg.content)) {
msg.author.username + " (" + msg.author.id + ") issued command: " + msg.content |> console.log(%);
let string = msg.content;
string = msg.content.split(" ");
string.shift();
" " |> string.join(%);
msg.author.username |> clever.setNick(%);
clever.create(function (err, session) {
if (err) log(err);
clever.ask(string, function (err, response) {
if (err) log(err);
msg.channel.sendMessage(response).then(msg => log(`Sent message: ${msg.content}`)).catch(console.error);
});
});
}
});

View file

@ -2,7 +2,14 @@
import * as babelparser from "@babel/parser";
//import core from "../babel/packages/babel-core";
import { parse_with_plugins } from "./parser/parse";
import { TransformRecipe, transform } from "./transform/transform";
import {
SelfHostedRecipe,
TransformRecipe,
transform,
} from "./transform/transform";
import { parseDSLtoAST } from "../didactic-chainsaw-dsl/src/JSTQL_interface/fetchAST";
import { parseJSTQL } from "./langium/langiumRunner";
/*
proposal await_to_promise {
applicable to {
@ -55,12 +62,11 @@ proposal pipeline_simple{
}
}
some(someOther);
*/
const transformExample: TransformRecipe = {
applicableTo: `<<a>>(<<b:Expression|Identifier>>);`,
transformTo: "b |> a(%)",
};
const code =
"a(something);a(1+1);something(some_other_thing + 1 + 10 + 100); console.log(a)";
@ -88,14 +94,65 @@ const test: TransformRecipe = {
applicableTo: "let <<x>> = 0;",
transformTo: "if (true) {console.log(<<x>>)};",
};
const path = "../test.js";
let codePresent = `
let x = 42;
let y = 19235;
let word = "This should remain unchanged";
let z = 1337;`;
const presentationTest: TransformRecipe = {
applicableTo: "let <<variableName:Identifier>> = <<value>>;",
transformTo: "let variableName = 13;",
};
const transformExample: TransformRecipe = {
applicableTo: `<<a>>(<<b:Expression>>)>>`,
transformTo: "b |> a(%)",
};
const selfHostedTransformExample: SelfHostedRecipe = {
prelude: `let a = Identifier; let b = Identifier`,
applicableTo: `a(b);`,
transformTo: "b |> a(%);",
};
const selfHostedTest = `
something(a);
`;
const selfHostedTransformExampleMultiStmt: SelfHostedRecipe = {
prelude: `let a = [Identifier, MemberExpression]; let b = [Expression]; let c = anyNumberArgs`,
applicableTo: `a(b);`,
transformTo: "b |> a(%);",
};
const selfHostedTestMultiStmt = `
let ddddddd = something(someOtherThing);
yoink.haha(hahahaha);
console.log(cccccc, dddddd);
`;
const path = "test.js";
const file = Bun.file(path);
const codeFromFile = await file.text();
const main = async () => {
//transform(selfHostedTransformExampleMultiStmt, codeFromFile);
const jstql_file =
"/home/rolfmg/Coding/Master/didactic-chainsaw/dsl_files/test_hello.jstl";
const test_file = Bun.file(jstql_file);
const test_JSTQL = await test_file.text();
console.log(parseJSTQL(test_JSTQL));
/*
await Bun.write(
"../output.js",
transform(simpleTransformExample, codeFromFile)
transform(selfHostedTransformExampleMultiStmt, codeFromFile)
);
console.log(
transform(selfHostedTransformExampleMultiStmt, selfHostedTestMultiStmt)
);
*/
};
main();

View file

@ -0,0 +1,5 @@
import { TransformRecipe } from "../transform/transform";
export function parseJSTQL(jstql: string): TransformRecipe {
console.log((await parseDSLtoAST(test_JSTQL)).proposals[0].code);
}

View file

@ -19,138 +19,147 @@ export interface PairedNodes {
export function runMatch(
code: TreeNode<t.Node>,
applicableTo: TreeNode<t.Node>,
internals: Map<string, InternalDSLVariable>
internals: InternalDSLVariable
): TreeNode<PairedNodes>[] {
let matches: TreeNode<t.Node>[] = [];
function checkDSLInternals(code_node: t.Node, aplTo: t.Node): boolean {
if (aplTo.type == "Identifier" && internals.has(aplTo.name)) {
let dsl_types = internals.get(aplTo.name)?.type ?? [];
for (const dsl_type of dsl_types) {
if (dsl_type == "Expression") {
if (
code_node.type.includes("Expression") ||
code_node.type == "StringLiteral"
) {
return true;
}
} else if (dsl_type == "") {
if (
code_node.type == "Identifier" &&
aplTo.type == "Identifier"
) {
return true;
}
} else if (dsl_type == "Identifier") {
if (code_node.type == "Identifier") {
return true;
}
}
}
}
return false;
// Special case for a single expression, we have to remove "ExpressionStatement" node.
if (
applicableTo.children.length === 1 &&
applicableTo.children[0].element.type === "ExpressionStatement"
) {
let matcher = new Matcher(
internals,
applicableTo.children[0].children[0].element
);
matcher.singleExprMatcher(code, applicableTo.children[0].children[0]);
return matcher.matches;
} else {
let matcher = new Matcher(internals, applicableTo.element);
matcher.multiStatementMatcher(code, applicableTo);
return matcher.matches;
}
function match(
code: TreeNode<t.Node>,
applicableTo: TreeNode<t.Node>
): boolean {
if (code.element.type == "Program") {
code.children.forEach((code_child) => {
match(code_child, applicableTo);
});
}
// This is a bit wierd, as we currently do not support having ApplicableTo be multiple statements
if (applicableTo.element.type == "Program") {
match(code, applicableTo.children[0]);
}
let node_matches = checkCodeNode(code.element, applicableTo.element);
//If element matches DSL internals, we return right away and ignore the contents
if (checkDSLInternals(code.element, applicableTo.element)) {
return true;
}
if (node_matches) {
if (applicableTo.children.length != code.children.length) {
return false;
}
for (let i = 0; i < applicableTo.children.length; i++) {
//Verify we can actually do a match
if (!match(code.children[i], applicableTo.children[i])) {
return false;
}
}
return true;
} else {
for (let code_child of code.children) {
//Avoid matching on single identifier
if (code_child.element.type == "Identifier") {
continue;
}
if (match(code_child, applicableTo)) {
matches.push(code_child);
}
}
return false;
}
}
match(code, applicableTo);
console.log(matches.length);
return matches
.map((match) => pairMatch(match, applicableTo))
.filter((match) => match != null);
}
function pairMatch(
match: TreeNode<t.Node>,
aplTo: TreeNode<t.Node>
): TreeNode<PairedNodes> | null {
if (aplTo.element.type == "Program") {
return pairMatch(match, aplTo.children[0]);
export class Matcher {
public matches: TreeNode<PairedNodes>[];
private internals: InternalDSLVariable;
private aplToFull: t.Node;
constructor(internals: InternalDSLVariable, aplToFull: t.Node) {
this.matches = [];
this.internals = internals;
this.aplToFull = aplToFull;
}
try {
let node: TreeNode<PairedNodes> = new TreeNode(null, {
codeNode: match.element,
singleExprMatcher(
code: TreeNode<t.Node>,
aplTo: TreeNode<t.Node>
): TreeNode<PairedNodes> | undefined {
let curMatches = this.checkCodeNode(code.element, aplTo.element);
curMatches =
curMatches && code.children.length >= aplTo.children.length;
// Current does not match and we have searched all the children, so just return early
// This ensures we only store the child search when we don't only have a partial match
let temp = [];
// If any matches bubble up from child nodes, we have to store it
for (let code_child of code.children) {
let maybeChildMatch = this.singleExprMatcher(code_child, aplTo);
if (maybeChildMatch) {
temp.push(maybeChildMatch);
}
}
// Filter the output for full matches :)
this.matches.push(
...temp.filter((x) => x.element.aplToNode === this.aplToFull)
);
if (!curMatches) {
return;
}
// At this point current does match
let pairedCurrent: TreeNode<PairedNodes> = new TreeNode(null, {
codeNode: code.element,
aplToNode: aplTo.element,
});
for (let i = 0; i < aplTo.children.length; i++) {
let child = pairMatch(match.children[i], aplTo.children[i]);
child.parent = node;
node.children.push(child);
let childSearch = this.singleExprMatcher(
code.children[i],
aplTo.children[i]
);
if (childSearch === undefined) {
// Failed to get a full match, so break here
return;
}
childSearch.parent = pairedCurrent;
pairedCurrent.children.push(childSearch);
}
return node;
} catch (exception) {
return null;
}
}
function checkCodeNode(code_node: t.Node, aplTo: t.Node): boolean {
if (code_node.type != aplTo.type) {
return false;
// If we are here, a full match has been found
return pairedCurrent;
}
//If not an internal DSL variable, gotta verify that the identifier is the same
if (code_node.type === "Identifier" && aplTo.type === "Identifier") {
if (code_node.name != aplTo.name) {
// This is broken
multiStatementMatcher(code: TreeNode<t.Node>, aplTo: TreeNode<t.Node>) {
console.log("Currently unsupported");
}
match(code: TreeNode<t.Node>, aplTo: TreeNode<t.Node>) {}
private checkCodeNode(code_node: t.Node, aplTo: t.Node): boolean {
// First verify the internal DSL variables
if (aplTo.type === "Identifier") {
if (aplTo.name in this.internals) {
if (this.internals[aplTo.name].includes(code_node.type)) {
return true;
}
if (this.internals[aplTo.name].includes("Expression")) {
return t.isExpression(code_node);
}
}
}
if (code_node.type != aplTo.type) {
return false;
}
}
for (let key of Object.keys(aplTo)) {
if (key in keys_to_ignore) {
continue;
//If not an internal DSL variable, gotta verify that the identifier is the same
if (code_node.type === "Identifier" && aplTo.type === "Identifier") {
if (code_node.name != aplTo.name) {
return false;
}
}
for (let key of Object.keys(aplTo)) {
if (key in keys_to_ignore) {
continue;
}
if (!Object.keys(code_node).includes(key)) {
return false;
}
}
if (!Object.keys(code_node).includes(key)) {
return false;
}
return true;
}
return true;
private buildPairTree(
code: TreeNode<t.Node>,
aplTo: TreeNode<t.Node>
): TreeNode<PairedNodes> {
let temp: TreeNode<PairedNodes> = new TreeNode(null, {
codeNode: code.element,
aplToNode: aplTo.element,
});
if (code.children.length >= aplTo.children.length) {
for (let i = 0; i < aplTo.children.length; i++) {
let child = this.buildPairTree(
code.children[i],
aplTo.children[i]
);
temp.children.push(child);
}
} else {
console.log("ERROR");
}
return temp;
}
}

View file

@ -1,11 +0,0 @@
import * as t from "@babel/types";
export interface InternalJsMap{
CallExpression:
}

View file

@ -3,69 +3,66 @@ import * as babelparser from "@babel/parser";
import * as t from "@babel/types";
export interface InternalDSLVariable {
type: string[];
dsl_name: string;
[internals: string]: string[];
}
export interface InternalParseResult {
internals: Map<string, InternalDSLVariable>;
prelude: InternalDSLVariable;
cleanedJS: string;
}
export function parseInternal(applicableTo: string): InternalParseResult {
let lastChar: null | string = null;
let inDslParseMode = false;
export function parseInternal(code: string): InternalParseResult {
let cleanedJS = "";
let temp = "";
let flag = false;
let prelude: InternalDSLVariable = {};
let inDslParseString = "";
let internalParseResult: InternalParseResult = {
internals: new Map(),
cleanedJS: "",
};
for (let char of applicableTo) {
if (inDslParseMode) {
if (char == ">" && lastChar == ">") {
//remove first closing >
inDslParseString = inDslParseString.slice(0, -1);
let { identifier, type, replaceWith } =
parseInternalString(inDslParseString);
internalParseResult.cleanedJS += replaceWith;
internalParseResult.internals.set("___" + identifier, {
type: type,
dsl_name: identifier,
});
inDslParseString = "";
inDslParseMode = false;
continue;
}
inDslParseString += char;
} else {
if (char == "<" && lastChar == "<") {
//Remove previous <
internalParseResult.cleanedJS =
internalParseResult.cleanedJS.slice(0, -1);
inDslParseMode = true;
continue;
}
internalParseResult.cleanedJS += char;
for (let i = 0; i < code.length; i++) {
if (code[i] === "<" && code[i + 1] === "<") {
// From now in we are inside of the DSL custom block
flag = true;
i += 1;
continue;
}
lastChar = char;
}
if (flag && code[i] === ">" && code[i + 1] === ">") {
// We encountered a closing tag
flag = false;
let { identifier, types } = parseInternalString(temp);
return internalParseResult;
cleanedJS += identifier;
prelude[identifier] = types;
i += 1;
temp = "";
continue;
}
if (flag) {
temp += code[i];
} else {
cleanedJS += code[i];
}
}
return { prelude, cleanedJS };
}
function parseInternalString(dslString: string) {
let splitted = dslString.split(":");
function parseInternalString(dslString: string): {
identifier: string;
types: string[];
} {
let [identifier, typeString, ..._] = dslString
.replace(/\s/g, "")
.split(":");
if (_.length > 0) {
// This is an error, and it means we probably have encountered two bitshift operators
throw new Error("Probably encountered bitshift");
}
return {
identifier: splitted[0],
type: splitted.length > 1 ? splitted[1].split("|") : [""],
replaceWith: "___" + splitted[0],
identifier,
types: typeString.length > 0 ? typeString.split("|") : [""],
};
}
@ -76,3 +73,10 @@ export function parse_with_plugins(
plugins: [["pipelineOperator", { proposal: "hack", topicToken: "%" }]],
});
}
function testParseInternal() {
parseInternal(`
<<a:Identifier>>(<< b : Identifier | MemberExpression >>);
`);
}
testParseInternal();

View file

@ -0,0 +1,49 @@
import { InternalDSLVariable, parse_with_plugins } from "./parse";
import * as t from "@babel/types";
export function preludeBuilder(prelude: string) {
let parsedPrelude = parse_with_plugins(prelude).program.body;
return extractValues(parsedPrelude);
}
function extractValues(types: t.Statement[]): InternalDSLVariable {
let prelude: InternalDSLVariable = {};
for (let stmt of types) {
if (stmt.type == "VariableDeclaration") {
stmt = <t.VariableDeclaration>stmt;
let declaration = stmt.declarations[0];
let innerDSLVariableName = (declaration.id as t.Identifier).name;
let init = declaration.init;
if (init) {
if (init.type == "ArrayExpression") {
init = <t.ArrayExpression>init;
let temp = [];
for (let elem of init.elements) {
if (elem && elem.type == "Identifier") {
temp.push(elem.name);
} else {
throw new Error(
"Usage of non variable declaration in Prelude Array"
);
}
}
prelude[innerDSLVariableName] = temp;
} else if (init.type === "Identifier") {
init = <t.Identifier>init;
prelude[innerDSLVariableName] = [init.name];
} else {
throw new Error(
"Invalid usage of right side declaration in prelude"
);
}
} else {
throw new Error("Empty wildcards are not legal");
}
} else {
throw new Error("Usage of non VariableDeclaration in Prelude");
}
}
return prelude;
}

View file

@ -10,20 +10,84 @@ import {
} from "../data_structures/tree";
import { runMatch } from "../matcher/matcher";
import { transformMatch, transformer } from "./transformMatch";
import { preludeBuilder } from "../parser/preludeBuilder";
export interface TransformRecipe {
applicableTo: string;
transformTo: string;
}
export interface SelfHostedRecipe extends TransformRecipe {
prelude: string;
}
export function transform(recipe: TransformRecipe, code: string) {
let { internals, cleanedJS } = parseInternal(recipe.applicableTo);
if ((<SelfHostedRecipe>recipe).prelude !== undefined) {
// We are using the self hosted version
return transformSelfHosted(<SelfHostedRecipe>recipe, code);
} else {
// We are using JSTQL
return transformJSTQL(recipe, code);
}
}
function transformSelfHosted(recipe: SelfHostedRecipe, code: string) {
let internals = preludeBuilder(recipe.prelude);
let codeAST = parse_with_plugins(code);
let codeTree = makeTree(codeAST);
let applicabelToAST = parse_with_plugins(cleanedJS);
let applicabelToAST = parse_with_plugins(recipe.applicableTo);
let applicableToTree = makeTree(applicabelToAST);
let transformTo = parse_with_plugins(recipe.transformTo);
let transformToTree = makeTree(transformTo);
if (
codeTree == undefined ||
applicableToTree == undefined ||
transformToTree == undefined
) {
throw new Error("This no worky LOL");
}
showTree(applicableToTree);
console.log();
let matches = runMatch(codeTree, applicableToTree, internals);
for (let match of matches) {
showTreePaired(match);
console.log(generate(match.element.codeNode).code);
}
console.log(matches.length);
return;
for (let match of matches) {
//console.log(transformToTree.element);
let output = structuredClone(transformToTree.element);
try {
transformer(match, transformToTree, output, codeAST);
} catch (error) {
console.log("We failed to transform an element!");
}
//let result = generate(transformToTreeClone.element);
//console.log(output);
console.log(generate(match.element.codeNode).code, "is turned into:");
console.log(generate(output, { topicToken: "%" }).code);
//console.log(generate(codeAST, { topicToken: "%" }).code);
console.log("\n");
}
console.log("Final generated code: \n");
let output = generate(codeAST, { topicToken: "%" }).code;
//showTree(transformToTree);
return output;
}
function transformJSTQL(recipe: TransformRecipe, code: string) {
let { prelude, cleanedJS } = parseInternal(recipe.applicableTo);
let codeAST = parse_with_plugins(code);
let codeTree = makeTree(codeAST);
let applicabelToAST = parse_with_plugins(cleanedJS);
console.dir(applicabelToAST, { depth: null });
let applicableToTree = makeTree(applicabelToAST);
let transformTo = parse_with_plugins(recipe.transformTo);
let transformToTree = makeTree(transformTo);
if (
codeTree == undefined ||
@ -33,7 +97,7 @@ export function transform(recipe: TransformRecipe, code: string) {
throw new Error("This no worky LOL");
}
let matches = runMatch(codeTree, applicableToTree, internals);
let matches = runMatch(codeTree, applicableToTree, prelude);
for (let match of matches) {
//console.log(transformToTree.element);

View file

@ -9,28 +9,31 @@ import {
showTreePaired,
} from "../data_structures/tree";
import { InternalDSLVariable } from "../parser/parse";
import { MatchedTreeNode, PairedNodes } from "../matcher/matcher";
import { Match, MatchedTreeNode, PairedNodes } from "../matcher/matcher";
import traverse from "@babel/traverse";
export function transformer(
match: TreeNode<PairedNodes>,
matches: Match,
trnTo: TreeNode<t.Node>,
output: t.Node,
inputCode: t.Node
) {
transformMatch(match, trnTo, output);
for (let match of matches.statements) {
transformMatch(match, trnTo, output);
}
if (output.type == "Program") {
output = output.body[0];
}
traverse(inputCode, {
enter(path) {
if (path.node === match.element.codeNode) {
console.log("We did stuffs?");
path.replaceWith(output);
}
},
});
for (let match of matches.statements)
traverse(inputCode, {
enter(path) {
if (path.node === match.element.codeNode) {
path.replaceWith(output);
}
},
});
}
export function transformMatch(
@ -87,7 +90,8 @@ function matchNode(aplTo: t.Node, trnTo: t.Node): boolean {
}
function washName(name: string): string {
if (name.startsWith("___")) {
return name;
if (name.startsWith("_-_")) {
return name.slice(3);
}
return name;

238
test.js
View file

@ -1,160 +1,108 @@
require("@risingstack/trace");
const Discord = require("discord.js");
const ytdl = require("ytdl-core");
const bot = new Discord.Client();
const fs = new require("fs");
const path = require("path");
const probe = require("pmx").probe();
const jsonfile = require("jsonfile");
const commandCooldown = require("./helpers/commandCooldown.js");
let cleverbot = require("cleverbot.io"),
clever = new cleverbot(
"jp6wu9XZbYdoICmo",
"54jV1VcMNxGQyc2cdKUFUpjkPVo3bTr2"
);
function parse() {
const input = document.getElementById("input").value;
const data = input.slice(32);
const log = require("./helpers/log.js");
const compressedData = decode_base64(data);
const uncompressed = pako.inflate(compressedData, { to: "string" });
const json = JSON.parse(uncompressed);
console.log(json);
bot.on("ready", () => {
bot.user.setGame(".help");
convertToDesktop(json);
}
(function loop(i) {
setTimeout(function () {
guilds.set(bot.guilds.size);
if (true) {
loop(i);
}
}, 1000);
})(10);
function convertToDesktop(json) {
const newValues = {
crb: false,
newClanRaidClassId: 0,
newClanRaidClassLevel: 0,
pendingImmortalSouls: 0,
pendingRaidRubies: 0,
immortalSouls: 0,
lastPurchaseTime: 0,
lastRaidAttemptTimestamp: 0,
lastRaidRewardCheckTimestamp: 0,
shouldShowHZERoster: false,
lastBonusRewardCheckTimestamp: 0,
};
log(
`Ready to serve ${bot.users.size} users, in ${bot.channels.size} channels of ${bot.guilds.size} servers.`
);
});
const mappedValues = {
rubies: Math.round(json.rubies / 10),
};
fs.readFile("config.json", (err, data) => {
if (err) {
log("Config file does not exist, creating one.");
const pcSpecificValues = {
readPatchNumber: "1.0e12",
saveOrigin: "pc",
};
let obj = {
discordToken: "TOKEN",
discordBotsToken: "TOKEN",
};
const hash = "7a990d405d2c6fb93aa8fbb0ec1a3b23";
const newData = {
...newValues,
...json,
...mappedValues,
...pcSpecificValues,
};
const compressed = pako.deflate(JSON.stringify(newData), { to: "string" });
const base64 = btoa(compressed);
jsonfile.spaces = 4;
jsonfile.writeFile("config.json", obj, (err) => {
console.log(err);
});
process.exit(1);
} else {
config = require("./config.json");
const finalSaveString = hash + base64;
document.getElementById("output_output").innerText = finalSaveString;
showOutput();
}
bot.login(config.discordToken);
}
});
function showOutput() {
document.getElementById("outputs").style.visibility = "visible";
}
global.skips = {};
global.queue = {
test: "test",
};
function copyOutput() {
const output = document.getElementById("output_output");
output.disabled = false;
output.focus();
output.select();
document.execCommand("copy");
output.disabled = true;
const successElement = document.getElementById("copy_success_msg");
successElement.style.visibility = "visible";
setTimeout(() => (successElement.style.visibility = "hidden"), 4000);
}
global.dispatchers = new Map();
global.connections = new Map();
global.voices = new Map();
global.streams = new Map();
function decode_base64(s) {
let e = {},
i,
k,
v = [],
r = "",
w = String.fromCharCode;
let n = [
[65, 91],
[97, 123],
[48, 58],
[43, 44],
[47, 48],
];
let config = "ERR";
global.allstreams = 0;
global.counter = probe.counter({
name: "Streams",
});
let guilds = probe.metric({
name: "Guilds",
});
let userCooldown = new Map();
bot.commands = new Discord.Collection();
bot.aliases = new Discord.Collection();
fs.readdir("./commands/", (err, files) => {
if (err) console.error(err);
log(`Loading a total of ${files.length} commands.`);
files.forEach((f) => {
let props = require(`./commands/${f}`);
log(`Loading Command: ${props.info.name}. :ok_hand:`);
bot.commands.set(props.info.name, props);
/*
props.conf.aliases.forEach(alias => {
bot.aliases.set(alias, props.info.name);
});
*/
});
});
bot.on("message", (msg) => {
const prefix = ".";
let id = bot.user.id;
let clevername = new RegExp(`^<@!?${id}>`);
if (msg.content.startsWith(prefix)) {
} else if (clevername.test(msg.content)) {
} else return;
if (msg.author.bot) return;
if (msg.guild) {
if (!queue[msg.guild.id]) {
queue[msg.guild.id] = [];
for (z in n) {
for (i = n[z][0]; i < n[z][1]; i++) {
v.push(w(i));
}
} else return;
let command = msg.content.split(" ")[0].slice(prefix.length);
let params = msg.content.split(" ").slice(1);
//let perms = bot.elevation(msg);
let cmd;
if (!userCooldown.get(msg.author.id)) {
userCooldown.set(msg.author.id, 0);
}
for (i = 0; i < 64; i++) {
e[v[i]] = i;
}
if (bot.commands.has(command)) {
if (!commandCooldown(userCooldown.get(msg.author.id))) {
userCooldown.set(msg.author.id, Date.now());
cmd = bot.commands.get(command);
} else msg.channel.sendMessage("You're sending commands too quickly!");
} else if (bot.aliases.has(command)) {
cmd = bot.commands.get(bot.aliases.get(command));
for (i = 0; i < s.length; i += 72) {
let b = 0,
c,
x,
l = 0,
o = s.substring(i, i + 72);
for (x = 0; x < o.length; x++) {
c = e[o.charAt(x)];
b = (b << 6) + c;
l += 6;
while (l >= 8) {
r += w((b >>> (l -= 8)) % 256);
}
}
}
if (cmd) {
cmd.run(bot, msg, params);
}
if (clevername.test(msg.content)) {
console.log(
msg.author.username +
" (" +
msg.author.id +
") issued command: " +
msg.content
);
let string = msg.content;
string = msg.content.split(" ");
string.shift();
string.join(" ");
clever.setNick(msg.author.username);
clever.create(function (err, session) {
if (err) log(err);
clever.ask(string, function (err, response) {
if (err) log(err);
msg.channel
.sendMessage(response)
.then((msg) => log(`Sent message: ${msg.content}`))
.catch(console.error);
});
});
}
});
return r;
}

View file

@ -3,7 +3,7 @@
"rootDir": "src",
"outDir": "dist",
"strict": true,
"target": "es2017"17",
"target": "es2017",
"module": "commonjs",
"sourceMap": true,
"esModuleInterop": true,