Skip to content

Commit

Permalink
Fix escape sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
imteekay committed Apr 28, 2023
1 parent bc76e30 commit c5e8220
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export function check(module: Module) {
error(expression.pos, 'Could not resolve ' + expression.text);
return errorType;
case Node.Literal:
return typeof expression.value === 'string' ? stringType : numberType;
return numberType;
case Node.StringLiteral:
return stringType;
case Node.Assignment:
const v = checkExpression(expression.value);
const t = checkExpression(expression.name);
Expand Down
32 changes: 32 additions & 0 deletions src/emit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { Statement, Node, Expression } from './types';

const singleQuoteRegex = /[\\\'\t\v\f\b\r\n]/g;
const doubleQuoteRegex = /[\\\"\t\v\f\b\r\n]/g;

const escapedCharsMap = new Map(
Object.entries({
'\t': '\\t',
'\v': '\\v',
'\f': '\\f',
'\b': '\\b',
'\r': '\\r',
'\n': '\\n',
'\\': '\\\\',
'"': '\\"',
"'": "\\'",
}),
);

export function emit(statements: Statement[]) {
return statements.map(emitStatement).join(';\n');
}
Expand All @@ -24,7 +41,22 @@ function emitExpression(expression: Expression): string {
return expression.text;
case Node.Literal:
return '' + expression.value;
case Node.StringLiteral:
return expression.isSingleQuote
? `'${escapeString(expression.value, true)}'`
: `"${escapeString(expression.value, false)}"`;
case Node.Assignment:
return `${expression.name.text} = ${emitExpression(expression.value)}`;
}
}

function escapeString(string: string, isSingleQuote: boolean) {
return string.replace(
isSingleQuote ? singleQuoteRegex : doubleQuoteRegex,
replacement,
);
}

function replacement(char: string) {
return escapedCharsMap.get(char) || char;
}
9 changes: 7 additions & 2 deletions src/lex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ export function lex(s: string): Lexer {
let pos = 0;
let text = '';
let token = Token.BOF;
let firstChar: string;

return {
scan,
token: () => token,
pos: () => pos,
text: () => text,
isSingleQuote: () => firstChar === "'",
};

function scan() {
Expand All @@ -41,6 +43,7 @@ export function lex(s: string): Lexer {
? keywords[text as keyof typeof keywords]
: Token.Identifier;
} else if (['"', "'"].includes(s.charAt(pos))) {
firstChar = s.charAt(pos);
text = scanString();
token = Token.String;
} else {
Expand Down Expand Up @@ -114,9 +117,11 @@ export function lex(s: string): Lexer {
case CharCodes.r:
return '\r';
case CharCodes.singleQuote:
return "'";
// prettier-ignore
return "\'";
case CharCodes.doubleQuote:
return '"';
// prettier-ignore
return '\"';
default:
return String.fromCharCode(char);
}
Expand Down
7 changes: 6 additions & 1 deletion src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ export function parse(lexer: Lexer): Module {
} else if (tryParseToken(Token.Literal)) {
return { kind: Node.Literal, value: +lexer.text(), pos };
} else if (tryParseToken(Token.String)) {
return { kind: Node.Literal, value: lexer.text(), pos };
return {
kind: Node.StringLiteral,
value: lexer.text(),
pos,
isSingleQuote: lexer.isSingleQuote(),
};
}
error(
pos,
Expand Down
12 changes: 10 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type Lexer = {
token(): Token;
pos(): number;
text(): string;
isSingleQuote(): boolean;
};

export enum Node {
Expand All @@ -30,6 +31,7 @@ export enum Node {
ExpressionStatement,
Var,
TypeAlias,
StringLiteral,
}

export type Error = {
Expand All @@ -41,7 +43,7 @@ export interface Location {
pos: number;
}

export type Expression = Identifier | Literal | Assignment;
export type Expression = Identifier | Literal | Assignment | StringLiteral;

export type Identifier = Location & {
kind: Node.Identifier;
Expand All @@ -50,7 +52,13 @@ export type Identifier = Location & {

export type Literal = Location & {
kind: Node.Literal;
value: number | string;
value: number;
};

export type StringLiteral = Location & {
kind: Node.StringLiteral;
value: string;
isSingleQuote: boolean;
};

export type Assignment = Location & {
Expand Down

0 comments on commit c5e8220

Please sign in to comment.