Skip to content

Commit

Permalink
Merge pull request #149 from babel/fix-annex-b-quantifiable-assertion
Browse files Browse the repository at this point in the history
fix: only ±lookbehind is quantifiable in annexB
  • Loading branch information
jviereck authored Oct 25, 2024
2 parents 77216e7 + 91d119f commit 4dda218
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 34 deletions.
80 changes: 50 additions & 30 deletions parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -567,51 +567,71 @@
function parseTerm() {
// Term ::
// Anchor
// Anchor Quantifier (see https://github.com/jviereck/regjsparser/issues/130)
// Atom
// Atom Quantifier

// Term (Annex B)::
// [~UnicodeMode] QuantifiableAssertion Quantifier (see https://github.com/jviereck/regjsparser/issues/130)
// [~UnicodeMode] ExtendedAtom Quantifier

// QuantifiableAssertion::
// (?= Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] )
// (?! Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] )

if (pos >= str.length || current('|') || current(')')) {
return null; /* Means: The term is empty */
}

var anchorOrAtom = parseAnchor();
var anchor = parseAnchor();

// If there is no Anchor, try to parse an atom.
if (!anchorOrAtom) {
var atom = parseAtomAndExtendedAtom();
var quantifier;
if (!atom) {
// Check if a quantifier is following. A quantifier without an atom
// is an error.
var pos_backup = pos
quantifier = parseQuantifier() || false;
if (quantifier) {
pos = pos_backup
bail('Expected atom');
if (anchor) {
var pos_backup = pos;
quantifier = parseQuantifier() || false;
if (quantifier) {
// Annex B
if (!isUnicodeMode && anchor.type === "group") {
quantifier.body = flattenBody(anchor);
// The quantifier contains the anchor. Therefore, the beginning of the
// quantifier range is given by the beginning of the anchor.
updateRawStart(quantifier, anchor.range[0]);
return quantifier;
}
pos = pos_backup;
bail("Expected atom");
}
return anchor;
}

// If no unicode flag, then try to parse ExtendedAtom -> ExtendedPatternCharacter.
// ExtendedPatternCharacter
var res;
if (!isUnicodeMode && (res = matchReg(/^\{/))) {
atom = createCharacter(res);
} else {
bail('Expected atom');
}
// If there is no Anchor, try to parse an atom.
var atom = parseAtomAndExtendedAtom();
var quantifier;
if (!atom) {
// Check if a quantifier is following. A quantifier without an atom
// is an error.
pos_backup = pos;
quantifier = parseQuantifier() || false;
if (quantifier) {
pos = pos_backup;
bail("Expected atom");
}

// If no unicode flag, then try to parse ExtendedAtom -> ExtendedPatternCharacter.
// ExtendedPatternCharacter
var res;
if (!isUnicodeMode && (res = matchReg(/^\{/))) {
atom = createCharacter(res);
} else {
bail("Expected atom");
}
anchorOrAtom = atom;
}

quantifier = parseQuantifier() || false;
if (quantifier) {
var type = anchorOrAtom.type, behavior = anchorOrAtom.behavior;
var type = atom.type, behavior = atom.behavior;
if (
type === "group" &&
(behavior === "negativeLookbehind" ||
behavior === "lookbehind" ||
(isUnicodeMode &&
(behavior === "negativeLookahead" || behavior === "lookahead")))
behavior === "lookbehind")
) {
bail(
"Invalid quantifier",
Expand All @@ -620,13 +640,13 @@
quantifier.range[1]
);
}
quantifier.body = flattenBody(anchorOrAtom);
quantifier.body = flattenBody(atom);
// The quantifier contains the atom. Therefore, the beginning of the
// quantifier range is given by the beginning of the atom.
updateRawStart(quantifier, anchorOrAtom.range[0]);
updateRawStart(quantifier, atom.range[0]);
return quantifier;
}
return anchorOrAtom;
return atom;
}

function parseGroup(matchA, typeA, matchB, typeB) {
Expand Down
4 changes: 2 additions & 2 deletions test/test-data-unicode-set.json
Original file line number Diff line number Diff line change
Expand Up @@ -1499,13 +1499,13 @@
".(?=.){2,3}": {
"type": "error",
"name": "SyntaxError",
"message": "Invalid quantifier at position 6\n .(?=.){2,3}\n ^",
"message": "Expected atom at position 6\n .(?=.){2,3}\n ^",
"input": ".(?=.){2,3}"
},
".(?!.){2,3}": {
"type": "error",
"name": "SyntaxError",
"message": "Invalid quantifier at position 6\n .(?!.){2,3}\n ^",
"message": "Expected atom at position 6\n .(?!.){2,3}\n ^",
"input": ".(?!.){2,3}"
},
"[\\__]": {
Expand Down
28 changes: 26 additions & 2 deletions test/test-data-unicode.json
Original file line number Diff line number Diff line change
Expand Up @@ -1232,13 +1232,13 @@
".(?=.){2,3}": {
"type": "error",
"name": "SyntaxError",
"message": "Invalid quantifier at position 6\n .(?=.){2,3}\n ^",
"message": "Expected atom at position 6\n .(?=.){2,3}\n ^",
"input": ".(?=.){2,3}"
},
".(?!.){2,3}": {
"type": "error",
"name": "SyntaxError",
"message": "Invalid quantifier at position 6\n .(?!.){2,3}\n ^",
"message": "Expected atom at position 6\n .(?!.){2,3}\n ^",
"input": ".(?!.){2,3}"
},
"[&&]": {
Expand Down Expand Up @@ -1848,5 +1848,29 @@
4
],
"raw": "[~~]"
},
"^*": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 1\n ^*\n ^",
"input": "^*"
},
"$+": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 1\n $+\n ^",
"input": "$+"
},
"\\b?": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 2\n \\b?\n ^",
"input": "\\b?"
},
"\\B{1}": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 2\n \\B{1}\n ^",
"input": "\\B{1}"
}
}
24 changes: 24 additions & 0 deletions test/test-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -38626,5 +38626,29 @@
11
],
"raw": ".(?!.){2,3}"
},
"^*": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 1\n ^*\n ^",
"input": "^*"
},
"$+": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 1\n $+\n ^",
"input": "$+"
},
"\\b?": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 2\n \\b?\n ^",
"input": "\\b?"
},
"\\B{1}": {
"type": "error",
"name": "SyntaxError",
"message": "Expected atom at position 2\n \\B{1}\n ^",
"input": "\\B{1}"
}
}

0 comments on commit 4dda218

Please sign in to comment.