Skip to content

Commit

Permalink
fix: represent regular expressions as a Regex node
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Previously, regular expressions were represented as `Identifier` nodes, which hasn't been a problem for decaffeinate because all we wanted to do was pass them through anyway. Now, however, we want to do some processing on them and so need to identify them separately. Not to mention the fact that they are not identifiers!
  • Loading branch information
eventualbuddha committed Dec 31, 2016
1 parent 362a790 commit ddabbca
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/mappers/mapLiteral.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import SourceType from 'coffee-lex/dist/SourceType';
import { Literal } from 'decaffeinate-coffeescript/lib/coffee-script/nodes';
import { inspect } from 'util';
import { Float, Heregex, Identifier, Int, JavaScript, Node, Quasi, RegexFlags, String, This } from '../nodes';
import { Float, Heregex, Identifier, Int, JavaScript, Node, Quasi, Regex, RegexFlags, String, This } from '../nodes';
import isStringAtPosition from '../util/isStringAtPosition';
import ParseContext from '../util/ParseContext';
import parseNumber from '../util/parseNumber';
import parseRegExp from '../util/parseRegExp';
import parseString from '../util/parseString';
import mapBase from './mapBase';

Expand Down Expand Up @@ -50,6 +51,14 @@ export default function mapLiteral(context: ParseContext, node: Literal): Node {
}
}

if (startToken.type === SourceType.REGEXP) {
let regExp = parseRegExp(node.value);
return new Regex(
line, column, start, end, raw, virtual,
regExp.pattern, RegexFlags.parse(regExp.flags)
);
}

if (isStringAtPosition(start, end, context)) {
return new String(
line, column, start, end, raw, virtual,
Expand Down
21 changes: 21 additions & 0 deletions src/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ export class Null extends Node {
super('Null', line, column, start, end, raw, virtual);
}
}

export class Undefined extends Node {
constructor(
line: number,
Expand All @@ -347,6 +348,26 @@ export class Undefined extends Node {
}
}

export class Regex extends Node {
readonly pattern: string;
readonly flags: RegexFlags;

constructor(
line: number,
column: number,
start: number,
end: number,
raw: string,
virtual: boolean,
pattern: string,
flags: RegexFlags
) {
super('Regex', line, column, start, end, raw, virtual);
this.pattern = pattern;
this.flags = flags;
}
}

export class Return extends Node {
readonly argument: Node | null;

Expand Down
8 changes: 8 additions & 0 deletions src/util/parseRegExp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { parse } from 'babylon';

/**
* Parses JavaScript source representing a regular expression.
*/
export default function parseRegExp(string: string): { pattern: string, flags: string } {
return parse(`(${string})`).program.body[0].expression;
}
1 change: 1 addition & 0 deletions test/examples/regexp/input.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/a/
43 changes: 43 additions & 0 deletions test/examples/regexp/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"type": "Program",
"line": 1,
"column": 1,
"range": [
0,
4
],
"raw": "/a/\n",
"body": {
"type": "Block",
"line": 1,
"column": 1,
"range": [
0,
3
],
"statements": [
{
"type": "Regex",
"line": 1,
"column": 1,
"range": [
0,
3
],
"raw": "/a/",
"pattern": "a",
"flags": {
"global": false,
"ignoreCase": false,
"multiline": false,
"sticky": false,
"g": false,
"i": false,
"m": false,
"y": false
}
}
],
"raw": "/a/"
}
}

0 comments on commit ddabbca

Please sign in to comment.