steel-lang-2 1.0.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/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 theworker02
4
+
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ [![npm](https://img.shields.io/npm/v/steel-lang-2)](https://www.npmjs.com/package/steel-lang-2)
2
+
3
+ Steel is a simple, readable programming language designed to be easy to learn and intuitive to use.
4
+
5
+ It focuses on clean syntax, minimal complexity, and fast execution through a custom JavaScript interpreter.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install steel-lang-2
11
+ ```
12
+
13
+
14
+
15
+
16
+
17
+ Features:
18
+ β€’ 🧠 Human-readable syntax
19
+ β€’ ⚑ Lightweight interpreter (Node.js)
20
+ β€’ 🧱 Simple variable system
21
+ β€’ πŸ” Control flow (if statements, loops)
22
+ β€’ πŸ’¬ Built-in output (say)
23
+ β€’ 🎨 VS Code syntax highlighting support
24
+ β€’ πŸ”§ Easy to extend and modify
25
+
26
+
27
+
28
+
29
+ Project Structure:
30
+
31
+ steel-lang/
32
+ β”œβ”€β”€ src/ # Language engine
33
+ β”‚ β”œβ”€β”€ lexer.js
34
+ β”‚ β”œβ”€β”€ parser.js
35
+ β”‚ β”œβ”€β”€ interpreter.js
36
+ β”‚ β”œβ”€β”€ environment.js
37
+ β”‚ └── index.js
38
+ β”œβ”€β”€ examples/ # Example programs
39
+ β”‚ β”œβ”€β”€ hello.steel
40
+ β”‚ β”œβ”€β”€ logic.steel
41
+ β”‚ └── variables.steel
42
+ β”œβ”€β”€ stl/ # VS Code extension
43
+ β”‚ β”œβ”€β”€ syntaxes/
44
+ β”‚ β”œβ”€β”€ icons/
45
+ β”‚ └── package.json
46
+ └── README.md
47
+
48
+
49
+
50
+
51
+
52
+ πŸš€ Getting Started
53
+
54
+ Clone the repository
55
+
56
+ 1. git clone https://github.com/theworker02/steel-lang.git
57
+
58
+ 2. cd steel-lang
59
+
60
+
61
+
62
+ Run a Steel program
63
+
64
+ 3. "node src/index.js examples/hello.steel"
65
+
66
+
67
+ πŸ§ͺ Example:
68
+
69
+ set x to 10
70
+
71
+ if x > 5 then
72
+ say "Steel is working!"
73
+ end
74
+
75
+
76
+ https://steel-lang.base44.app
77
+
78
+
79
+ 🧩 VS Code Extension:
80
+
81
+ Steel includes a custom VS Code extension for syntax highlighting.
82
+
83
+ Run locally: β€œcd stl”
84
+
85
+ Then open the folder in VS code and press: F5
86
+
87
+
88
+ 🎯 Goals:
89
+
90
+ β€’ Keep syntax simple and readable
91
+ β€’ Build a fully custom language ecosystem
92
+ β€’ Add functions, modules, and advanced features
93
+ β€’ Expand tooling (CLI, debugger, autocomplete)
94
+
95
+
96
+ https://steel-lang.base44.app
97
+
98
+
99
+ πŸ› οΈ Future Plans:
100
+
101
+ β€’ CLI command (steel run file.steel)
102
+ β€’ Error handling improvements
103
+ β€’ Function system
104
+ β€’ Package manager (maybe πŸ‘€)
105
+ β€’ Full VS Code integration (IntelliSense)
106
+
107
+
108
+ 🀝 Contributing:
109
+
110
+ Pull requests are welcome. This project is actively evolving and is considered to me still a work in progress. A lot has to be done honestly.
111
+
112
+ License: MIT License
113
+
114
+ Author: theworker02
115
+
116
+ βš™οΈ Status:
117
+
118
+ 🚧 Early Development/Work in progress, but fully functional
119
+
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "icon": "icons/steel.png",
3
+ "name": "steel-lang-2",
4
+ "version": "1.0.0",
5
+ "files": [
6
+ "src/",
7
+ "icons/"
8
+ ],
9
+ "description": "A simple, human-readable scripting language",
10
+ "main": "src/index.js",
11
+ "scripts": {
12
+ "start": "node src/index.js examples/hello.steel"
13
+ },
14
+ "keywords": [
15
+ "language",
16
+ "interpreter",
17
+ "steel"
18
+ ],
19
+ "author": "theworker02",
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/magnexis/Steel-lang.git"
24
+ }
25
+ }
@@ -0,0 +1,35 @@
1
+ class Environment {
2
+
3
+ constructor() {
4
+
5
+ this.variables = {};
6
+
7
+ }
8
+
9
+
10
+
11
+ set(name, value) {
12
+
13
+ this.variables[name] = value;
14
+
15
+ }
16
+
17
+
18
+
19
+ get(name) {
20
+
21
+ if (!(name in this.variables)) {
22
+
23
+ throw new Error(`Variable "${name}" is not defined`);
24
+
25
+ }
26
+
27
+ return this.variables[name];
28
+
29
+ }
30
+
31
+ }
32
+
33
+
34
+
35
+ module.exports = Environment;
package/src/index.js ADDED
@@ -0,0 +1,49 @@
1
+ const fs = require('fs');
2
+
3
+ const { tokenize } = require('./lexer');
4
+
5
+ const { parse } = require('./parser');
6
+
7
+ const { interpret } = require('./interpreter');
8
+
9
+ const Environment = require('./environment');
10
+
11
+
12
+
13
+ const file = process.argv[2];
14
+
15
+
16
+
17
+ if (!file) {
18
+
19
+ console.log("Usage: node src/index.js <file.steel>");
20
+
21
+ process.exit(1);
22
+
23
+ }
24
+
25
+
26
+
27
+ try {
28
+
29
+ const code = fs.readFileSync(file, 'utf-8');
30
+
31
+
32
+
33
+ const tokens = tokenize(code);
34
+
35
+ const ast = parse(tokens);
36
+
37
+
38
+
39
+ const env = new Environment();
40
+
41
+
42
+
43
+ interpret(ast, env);
44
+
45
+ } catch (err) {
46
+
47
+ console.error("Error:", err.message);
48
+
49
+ }
@@ -0,0 +1,99 @@
1
+ function interpret(ast, env) {
2
+
3
+ for (let node of ast) {
4
+
5
+
6
+
7
+ if (node.type === 'VariableDeclaration') {
8
+
9
+ const value = evaluate(node.value, env);
10
+
11
+ env.set(node.name, value);
12
+
13
+ }
14
+
15
+
16
+
17
+ if (node.type === 'SayStatement') {
18
+
19
+ const value = evaluate(node.value, env);
20
+
21
+ console.log(value);
22
+
23
+ }
24
+
25
+
26
+
27
+ if (node.type === 'IfStatement') {
28
+
29
+ const condition = evaluate(node.condition, env);
30
+
31
+
32
+
33
+ if (condition) {
34
+
35
+ interpret(node.body, env);
36
+
37
+ }
38
+
39
+ }
40
+
41
+
42
+
43
+ }
44
+
45
+ }
46
+
47
+
48
+
49
+ function evaluate(node, env) {
50
+
51
+ if (node.type === 'NUMBER') return node.value;
52
+
53
+ if (node.type === 'STRING') return node.value;
54
+
55
+
56
+
57
+ if (node.type === 'IDENTIFIER') {
58
+
59
+ return env.get(node.value);
60
+
61
+ }
62
+
63
+
64
+
65
+ if (node.type === 'BinaryExpression') {
66
+
67
+ const left = evaluate(node.left, env);
68
+
69
+ const right = evaluate(node.right, env);
70
+
71
+
72
+
73
+ switch (node.operator) {
74
+
75
+ case 'PLUS': return left + right;
76
+
77
+ case 'MINUS': return left - right;
78
+
79
+ case 'GT': return left > right;
80
+
81
+ case 'LT': return left < right;
82
+
83
+ case 'EQEQ': return left === right;
84
+
85
+ }
86
+
87
+ }
88
+
89
+
90
+
91
+ return null;
92
+
93
+ }
94
+
95
+
96
+
97
+ module.exports = { interpret };
98
+
99
+
package/src/lexer.js ADDED
@@ -0,0 +1,94 @@
1
+ const KEYWORDS = {
2
+
3
+ set: 'SET',
4
+
5
+ to: 'TO',
6
+
7
+ say: 'SAY',
8
+
9
+ if: 'IF',
10
+
11
+ then: 'THEN',
12
+
13
+ end: 'END',
14
+
15
+ };
16
+
17
+ const OPERATORS = {
18
+ '+': 'PLUS',
19
+ '-': 'MINUS',
20
+ '>': 'GT',
21
+ '<': 'LT',
22
+ '==': 'EQEQ',
23
+ };
24
+
25
+
26
+
27
+ function tokenize(input) {
28
+
29
+ const tokens = [];
30
+
31
+
32
+
33
+ const regex = /"[^"]*"|==|[+\-<>]|[^\s]+/g;
34
+
35
+ const words = input.match(regex) || [];
36
+
37
+
38
+
39
+ for (let word of words) {
40
+
41
+ if (OPERATORS[word]) {
42
+
43
+ tokens.push({ type: OPERATORS[word] });
44
+
45
+ }
46
+
47
+ else if (!isNaN(word)) {
48
+
49
+ tokens.push({ type: 'NUMBER', value: Number(word) });
50
+
51
+ }
52
+
53
+ else if (word.startsWith('"')) {
54
+
55
+ tokens.push({
56
+
57
+ type: 'STRING',
58
+
59
+ value: word.slice(1, -1)
60
+
61
+ });
62
+
63
+ }
64
+
65
+ else if (KEYWORDS[word]) {
66
+
67
+ tokens.push({ type: KEYWORDS[word] });
68
+
69
+ }
70
+
71
+ else {
72
+
73
+ tokens.push({
74
+
75
+ type: 'IDENTIFIER',
76
+
77
+ value: word
78
+
79
+ });
80
+
81
+ }
82
+
83
+ }
84
+
85
+
86
+
87
+ return tokens;
88
+
89
+ }
90
+
91
+
92
+
93
+ module.exports = { tokenize };
94
+
package/src/parser.js ADDED
@@ -0,0 +1,198 @@
1
+ function parse(tokens) {
2
+
3
+ let i = 0;
4
+
5
+
6
+
7
+ function parseExpression() {
8
+
9
+ if (i >= tokens.length) {
10
+ throw new SyntaxError('Unexpected end of input');
11
+ }
12
+
13
+ const left = tokens[i++];
14
+
15
+
16
+
17
+ if (tokens[i] && ['PLUS', 'MINUS', 'GT', 'LT', 'EQEQ'].includes(tokens[i].type)) {
18
+
19
+ const operator = tokens[i++];
20
+
21
+ if (!tokens[i]) throw new SyntaxError('Expected right-hand operand');
22
+
23
+ const right = tokens[i++];
24
+
25
+
26
+
27
+ return {
28
+
29
+ type: 'BinaryExpression',
30
+
31
+ left,
32
+
33
+ operator: operator.type,
34
+
35
+ right
36
+
37
+ };
38
+
39
+ }
40
+
41
+
42
+
43
+ return left;
44
+
45
+ }
46
+
47
+
48
+
49
+ const ast = [];
50
+
51
+
52
+
53
+ while (i < tokens.length) {
54
+
55
+ const token = tokens[i];
56
+
57
+
58
+
59
+ // set x to ...
60
+
61
+ if (token.type === 'SET') {
62
+
63
+ if (!tokens[i + 1] || tokens[i + 1].type !== 'IDENTIFIER') {
64
+ throw new SyntaxError("'SET' expects a variable name");
65
+ }
66
+ if (!tokens[i + 2] || tokens[i + 2].type !== 'TO') {
67
+ throw new SyntaxError("'SET' expects 'TO' after variable name");
68
+ }
69
+
70
+ const name = tokens[i + 1].value;
71
+
72
+ i += 3; // skip SET name TO
73
+
74
+
75
+
76
+ const value = parseExpression();
77
+
78
+
79
+
80
+ ast.push({
81
+
82
+ type: 'VariableDeclaration',
83
+
84
+ name,
85
+
86
+ value
87
+
88
+ });
89
+
90
+ }
91
+
92
+
93
+
94
+ // say ...
95
+
96
+ else if (token.type === 'SAY') {
97
+
98
+ i++;
99
+
100
+ const value = parseExpression();
101
+
102
+
103
+
104
+ ast.push({
105
+
106
+ type: 'SayStatement',
107
+
108
+ value
109
+
110
+ });
111
+
112
+ }
113
+
114
+
115
+
116
+ // if condition then ... end
117
+
118
+ else if (token.type === 'IF') {
119
+
120
+ i++;
121
+
122
+
123
+
124
+ const condition = parseExpression();
125
+
126
+
127
+
128
+ if (!tokens[i] || tokens[i].type !== 'THEN') {
129
+ throw new SyntaxError("'IF' expects 'THEN' after condition");
130
+ }
131
+ i++; // skip THEN
132
+
133
+
134
+
135
+ const body = [];
136
+
137
+
138
+
139
+ while (tokens[i] && tokens[i].type !== 'END') {
140
+
141
+ if (tokens[i].type === 'SAY') {
142
+
143
+ i++;
144
+
145
+ body.push({
146
+
147
+ type: 'SayStatement',
148
+
149
+ value: parseExpression()
150
+
151
+ });
152
+
153
+ } else {
154
+
155
+ i++;
156
+
157
+ }
158
+
159
+ }
160
+
161
+ if (!tokens[i]) {
162
+ throw new SyntaxError("'IF' block missing 'END'");
163
+ }
164
+ i++; // skip END
165
+
166
+
167
+
168
+ ast.push({
169
+
170
+ type: 'IfStatement',
171
+
172
+ condition,
173
+
174
+ body
175
+
176
+ });
177
+
178
+ }
179
+
180
+
181
+
182
+ else {
183
+
184
+ i++;
185
+
186
+ }
187
+
188
+ }
189
+
190
+
191
+
192
+ return ast;
193
+
194
+ }
195
+
196
+
197
+
198
+ module.exports = { parse };