amr-lang 1.0.3 → 1.0.4
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/package.json +1 -1
- package/src/ast.ts +4 -1
- package/src/interpreter.ts +3 -0
- package/src/lexer.ts +34 -0
- package/src/parser.ts +5 -0
package/package.json
CHANGED
package/src/ast.ts
CHANGED
|
@@ -10,7 +10,8 @@ export type Node =
|
|
|
10
10
|
| CallExpr
|
|
11
11
|
| BinaryExpr
|
|
12
12
|
| Identifier
|
|
13
|
-
| NumberLiteral
|
|
13
|
+
| NumberLiteral
|
|
14
|
+
| StringLiteral;
|
|
14
15
|
|
|
15
16
|
export type Program = { type: "Program"; body: Node[] };
|
|
16
17
|
|
|
@@ -33,3 +34,5 @@ export type BinaryExpr = { type: "BinaryExpr"; operator: string; left: Node; rig
|
|
|
33
34
|
export type Identifier = { type: "Identifier"; name: string };
|
|
34
35
|
|
|
35
36
|
export type NumberLiteral = { type: "NumberLiteral"; value: number };
|
|
37
|
+
|
|
38
|
+
export type StringLiteral = { type: "StringLiteral"; value: string };
|
package/src/interpreter.ts
CHANGED
package/src/lexer.ts
CHANGED
|
@@ -49,6 +49,40 @@ export class Lexer {
|
|
|
49
49
|
return { type: "NUMBER", value, line: this.line, column: startCol };
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// String literals
|
|
53
|
+
if (char === '"' || char === "'") {
|
|
54
|
+
const quote = char;
|
|
55
|
+
const startCol = this.column;
|
|
56
|
+
this.advance(); // Skip opening quote
|
|
57
|
+
let value = "";
|
|
58
|
+
|
|
59
|
+
while (this.pos < this.input.length && this.input[this.pos] !== quote) {
|
|
60
|
+
if (this.input[this.pos] === '\\' && this.pos + 1 < this.input.length) {
|
|
61
|
+
this.advance(); // Skip backslash
|
|
62
|
+
const escaped = this.advance();
|
|
63
|
+
// Handle escape sequences
|
|
64
|
+
switch (escaped) {
|
|
65
|
+
case 'n': value += '\n'; break;
|
|
66
|
+
case 't': value += '\t'; break;
|
|
67
|
+
case 'r': value += '\r'; break;
|
|
68
|
+
case '\\': value += '\\'; break;
|
|
69
|
+
case quote: value += quote; break;
|
|
70
|
+
default: value += escaped;
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
value += this.advance();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (this.input[this.pos] === quote) {
|
|
78
|
+
this.advance(); // Skip closing quote
|
|
79
|
+
} else {
|
|
80
|
+
throw new Error(`Unterminated string at ${this.line}:${startCol}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { type: "STRING", value, line: this.line, column: startCol };
|
|
84
|
+
}
|
|
85
|
+
|
|
52
86
|
if (char.match(/[a-z]/i)) {
|
|
53
87
|
let value = "";
|
|
54
88
|
const startCol = this.column;
|
package/src/parser.ts
CHANGED
|
@@ -185,6 +185,11 @@ export class Parser {
|
|
|
185
185
|
return { type: "NumberLiteral", value };
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
if (this.check("STRING")) {
|
|
189
|
+
const value = this.consume().value!;
|
|
190
|
+
return { type: "StringLiteral", value };
|
|
191
|
+
}
|
|
192
|
+
|
|
188
193
|
if (this.check("IDENT")) {
|
|
189
194
|
const name = this.consume().value!;
|
|
190
195
|
|