File tree 5 files changed +58
-6
lines changed 5 files changed +58
-6
lines changed Original file line number Diff line number Diff line change @@ -54,7 +54,9 @@ export function check(module: Module) {
54
54
error ( expression . pos , 'Could not resolve ' + expression . text ) ;
55
55
return errorType ;
56
56
case Node . Literal :
57
- return typeof expression . value === 'string' ? stringType : numberType ;
57
+ return numberType ;
58
+ case Node . StringLiteral :
59
+ return stringType ;
58
60
case Node . Assignment :
59
61
const v = checkExpression ( expression . value ) ;
60
62
const t = checkExpression ( expression . name ) ;
Original file line number Diff line number Diff line change 1
1
import { Statement , Node , Expression } from './types' ;
2
2
3
+ const singleQuoteRegex = / [ \\ \' \t \v \f \b \r \n ] / g;
4
+ const doubleQuoteRegex = / [ \\ \" \t \v \f \b \r \n ] / g;
5
+
6
+ const escapedCharsMap = new Map (
7
+ Object . entries ( {
8
+ '\t' : '\\t' ,
9
+ '\v' : '\\v' ,
10
+ '\f' : '\\f' ,
11
+ '\b' : '\\b' ,
12
+ '\r' : '\\r' ,
13
+ '\n' : '\\n' ,
14
+ '\\' : '\\\\' ,
15
+ '"' : '\\"' ,
16
+ "'" : "\\'" ,
17
+ } ) ,
18
+ ) ;
19
+
3
20
export function emit ( statements : Statement [ ] ) {
4
21
return statements . map ( emitStatement ) . join ( ';\n' ) ;
5
22
}
@@ -24,7 +41,22 @@ function emitExpression(expression: Expression): string {
24
41
return expression . text ;
25
42
case Node . Literal :
26
43
return '' + expression . value ;
44
+ case Node . StringLiteral :
45
+ return expression . isSingleQuote
46
+ ? `'${ escapeString ( expression . value , true ) } '`
47
+ : `"${ escapeString ( expression . value , false ) } "` ;
27
48
case Node . Assignment :
28
49
return `${ expression . name . text } = ${ emitExpression ( expression . value ) } ` ;
29
50
}
30
51
}
52
+
53
+ function escapeString ( string : string , isSingleQuote : boolean ) {
54
+ return string . replace (
55
+ isSingleQuote ? singleQuoteRegex : doubleQuoteRegex ,
56
+ replacement ,
57
+ ) ;
58
+ }
59
+
60
+ function replacement ( char : string ) {
61
+ return escapedCharsMap . get ( char ) || char ;
62
+ }
Original file line number Diff line number Diff line change @@ -11,12 +11,14 @@ export function lex(s: string): Lexer {
11
11
let pos = 0 ;
12
12
let text = '' ;
13
13
let token = Token . BOF ;
14
+ let firstChar : string ;
14
15
15
16
return {
16
17
scan,
17
18
token : ( ) => token ,
18
19
pos : ( ) => pos ,
19
20
text : ( ) => text ,
21
+ isSingleQuote : ( ) => firstChar === "'" ,
20
22
} ;
21
23
22
24
function scan ( ) {
@@ -41,6 +43,7 @@ export function lex(s: string): Lexer {
41
43
? keywords [ text as keyof typeof keywords ]
42
44
: Token . Identifier ;
43
45
} else if ( [ '"' , "'" ] . includes ( s . charAt ( pos ) ) ) {
46
+ firstChar = s . charAt ( pos ) ;
44
47
text = scanString ( ) ;
45
48
token = Token . String ;
46
49
} else {
@@ -114,9 +117,11 @@ export function lex(s: string): Lexer {
114
117
case CharCodes . r :
115
118
return '\r' ;
116
119
case CharCodes . singleQuote :
117
- return "'" ;
120
+ // prettier-ignore
121
+ return "\'" ;
118
122
case CharCodes . doubleQuote :
119
- return '"' ;
123
+ // prettier-ignore
124
+ return '\"' ;
120
125
default :
121
126
return String . fromCharCode ( char ) ;
122
127
}
Original file line number Diff line number Diff line change @@ -37,7 +37,12 @@ export function parse(lexer: Lexer): Module {
37
37
} else if ( tryParseToken ( Token . Literal ) ) {
38
38
return { kind : Node . Literal , value : + lexer . text ( ) , pos } ;
39
39
} else if ( tryParseToken ( Token . String ) ) {
40
- return { kind : Node . Literal , value : lexer . text ( ) , pos } ;
40
+ return {
41
+ kind : Node . StringLiteral ,
42
+ value : lexer . text ( ) ,
43
+ pos,
44
+ isSingleQuote : lexer . isSingleQuote ( ) ,
45
+ } ;
41
46
}
42
47
error (
43
48
pos ,
Original file line number Diff line number Diff line change @@ -21,6 +21,7 @@ export type Lexer = {
21
21
token ( ) : Token ;
22
22
pos ( ) : number ;
23
23
text ( ) : string ;
24
+ isSingleQuote ( ) : boolean ;
24
25
} ;
25
26
26
27
export enum Node {
@@ -30,6 +31,7 @@ export enum Node {
30
31
ExpressionStatement ,
31
32
Var ,
32
33
TypeAlias ,
34
+ StringLiteral ,
33
35
}
34
36
35
37
export type Error = {
@@ -41,7 +43,7 @@ export interface Location {
41
43
pos : number ;
42
44
}
43
45
44
- export type Expression = Identifier | Literal | Assignment ;
46
+ export type Expression = Identifier | Literal | Assignment | StringLiteral ;
45
47
46
48
export type Identifier = Location & {
47
49
kind : Node . Identifier ;
@@ -50,7 +52,13 @@ export type Identifier = Location & {
50
52
51
53
export type Literal = Location & {
52
54
kind : Node . Literal ;
53
- value : number | string ;
55
+ value : number ;
56
+ } ;
57
+
58
+ export type StringLiteral = Location & {
59
+ kind : Node . StringLiteral ;
60
+ value : string ;
61
+ isSingleQuote : boolean ;
54
62
} ;
55
63
56
64
export type Assignment = Location & {
You can’t perform that action at this time.
0 commit comments