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.
- package/bin/fazer.exe +0 -0
- package/fazer.js +175 -0
- 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
|
+
}
|