1- class TokenType {
2- static NUMBER = "NUMBER" ;
3- static IDENTIFIER = "IDENTIFIER" ;
4- static OPERATOR = "OPERATOR" ;
5- static LEFT_PAREN = "LEFT_PAREN" ;
6- static RIGHT_PAREN = "RIGHT_PAREN" ;
7- static LEFT_BRACKET = "LEFT_BRACKET" ;
8- static RIGHT_BRACKET = "RIGHT_BRACKET" ;
9- static COMMA = "COMMA" ;
10- static DOT = "DOT" ;
11- static EOF = "EOF" ;
12- }
1+ const TokenType = Object . freeze ( {
2+ NUMBER : Symbol ( 'NUMBER' ) ,
3+ IDENTIFIER : Symbol ( 'IDENTIFIER' ) ,
4+ OPERATOR : Symbol ( 'OPERATOR' ) ,
5+ LEFT_PAREN : Symbol ( 'LEFT_PAREN' ) ,
6+ RIGHT_PAREN : Symbol ( 'RIGHT_PAREN' ) ,
7+ LEFT_BRACKET : Symbol ( 'LEFT_BRACKET' ) ,
8+ RIGHT_BRACKET : Symbol ( 'RIGHT_BRACKET' ) ,
9+ COMMA : Symbol ( 'COMMA' ) ,
10+ DOT : Symbol ( 'DOT' ) ,
11+ EOF : Symbol ( 'EOF' )
12+ } ) ;
13+
14+ const ASTNodeType = Object . freeze ( {
15+ NUMBER : Symbol ( 'NUMBER' ) ,
16+ VARIABLE : Symbol ( 'VARIABLE' ) ,
17+ BINARY_OP : Symbol ( 'BINARY_OP' ) ,
18+ UNARY_OP : Symbol ( 'UNARY_OP' ) ,
19+ FUNCTION_CALL : Symbol ( 'FUNCTION_CALL' ) ,
20+ ARRAY_ACCESS : Symbol ( 'ARRAY_ACCESS' ) ,
21+ PROPERTY_ACCESS : Symbol ( 'PROPERTY_ACCESS' )
22+ } ) ;
1323
1424class Token {
1525 constructor ( type , value ) {
@@ -32,25 +42,16 @@ class Lexer {
3242
3343 const char = this . input [ this . position ] ;
3444
35- if ( this . isDigit ( char ) ) {
36- return this . readNumber ( ) ;
37- } else if ( this . isAlpha ( char ) ) {
38- return this . readIdentifier ( ) ;
39- } else if ( this . isOperator ( char ) ) {
40- return new Token ( TokenType . OPERATOR , this . advance ( ) ) ;
41- } else if ( char === "(" ) {
42- return new Token ( TokenType . LEFT_PAREN , this . advance ( ) ) ;
43- } else if ( char === ")" ) {
44- return new Token ( TokenType . RIGHT_PAREN , this . advance ( ) ) ;
45- } else if ( char === "[" ) {
46- return new Token ( TokenType . LEFT_BRACKET , this . advance ( ) ) ;
47- } else if ( char === "]" ) {
48- return new Token ( TokenType . RIGHT_BRACKET , this . advance ( ) ) ;
49- } else if ( char === "," ) {
50- return new Token ( TokenType . COMMA , this . advance ( ) ) ;
51- } else if ( char === "." ) {
52- return new Token ( TokenType . DOT , this . advance ( ) ) ;
53- }
45+ if ( this . isDigit ( char ) ) { return this . readNumber ( ) ; }
46+ else if ( this . isAlpha ( char ) ) { return this . readIdentifier ( ) ; }
47+ else if ( this . isOperator ( char ) ) { return new Token ( TokenType . OPERATOR , this . advance ( ) ) ; }
48+ else if ( char === "(" ) { return new Token ( TokenType . LEFT_PAREN , this . advance ( ) ) ; }
49+ else if ( char === ")" ) { return new Token ( TokenType . RIGHT_PAREN , this . advance ( ) ) ; }
50+ else if ( char === "[" ) { return new Token ( TokenType . LEFT_BRACKET , this . advance ( ) ) ; }
51+ else if ( char === "]" ) { return new Token ( TokenType . RIGHT_BRACKET , this . advance ( ) ) ; }
52+ else if ( char === "," ) { return new Token ( TokenType . COMMA , this . advance ( ) ) ; }
53+ else if ( char === "." ) { return new Token ( TokenType . DOT , this . advance ( ) ) ;
54+ }
5455
5556 throw new Error ( `Unexpected character: ${ char } ` ) ;
5657 }
@@ -118,7 +119,7 @@ class Parser {
118119 while ( this . currentToken . type === TokenType . OPERATOR && ( this . currentToken . value === "+" || this . currentToken . value === "-" ) ) {
119120 const token = this . currentToken ;
120121 this . eat ( TokenType . OPERATOR ) ;
121- node = { type : "BinaryOp" , left : node , op : token . value , right : this . multiplicative ( ) } ;
122+ node = { type : ASTNodeType . BINARY_OP , left : node , op : token . value , right : this . multiplicative ( ) } ;
122123 }
123124
124125 return node ;
@@ -130,7 +131,7 @@ class Parser {
130131 while ( this . currentToken . type === TokenType . OPERATOR && ( this . currentToken . value === "*" || this . currentToken . value === "/" || this . currentToken . value === "%" ) ) {
131132 const token = this . currentToken ;
132133 this . eat ( TokenType . OPERATOR ) ;
133- node = { type : "BinaryOp" , left : node , op : token . value , right : this . exponential ( ) } ;
134+ node = { type : ASTNodeType . BINARY_OP , left : node , op : token . value , right : this . exponential ( ) } ;
134135 }
135136
136137 return node ;
@@ -142,7 +143,7 @@ class Parser {
142143 while ( this . currentToken . type === TokenType . OPERATOR && this . currentToken . value === "^" ) {
143144 const token = this . currentToken ;
144145 this . eat ( TokenType . OPERATOR ) ;
145- node = { type : "BinaryOp" , left : node , op : token . value , right : this . unary ( ) } ;
146+ node = { type : ASTNodeType . BINARY_OP , left : node , op : token . value , right : this . unary ( ) } ;
146147 }
147148
148149 return node ;
@@ -152,7 +153,7 @@ class Parser {
152153 if ( this . currentToken . type === TokenType . OPERATOR && ( this . currentToken . value === "+" || this . currentToken . value === "-" ) ) {
153154 const token = this . currentToken ;
154155 this . eat ( TokenType . OPERATOR ) ;
155- return { type : "UnaryOp" , op : token . value , expr : this . unary ( ) } ;
156+ return { type : ASTNodeType . UNARY_OP , op : token . value , expr : this . unary ( ) } ;
156157 }
157158 return this . primary ( ) ;
158159 }
@@ -161,7 +162,7 @@ class Parser {
161162 if ( this . currentToken . type === TokenType . NUMBER ) {
162163 const token = this . currentToken ;
163164 this . eat ( TokenType . NUMBER ) ;
164- return { type : "Number" , value : token . value } ;
165+ return { type : ASTNodeType . NUMBER , value : token . value } ;
165166 } else if ( this . currentToken . type === TokenType . IDENTIFIER ) {
166167 return this . variable ( ) ;
167168 } else if ( this . currentToken . type === TokenType . LEFT_PAREN ) {
@@ -175,7 +176,7 @@ class Parser {
175176 }
176177
177178 variable ( ) {
178- let node = { type : "Variable" , name : this . currentToken . value } ;
179+ let node = { type : ASTNodeType . VARIABLE , name : this . currentToken . value } ;
179180 this . eat ( TokenType . IDENTIFIER ) ;
180181
181182 if ( this . currentToken . type === TokenType . LEFT_PAREN ) {
@@ -194,7 +195,7 @@ class Parser {
194195 throw new Error ( "Expected property name after '.'" ) ;
195196 }
196197 node = {
197- type : "PropertyAccess" ,
198+ type : ASTNodeType . PROPERTY_ACCESS ,
198199 object : node ,
199200 property : this . currentToken . value
200201 } ;
@@ -209,14 +210,14 @@ class Parser {
209210 this . eat ( TokenType . LEFT_PAREN ) ;
210211 const args = this . argumentList ( ) ;
211212 this . eat ( TokenType . RIGHT_PAREN ) ;
212- return { type : "FunctionCall" , name : name , arguments : args } ;
213+ return { type : ASTNodeType . FUNCTION_CALL , name : name , arguments : args } ;
213214 }
214215
215216 arrayAccess ( node ) {
216217 this . eat ( TokenType . LEFT_BRACKET ) ;
217218 const index = this . expression ( ) ;
218219 this . eat ( TokenType . RIGHT_BRACKET ) ;
219- return { type : "ArrayAccess" , array : node , index : index } ;
220+ return { type : ASTNodeType . ARRAY_ACCESS , array : node , index : index } ;
220221 }
221222
222223 argumentList ( ) {
@@ -251,22 +252,16 @@ class Interpreter {
251252 }
252253
253254 visit ( node ) {
254- if ( node . type === "Number" ) {
255- return node . value ;
256- } else if ( node . type === "Variable" ) {
257- return this . getValueFromData ( node . name , this . data ) ;
258- } else if ( node . type === "BinaryOp" ) {
259- return this . visitBinaryOp ( node ) ;
260- } else if ( node . type === "UnaryOp" ) {
261- return this . visitUnaryOp ( node ) ;
262- } else if ( node . type === "FunctionCall" ) {
263- return this . visitFunctionCall ( node ) ;
264- } else if ( node . type === "ArrayAccess" ) {
265- return this . visitArrayAccess ( node ) ;
266- } else if ( node . type === "PropertyAccess" ) {
267- return this . visitPropertyAccess ( node ) ;
255+ switch ( node . type ) {
256+ case ASTNodeType . NUMBER : return node . value ;
257+ case ASTNodeType . VARIABLE : return this . getValueFromData ( node . name , this . data ) ;
258+ case ASTNodeType . BINARY_OP : return this . visitBinaryOp ( node ) ;
259+ case ASTNodeType . UNARY_OP : return this . visitUnaryOp ( node ) ;
260+ case ASTNodeType . FUNCTION_CALL : return this . visitFunctionCall ( node ) ;
261+ case ASTNodeType . ARRAY_ACCESS : return this . visitArrayAccess ( node ) ;
262+ case ASTNodeType . PROPERTY_ACCESS : return this . visitPropertyAccess ( node ) ;
263+ default : throw new Error ( `Unknown node type: ${ node . type } ` ) ;
268264 }
269- throw new Error ( `Unknown node type: ${ node . type } ` ) ;
270265 }
271266
272267 visitArrayAccess ( node ) {
@@ -293,52 +288,35 @@ class Interpreter {
293288 const left = this . visit ( node . left ) ;
294289 const right = this . visit ( node . right ) ;
295290 switch ( node . op ) {
296- case "+" :
297- return left + right ;
298- case "-" :
299- return left - right ;
300- case "*" :
301- return left * right ;
302- case "/" :
303- return left / right ;
304- case "%" :
305- return left % right ;
306- case "^" :
307- return Math . pow ( left , right ) ;
308- default :
309- throw new Error ( `Unknown operator: ${ node . op } ` ) ;
291+ case "+" : return left + right ;
292+ case "-" : return left - right ;
293+ case "*" : return left * right ;
294+ case "/" : return left / right ;
295+ case "%" : return left % right ;
296+ case "^" : return Math . pow ( left , right ) ;
297+ default : throw new Error ( `Unknown operator: ${ node . op } ` ) ;
310298 }
311299 }
312300
313301 visitUnaryOp ( node ) {
314302 const expr = this . visit ( node . expr ) ;
315303 switch ( node . op ) {
316- case "+" :
317- return + expr ;
318- case "-" :
319- return - expr ;
320- default :
321- throw new Error ( `Unknown unary operator: ${ node . op } ` ) ;
304+ case "+" : return + expr ;
305+ case "-" : return - expr ;
306+ default : throw new Error ( `Unknown unary operator: ${ node . op } ` ) ;
322307 }
323308 }
324309
325310 visitFunctionCall ( node ) {
326311 const args = node . arguments . map ( ( arg ) => this . visit ( arg ) ) ;
327312 switch ( node . name . toLowerCase ( ) ) {
328- case "min" :
329- return Math . min ( ...args ) ;
330- case "max" :
331- return Math . max ( ...args ) ;
332- case "abs" :
333- return Math . abs ( args [ 0 ] ) ;
334- case "round" :
335- return Math . round ( args [ 0 ] ) ;
336- case "floor" :
337- return Math . floor ( args [ 0 ] ) ;
338- case "ceil" :
339- return Math . ceil ( args [ 0 ] ) ;
340- default :
341- throw new Error ( `Unknown function: ${ node . name } ` ) ;
313+ case "min" : return Math . min ( ...args ) ;
314+ case "max" : return Math . max ( ...args ) ;
315+ case "abs" : return Math . abs ( args [ 0 ] ) ;
316+ case "round" : return Math . round ( args [ 0 ] ) ;
317+ case "floor" : return Math . floor ( args [ 0 ] ) ;
318+ case "ceil" : return Math . ceil ( args [ 0 ] ) ;
319+ default : throw new Error ( `Unknown function: ${ node . name } ` ) ;
342320 }
343321 }
344322
0 commit comments