fazer-lang 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/bin/fazer.exe +0 -0
  2. package/fazer.js +175 -0
  3. package/package.json +44 -0
package/bin/fazer.exe ADDED
Binary file
package/fazer.js ADDED
@@ -0,0 +1,175 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { Client, IntentsBitField } = require('discord.js'); // Pour Discord
4
+ const { Lexer, Parser, createToken } = require('chevrotain'); // Pour vrai parser
5
+
6
+ // Parser Chevrotain pour remplacer regex (plus robuste, évite fragilités)
7
+ const Stash = createToken({ name: 'Stash', pattern: /stash/ });
8
+ const Broadcast = createToken({ name: 'Broadcast', pattern: /broadcast/ });
9
+ const Intersect = createToken({ name: 'Intersect', pattern: /intersect/ });
10
+ const Detour = createToken({ name: 'Detour', pattern: /detour/ });
11
+ const EndIntersect = createToken({ name: 'EndIntersect', pattern: /endintersect/ });
12
+ const Flow = createToken({ name: 'Flow', pattern: /flow/ });
13
+ const EndFlow = createToken({ name: 'EndFlow', pattern: /endflow/ });
14
+ const Trigger = createToken({ name: 'Trigger', pattern: /trigger/ });
15
+ const Risk = createToken({ name: 'Risk', pattern: /risk/ });
16
+ const Patrol = createToken({ name: 'Patrol', pattern: /patrol/ });
17
+ const EndPatrol = createToken({ name: 'EndPatrol', pattern: /endpatrol/ });
18
+ const Parallel = createToken({ name: 'Parallel', pattern: /parallel streets/ });
19
+ const EndParallel = createToken({ name: 'EndParallel', pattern: /endparallel/ });
20
+ const Uhquali = createToken({ name: 'Uhquali', pattern: /uhquali/ });
21
+ const Cooldown = createToken({ name: 'Cooldown', pattern: /cooldown/ });
22
+ const Wait = createToken({ name: 'Wait', pattern: /wait/ });
23
+ const Save = createToken({ name: 'Save', pattern: /save/ });
24
+ const Load = createToken({ name: 'Load', pattern: /load/ });
25
+ const Territory = createToken({ name: 'Territory', pattern: /territory/ });
26
+ const Whitespace = createToken({ name: 'Whitespace', pattern: /\s+/, group: Lexer.SKIPPED });
27
+ const Identifier = createToken({ name: 'Identifier', pattern: /\w+/ });
28
+ const NumberLiteral = createToken({ name: 'NumberLiteral', pattern: /\d+/ });
29
+ const StringLiteral = createToken({ name: 'StringLiteral', pattern: /"[^"]*"/ });
30
+ const Comment = createToken({ name: 'Comment', pattern: /#.*/, group: Lexer.SKIPPED });
31
+
32
+ // Lexer
33
+ const fazerLexer = new Lexer([
34
+ Whitespace, Comment, Stash, Broadcast, Intersect, Detour, EndIntersect, Flow, EndFlow, Trigger, Risk,
35
+ Patrol, EndPatrol, Parallel, EndParallel, Uhquali, Cooldown, Wait, Save, Load, Territory,
36
+ Identifier, NumberLiteral, StringLiteral
37
+ ]);
38
+
39
+ // Parser basique (extendable)
40
+ class FazerParser extends Parser {
41
+ constructor() {
42
+ super(fazerLexer.allTokens);
43
+ const $ = this;
44
+ $.RULE('statement', () => {
45
+ $.OR([
46
+ { ALT: () => $.SUBRULE($.stashStmt) },
47
+ { ALT: () => $.SUBRULE($.broadcastStmt) },
48
+ // Ajoute les autres rules pour intersect, flow, etc.
49
+ { ALT: () => $.SUBRULE($.uhqualiStmt) },
50
+ { ALT: () => $.SUBRULE($.cooldownStmt) },
51
+ { ALT: () => $.SUBRULE($.waitStmt) },
52
+ { ALT: () => $.SUBRULE($.saveStmt) },
53
+ { ALT: () => $.SUBRULE($.loadStmt) },
54
+ { ALT: () => $.SUBRULE($.territoryStmt) },
55
+ // ... (extend pour les autres)
56
+ ]);
57
+ });
58
+ // Ajoute rules pour chaque stmt (ex: stashStmt: consume(Stash) then Identifier etc.)
59
+ this.performSelfAnalysis();
60
+ }
61
+ }
62
+ const parser = new FazerParser();
63
+
64
+ class FazerInterpreter {
65
+ constructor() {
66
+ this.variables = {};
67
+ this.functions = {};
68
+ this.cooldowns = {}; // { name: endTime }
69
+ this.discordClient = null; // Init Discord lazy
70
+ }
71
+
72
+ // Parse avec Chevrotain
73
+ parse(code) {
74
+ const lexResult = fazerLexer.tokenize(code);
75
+ parser.input = lexResult.tokens;
76
+ const cst = parser.statement(); // Parse top-level
77
+ if (parser.errors.length > 0) throw new Error(parser.errors[0].message);
78
+ return cst; // Retourne CST pour exécution
79
+ }
80
+
81
+ // Exécute (simplifié, étend pour full CST)
82
+ async executeBlock(lines, isAsync = false) {
83
+ // Pour l'instant, mix regex + chevrotain ; full chevrotain later
84
+ // ... (garde la logique précédente, mais parse chaque line avec lexer)
85
+ let i = 0;
86
+ const output = [];
87
+ while (i < lines.length) {
88
+ const line = lines[i].trim();
89
+ if (!line || line.startsWith('#')) { i++; continue; }
90
+
91
+ // Exemple pour uhquali
92
+ if (line.startsWith('uhquali event ')) {
93
+ const eventName = line.slice(13).trim().replace(/"/g, '');
94
+ const events = ['Win culture boost +20 cultural_rep', 'Lose -10, rival diss', 'Neutral vibe'];
95
+ const outcome = events[Math.floor(Math.random() * events.length)];
96
+ this.variables['cultural_rep'] = (this.variables['cultural_rep'] || 0) + (outcome.includes('+') ? 20 : outcome.includes('-') ? -10 : 0);
97
+ console.log(`Uhquali event "${eventName}": ${outcome}`);
98
+ output.push(outcome);
99
+ }
100
+
101
+ // Cooldown
102
+ if (line.startsWith('cooldown ')) {
103
+ const [name, timeStr] = line.slice(9).trim().split(' ');
104
+ const time = this.parseTime(timeStr);
105
+ this.cooldowns[name] = Date.now() + time;
106
+ console.log(`Cooldown set for ${name}: ${timeStr}`);
107
+ }
108
+
109
+ // Check cooldown in actions (ex: in heist, if (Date.now() < this.cooldowns['heist']) bust)
110
+
111
+ // Wait
112
+ if (line.startsWith('wait ')) {
113
+ const timeStr = line.slice(5).trim();
114
+ const time = this.parseTime(timeStr);
115
+ await new Promise(resolve => setTimeout(resolve, time));
116
+ }
117
+
118
+ // Save
119
+ if (line.startsWith('save ')) {
120
+ const name = line.slice(5).trim();
121
+ fs.writeFileSync(`${name}.json`, JSON.stringify(this.variables));
122
+ console.log(`State saved to ${name}.json`);
123
+ }
124
+
125
+ // Load
126
+ if (line.startsWith('load ')) {
127
+ const name = line.slice(5).trim();
128
+ if (fs.existsSync(`${name}.json`)) {
129
+ this.variables = JSON.parse(fs.readFileSync(`${name}.json`, 'utf8'));
130
+ console.log(`State loaded from ${name}.json`);
131
+ }
132
+ }
133
+
134
+ // Broadcast to Discord
135
+ if (line.startsWith('broadcast to discord ')) {
136
+ const [channelId, ...msgParts] = line.slice(20).trim().split(' ');
137
+ const message = msgParts.join(' ');
138
+ await this.sendToDiscord(channelId, this.evaluate(message));
139
+ }
140
+
141
+ // Territory
142
+ if (line.startsWith('territory ')) {
143
+ const [name, action, key, value] = line.slice(10).trim().split(' ');
144
+ if (!this.variables[name]) this.variables[name] = {};
145
+ if (action === 'add') this.variables[name][key] = this.evaluate(value);
146
+ console.log(`Territory ${name} updated`);
147
+ }
148
+
149
+ // ... (intègre le reste de la logique précédente pour intersect, risk, etc.)
150
+
151
+ i++;
152
+ }
153
+ return output;
154
+ }
155
+
156
+ parseTime(timeStr) {
157
+ const val = parseInt(timeStr.slice(0, -1));
158
+ const unit = timeStr.slice(-1);
159
+ return val * (unit === 's' ? 1000 : unit === 'm' ? 60000 : unit === 'h' ? 3600000 : 86400000); // s/m/h/d
160
+ }
161
+
162
+ async sendToDiscord(channelId, message) {
163
+ if (!this.discordClient) {
164
+ this.discordClient = new Client({ intents: [IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages] });
165
+ await this.discordClient.login(process.env.DISCORD_TOKEN);
166
+ }
167
+ const channel = await this.discordClient.channels.fetch(channelId);
168
+ await channel.send(message);
169
+ }
170
+
171
+ // ... (reste du code : evaluate, run, CLI)
172
+ }
173
+
174
+ // CLI reste pareil
175
+ // ...
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "fazer-lang",
3
+ "version": "0.1.0",
4
+ "description": "Fazer Language – Un langage de programmation.",
5
+ "main": "fazer.js",
6
+ "bin": {
7
+ "fazer": "fazer.js"
8
+ },
9
+ "dependencies": {
10
+ "discord.js": "^14.14.1",
11
+ "chevrotain": "^11.0.3"
12
+ },
13
+ "devDependencies": {
14
+ "pkg": "^5.8.1"
15
+ },
16
+ "scripts": {
17
+ "start": "node fazer.js",
18
+ "build": "pkg fazer.js -t node18-win-x64 -o bin/fazer.exe"
19
+ },
20
+ "keywords": [
21
+ "fazer",
22
+ "programming-language",
23
+ "street-script",
24
+ "discord-bot",
25
+ "simulation",
26
+ "risk-based"
27
+ ],
28
+ "author": "hm (Fazer City)",
29
+ "license": "MIT",
30
+ "files": [
31
+ "fazer.js",
32
+ "bin/",
33
+ "README.md",
34
+ "logo.png"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/hmj34/fazer-lang.git"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/hmj34/fazer-lang/issues"
42
+ },
43
+ "homepage": "https://github.com/hmj34/fazer-lang#readme"
44
+ }