tweak-parser
Rich Harris 15 hours ago
parent d2e89640ec
commit b3fb4365b6

@ -1,9 +1,10 @@
/** @import { Pattern } from 'estree' */
/** @import { Expression, Pattern, ObjectPattern, Property, Identifier, RestElement, ArrayPattern } from 'estree' */
/** @import { Parser } from '../index.js' */
import { match_bracket } from '../utils/bracket.js';
import { parse_expression_at } from '../acorn.js';
import { regex_not_newline_characters } from '../../patterns.js';
import * as e from '../../../errors.js';
import { get_loc } from '../../../state.js';
/**
* @param {Parser} parser
@ -13,6 +14,14 @@ export default function read_pattern(parser) {
const start = parser.index;
let i = parser.index;
if (parser.match('{')) {
return read_object_pattern(parser);
}
if (parser.match('[')) {
return read_array_pattern(parser);
}
const id = parser.read_identifier();
if (id.name !== '') {
@ -67,6 +76,231 @@ export default function read_pattern(parser) {
return expression;
}
/**
* @param {Parser} parser
* @returns {ObjectPattern}
*/
function read_object_pattern(parser) {
const start = parser.index;
parser.eat('{', true);
/** @type {Array<Property | RestElement>} */
const properties = [];
/** @type {ObjectPattern} */
const pattern = {
type: 'ObjectPattern',
start,
end: -1,
// @ts-ignore I think the ESTree types might just be wrong here?
properties
};
while (true) {
parser.allow_whitespace();
const start = parser.index;
if (parser.match('}')) {
// can end up here if last element had a trailing comma
break;
}
if (parser.eat('...')) {
parser.allow_whitespace();
const argument = parser.read_identifier();
properties.push({
type: 'RestElement',
start,
end: argument.end,
argument,
loc: get_loc(start, argument.end)
});
parser.allow_whitespace();
break;
}
const computed = parser.eat('[');
const key = computed
? /** @type {Expression} */ (parse_expression_at(parser, parser.template, parser.index))
: parser.read_identifier();
if (computed) parser.eat(']', true);
/** @type {Property} */
const property = {
type: 'Property',
start,
end: -1,
key,
value: /** @type {Identifier} */ (key),
method: false,
shorthand: true,
computed,
kind: 'init'
};
parser.allow_whitespace();
if (parser.eat(':', computed)) {
property.value = read_pattern(parser);
property.shorthand = false;
}
parser.allow_whitespace();
if (parser.eat('=')) {
parser.allow_whitespace();
const start = parser.index;
let right = /** @type {Expression} */ (
parse_expression_at(parser, parser.template, parser.index)
);
if (right.type === 'SequenceExpression' && right.start === start) {
right = right.expressions[0];
parser.index = /** @type {number} */ (right.end);
}
property.value = {
type: 'AssignmentPattern',
start: property.value.start,
end: right.end,
left: /** @type {Pattern} */ (property.value),
right,
loc: get_loc(property.value.start, right.end)
};
}
if (parser.ts) {
property.typeAnnotation = read_type_annotation(parser);
}
property.end = parser.index;
property.loc = get_loc(start, property.end);
properties.push(property);
parser.allow_whitespace();
if (!parser.eat(',')) {
break;
}
}
parser.allow_whitespace();
parser.eat('}', true);
pattern.end = parser.index;
pattern.loc = get_loc(start, parser.index);
return pattern;
}
/**
* @param {Parser} parser
* @returns {ArrayPattern}
*/
function read_array_pattern(parser) {
const start = parser.index;
parser.eat('[', true);
/** @type {Pattern[]} */
const elements = [];
/** @type {ArrayPattern} */
const pattern = {
type: 'ArrayPattern',
start,
end: -1,
elements
};
while (true) {
parser.allow_whitespace();
const start = parser.index;
if (parser.match('}')) {
// can end up here if last element had a trailing comma
break;
}
if (parser.eat('...')) {
parser.allow_whitespace();
const argument = parser.read_identifier();
elements.push({
type: 'RestElement',
start,
end: argument.end,
argument,
loc: get_loc(start, argument.end)
});
parser.allow_whitespace();
break;
}
let element = read_pattern(parser);
parser.allow_whitespace();
if (parser.eat('=')) {
parser.allow_whitespace();
const start = parser.index;
let right = /** @type {Expression} */ (
parse_expression_at(parser, parser.template, parser.index)
);
if (right.type === 'SequenceExpression' && right.start === start) {
right = right.expressions[0];
parser.index = /** @type {number} */ (right.end);
}
element = {
type: 'AssignmentPattern',
start: element.start,
end: right.end,
left: /** @type {Pattern} */ (element),
right,
loc: get_loc(element.start, right.end)
};
}
if (parser.ts) {
element.typeAnnotation = read_type_annotation(parser);
}
element.end = parser.index;
element.loc = get_loc(start, element.end);
elements.push(element);
parser.allow_whitespace();
if (!parser.eat(',')) {
break;
}
}
parser.allow_whitespace();
parser.eat(']', true);
pattern.end = parser.index;
pattern.loc = get_loc(start, parser.index);
return pattern;
}
/**
* @param {Parser} parser
* @returns {any}

@ -14,6 +14,7 @@ import { get_attribute_expression, is_expression_attribute } from '../../../util
import { closing_tag_omitted } from '../../../../html-tree-validation.js';
import { list } from '../../../utils/string.js';
import { locator } from '../../../state.js';
import { read_comment } from '../utils/comment.js';
const regex_invalid_unquoted_attribute_value = /(\/>|[\s"'=<>`])/y;
const regex_closing_textarea_tag = /<\/textarea(\s[^>]*)?>/iy;
@ -716,50 +717,6 @@ function read_attribute(parser) {
return create_attribute(tag.name, tag.loc, start, end, value);
}
/**
* @param {Parser} parser
* @returns {AST.JSComment | null}
*/
function read_comment(parser) {
const start = parser.index;
if (parser.eat('//')) {
const value = parser.read_until(/\n/);
const end = parser.index;
return {
type: 'Line',
start,
end,
value,
loc: {
start: locator(start),
end: locator(end)
}
};
}
if (parser.eat('/*')) {
const value = parser.read_until(/\*\//);
parser.eat('*/');
const end = parser.index;
return {
type: 'Block',
start,
end,
value,
loc: {
start: locator(start),
end: locator(end)
}
};
}
return null;
}
/**
* @param {string} name
* @returns {any}

@ -0,0 +1,47 @@
/** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */
import { locator } from '../../../state.js';
/**
* @param {Parser} parser
* @returns {AST.JSComment | null}
*/
export function read_comment(parser) {
const start = parser.index;
if (parser.eat('//')) {
const value = parser.read_until(/\n/);
const end = parser.index;
return {
type: 'Line',
start,
end,
value,
loc: {
start: locator(start),
end: locator(end)
}
};
}
if (parser.eat('/*')) {
const value = parser.read_until(/\*\//);
parser.eat('*/');
const end = parser.index;
return {
type: 'Block',
start,
end,
value,
loc: {
start: locator(start),
end: locator(end)
}
};
}
return null;
}

@ -49,6 +49,22 @@ export let runes = false;
/** @type {(index: number) => Location} */
export let locator;
/**
* @param {number | undefined} start
* @param {number | undefined} end
*/
export function get_loc(start, end) {
if (start !== undefined && end !== undefined) {
const s = locator(start);
const e = locator(end);
return {
start: { line: s.line, column: s.column },
end: { line: e.line, column: e.column }
};
}
}
/** @param {string} value */
export function set_source(value) {
source = value;

@ -82,11 +82,11 @@
"loc": {
"start": {
"line": 5,
"column": 19
"column": 18
},
"end": {
"line": 5,
"column": 40
"column": 39
}
},
"elements": [
@ -97,11 +97,11 @@
"loc": {
"start": {
"line": 5,
"column": 20
"column": 19
},
"end": {
"line": 5,
"column": 23
"column": 22
}
},
"name": "key"
@ -113,11 +113,11 @@
"loc": {
"start": {
"line": 5,
"column": 25
"column": 24
},
"end": {
"line": 5,
"column": 30
"column": 29
}
},
"name": "value"
@ -129,11 +129,11 @@
"loc": {
"start": {
"line": 5,
"column": 32
"column": 31
},
"end": {
"line": 5,
"column": 39
"column": 38
}
},
"argument": {
@ -143,11 +143,13 @@
"loc": {
"start": {
"line": 5,
"column": 35
"column": 34,
"character": 75
},
"end": {
"line": 5,
"column": 39
"column": 38,
"character": 79
}
},
"name": "rest"

@ -70,11 +70,13 @@
"loc": {
"start": {
"line": 1,
"column": 14
"column": 14,
"character": 14
},
"end": {
"line": 1,
"column": 15
"column": 15,
"character": 15
}
},
"name": "y"
@ -100,11 +102,13 @@
"loc": {
"start": {
"line": 1,
"column": 14
"column": 14,
"character": 14
},
"end": {
"line": 1,
"column": 15
"column": 15,
"character": 15
}
},
"name": "y"
@ -170,11 +174,11 @@
"loc": {
"start": {
"line": 3,
"column": 13
"column": 12
},
"end": {
"line": 3,
"column": 24
"column": 23
}
},
"properties": [
@ -185,11 +189,11 @@
"loc": {
"start": {
"line": 3,
"column": 15
"column": 14
},
"end": {
"line": 3,
"column": 22
"column": 21
}
},
"method": false,
@ -202,11 +206,13 @@
"loc": {
"start": {
"line": 3,
"column": 15
"column": 14,
"character": 47
},
"end": {
"line": 3,
"column": 16
"column": 15,
"character": 48
}
},
"name": "y"
@ -218,11 +224,11 @@
"loc": {
"start": {
"line": 3,
"column": 15
"column": 14
},
"end": {
"line": 3,
"column": 22
"column": 21
}
},
"left": {
@ -232,11 +238,13 @@
"loc": {
"start": {
"line": 3,
"column": 15
"column": 14,
"character": 47
},
"end": {
"line": 3,
"column": 16
"column": 15,
"character": 48
}
},
"name": "y"
@ -248,11 +256,11 @@
"loc": {
"start": {
"line": 3,
"column": 19
"column": 18
},
"end": {
"line": 3,
"column": 22
"column": 21
}
},
"value": "{",
@ -302,11 +310,11 @@
"loc": {
"start": {
"line": 5,
"column": 13
"column": 12
},
"end": {
"line": 5,
"column": 24
"column": 23
}
},
"properties": [
@ -317,11 +325,11 @@
"loc": {
"start": {
"line": 5,
"column": 15
"column": 14
},
"end": {
"line": 5,
"column": 22
"column": 21
}
},
"method": false,
@ -334,11 +342,13 @@
"loc": {
"start": {
"line": 5,
"column": 15
"column": 14,
"character": 80
},
"end": {
"line": 5,
"column": 16
"column": 15,
"character": 81
}
},
"name": "y"
@ -350,11 +360,11 @@
"loc": {
"start": {
"line": 5,
"column": 15
"column": 14
},
"end": {
"line": 5,
"column": 22
"column": 21
}
},
"left": {
@ -364,11 +374,13 @@
"loc": {
"start": {
"line": 5,
"column": 15
"column": 14,
"character": 80
},
"end": {
"line": 5,
"column": 16
"column": 15,
"character": 81
}
},
"name": "y"
@ -380,11 +392,11 @@
"loc": {
"start": {
"line": 5,
"column": 19
"column": 18
},
"end": {
"line": 5,
"column": 22
"column": 21
}
},
"value": "]",
@ -434,11 +446,11 @@
"loc": {
"start": {
"line": 7,
"column": 13
"column": 12
},
"end": {
"line": 7,
"column": 29
"column": 28
}
},
"properties": [
@ -449,11 +461,11 @@
"loc": {
"start": {
"line": 7,
"column": 15
"column": 14
},
"end": {
"line": 7,
"column": 27
"column": 26
}
},
"method": false,
@ -466,11 +478,13 @@
"loc": {
"start": {
"line": 7,
"column": 15
"column": 14,
"character": 113
},
"end": {
"line": 7,
"column": 16
"column": 15,
"character": 114
}
},
"name": "y"
@ -482,11 +496,11 @@
"loc": {
"start": {
"line": 7,
"column": 15
"column": 14
},
"end": {
"line": 7,
"column": 27
"column": 26
}
},
"left": {
@ -496,11 +510,13 @@
"loc": {
"start": {
"line": 7,
"column": 15
"column": 14,
"character": 113
},
"end": {
"line": 7,
"column": 16
"column": 15,
"character": 114
}
},
"name": "y"
@ -512,11 +528,11 @@
"loc": {
"start": {
"line": 7,
"column": 19
"column": 18
},
"end": {
"line": 7,
"column": 27
"column": 26
}
},
"expressions": [
@ -527,11 +543,11 @@
"loc": {
"start": {
"line": 7,
"column": 22
"column": 21
},
"end": {
"line": 7,
"column": 25
"column": 24
}
},
"expressions": [],
@ -543,11 +559,11 @@
"loc": {
"start": {
"line": 7,
"column": 23
"column": 22
},
"end": {
"line": 7,
"column": 24
"column": 23
}
},
"value": {
@ -567,11 +583,11 @@
"loc": {
"start": {
"line": 7,
"column": 20
"column": 19
},
"end": {
"line": 7,
"column": 20
"column": 19
}
},
"value": {
@ -587,11 +603,11 @@
"loc": {
"start": {
"line": 7,
"column": 26
"column": 25
},
"end": {
"line": 7,
"column": 26
"column": 25
}
},
"value": {
@ -646,11 +662,11 @@
"loc": {
"start": {
"line": 9,
"column": 13
"column": 12
},
"end": {
"line": 9,
"column": 32
"column": 31
}
},
"properties": [
@ -661,11 +677,11 @@
"loc": {
"start": {
"line": 9,
"column": 15
"column": 14
},
"end": {
"line": 9,
"column": 30
"column": 29
}
},
"method": false,
@ -678,11 +694,13 @@
"loc": {
"start": {
"line": 9,
"column": 15
"column": 14,
"character": 151
},
"end": {
"line": 9,
"column": 16
"column": 15,
"character": 152
}
},
"name": "y"
@ -694,11 +712,11 @@
"loc": {
"start": {
"line": 9,
"column": 15
"column": 14
},
"end": {
"line": 9,
"column": 30
"column": 29
}
},
"left": {
@ -708,11 +726,13 @@
"loc": {
"start": {
"line": 9,
"column": 15
"column": 14,
"character": 151
},
"end": {
"line": 9,
"column": 16
"column": 15,
"character": 152
}
},
"name": "y"
@ -724,11 +744,11 @@
"loc": {
"start": {
"line": 9,
"column": 19
"column": 18
},
"end": {
"line": 9,
"column": 30
"column": 29
}
},
"expressions": [
@ -739,11 +759,11 @@
"loc": {
"start": {
"line": 9,
"column": 22
"column": 21
},
"end": {
"line": 9,
"column": 28
"column": 27
}
},
"expressions": [],
@ -755,11 +775,11 @@
"loc": {
"start": {
"line": 9,
"column": 23
"column": 22
},
"end": {
"line": 9,
"column": 27
"column": 26
}
},
"value": {
@ -779,11 +799,11 @@
"loc": {
"start": {
"line": 9,
"column": 20
"column": 19
},
"end": {
"line": 9,
"column": 20
"column": 19
}
},
"value": {
@ -799,11 +819,11 @@
"loc": {
"start": {
"line": 9,
"column": 29
"column": 28
},
"end": {
"line": 9,
"column": 29
"column": 28
}
},
"value": {

@ -207,11 +207,13 @@
"loc": {
"start": {
"line": 1,
"column": 19
"column": 19,
"character": 19
},
"end": {
"line": 1,
"column": 23
"column": 23,
"character": 23
}
},
"name": "name"
@ -223,11 +225,13 @@
"loc": {
"start": {
"line": 1,
"column": 19
"column": 19,
"character": 19
},
"end": {
"line": 1,
"column": 23
"column": 23,
"character": 23
}
},
"name": "name"
@ -258,11 +262,13 @@
"loc": {
"start": {
"line": 1,
"column": 25
"column": 25,
"character": 25
},
"end": {
"line": 1,
"column": 29
"column": 29,
"character": 29
}
},
"name": "cool"
@ -288,11 +294,13 @@
"loc": {
"start": {
"line": 1,
"column": 25
"column": 25,
"character": 25
},
"end": {
"line": 1,
"column": 29
"column": 29,
"character": 29
}
},
"name": "cool"
@ -495,11 +503,11 @@
"loc": {
"start": {
"line": 5,
"column": 18
"column": 17
},
"end": {
"line": 5,
"column": 57
"column": 56
}
},
"properties": [
@ -510,11 +518,11 @@
"loc": {
"start": {
"line": 5,
"column": 20
"column": 19
},
"end": {
"line": 5,
"column": 42
"column": 41
}
},
"method": false,
@ -527,11 +535,13 @@
"loc": {
"start": {
"line": 5,
"column": 20
"column": 19,
"character": 115
},
"end": {
"line": 5,
"column": 24
"column": 23,
"character": 119
}
},
"name": "name"
@ -543,11 +553,11 @@
"loc": {
"start": {
"line": 5,
"column": 20
"column": 19
},
"end": {
"line": 5,
"column": 42
"column": 41
}
},
"left": {
@ -557,11 +567,13 @@
"loc": {
"start": {
"line": 5,
"column": 20
"column": 19,
"character": 115
},
"end": {
"line": 5,
"column": 24
"column": 23,
"character": 119
}
},
"name": "name"
@ -573,11 +585,11 @@
"loc": {
"start": {
"line": 5,
"column": 27
"column": 26
},
"end": {
"line": 5,
"column": 42
"column": 41
}
},
"expressions": [
@ -588,11 +600,11 @@
"loc": {
"start": {
"line": 5,
"column": 35
"column": 34
},
"end": {
"line": 5,
"column": 40
"column": 39
}
},
"value": "Doe",
@ -607,11 +619,11 @@
"loc": {
"start": {
"line": 5,
"column": 28
"column": 27
},
"end": {
"line": 5,
"column": 33
"column": 32
}
},
"value": {
@ -627,11 +639,11 @@
"loc": {
"start": {
"line": 5,
"column": 41
"column": 40
},
"end": {
"line": 5,
"column": 41
"column": 40
}
},
"value": {
@ -652,11 +664,11 @@
"loc": {
"start": {
"line": 5,
"column": 44
"column": 43
},
"end": {
"line": 5,
"column": 55
"column": 54
}
},
"method": false,
@ -669,11 +681,13 @@
"loc": {
"start": {
"line": 5,
"column": 44
"column": 43,
"character": 139
},
"end": {
"line": 5,
"column": 48
"column": 47,
"character": 143
}
},
"name": "cool"
@ -685,11 +699,11 @@
"loc": {
"start": {
"line": 5,
"column": 44
"column": 43
},
"end": {
"line": 5,
"column": 55
"column": 54
}
},
"left": {
@ -699,11 +713,13 @@
"loc": {
"start": {
"line": 5,
"column": 44
"column": 43,
"character": 139
},
"end": {
"line": 5,
"column": 48
"column": 47,
"character": 143
}
},
"name": "cool"
@ -715,11 +731,11 @@
"loc": {
"start": {
"line": 5,
"column": 51
"column": 50
},
"end": {
"line": 5,
"column": 55
"column": 54
}
},
"value": true,
@ -906,11 +922,11 @@
"loc": {
"start": {
"line": 9,
"column": 18
"column": 17
},
"end": {
"line": 9,
"column": 79
"column": 78
}
},
"properties": [
@ -921,11 +937,11 @@
"loc": {
"start": {
"line": 9,
"column": 20
"column": 19
},
"end": {
"line": 9,
"column": 64
"column": 63
}
},
"method": false,
@ -938,11 +954,13 @@
"loc": {
"start": {
"line": 9,
"column": 20
"column": 19,
"character": 229
},
"end": {
"line": 9,
"column": 24
"column": 23,
"character": 233
}
},
"name": "name"
@ -954,11 +972,11 @@
"loc": {
"start": {
"line": 9,
"column": 20
"column": 19
},
"end": {
"line": 9,
"column": 64
"column": 63
}
},
"left": {
@ -968,11 +986,13 @@
"loc": {
"start": {
"line": 9,
"column": 20
"column": 19,
"character": 229
},
"end": {
"line": 9,
"column": 24
"column": 23,
"character": 233
}
},
"name": "name"
@ -984,11 +1004,11 @@
"loc": {
"start": {
"line": 9,
"column": 27
"column": 26
},
"end": {
"line": 9,
"column": 64
"column": 63
}
},
"callee": {
@ -998,11 +1018,11 @@
"loc": {
"start": {
"line": 9,
"column": 28
"column": 27
},
"end": {
"line": 9,
"column": 61
"column": 60
}
},
"id": null,
@ -1017,11 +1037,11 @@
"loc": {
"start": {
"line": 9,
"column": 34
"column": 33
},
"end": {
"line": 9,
"column": 61
"column": 60
}
},
"body": [
@ -1032,11 +1052,11 @@
"loc": {
"start": {
"line": 9,
"column": 36
"column": 35
},
"end": {
"line": 9,
"column": 59
"column": 58
}
},
"argument": {
@ -1046,11 +1066,11 @@
"loc": {
"start": {
"line": 9,
"column": 43
"column": 42
},
"end": {
"line": 9,
"column": 58
"column": 57
}
},
"expressions": [
@ -1061,11 +1081,11 @@
"loc": {
"start": {
"line": 9,
"column": 51
"column": 50
},
"end": {
"line": 9,
"column": 56
"column": 55
}
},
"value": "Doe",
@ -1080,11 +1100,11 @@
"loc": {
"start": {
"line": 9,
"column": 44
"column": 43
},
"end": {
"line": 9,
"column": 49
"column": 48
}
},
"value": {
@ -1100,11 +1120,11 @@
"loc": {
"start": {
"line": 9,
"column": 57
"column": 56
},
"end": {
"line": 9,
"column": 57
"column": 56
}
},
"value": {
@ -1132,11 +1152,11 @@
"loc": {
"start": {
"line": 9,
"column": 66
"column": 65
},
"end": {
"line": 9,
"column": 77
"column": 76
}
},
"method": false,
@ -1149,11 +1169,13 @@
"loc": {
"start": {
"line": 9,
"column": 66
"column": 65,
"character": 275
},
"end": {
"line": 9,
"column": 70
"column": 69,
"character": 279
}
},
"name": "cool"
@ -1165,11 +1187,11 @@
"loc": {
"start": {
"line": 9,
"column": 66
"column": 65
},
"end": {
"line": 9,
"column": 77
"column": 76
}
},
"left": {
@ -1179,11 +1201,13 @@
"loc": {
"start": {
"line": 9,
"column": 66
"column": 65,
"character": 275
},
"end": {
"line": 9,
"column": 70
"column": 69,
"character": 279
}
},
"name": "cool"
@ -1195,11 +1219,11 @@
"loc": {
"start": {
"line": 9,
"column": 73
"column": 72
},
"end": {
"line": 9,
"column": 77
"column": 76
}
},
"value": true,

@ -133,11 +133,11 @@
"loc": {
"start": {
"line": 5,
"column": 15
"column": 14
},
"end": {
"line": 5,
"column": 39
"column": 38
}
},
"elements": [
@ -148,11 +148,11 @@
"loc": {
"start": {
"line": 5,
"column": 16
"column": 15
},
"end": {
"line": 5,
"column": 19
"column": 18
}
},
"name": "key"
@ -164,11 +164,11 @@
"loc": {
"start": {
"line": 5,
"column": 21
"column": 20
},
"end": {
"line": 5,
"column": 38
"column": 37
}
},
"left": {
@ -178,11 +178,13 @@
"loc": {
"start": {
"line": 5,
"column": 21
"column": 20,
"character": 65
},
"end": {
"line": 5,
"column": 26
"column": 25,
"character": 70
}
},
"name": "value"
@ -194,11 +196,11 @@
"loc": {
"start": {
"line": 5,
"column": 29
"column": 28
},
"end": {
"line": 5,
"column": 38
"column": 37
}
},
"value": "default",

Loading…
Cancel
Save