diff --git a/spec/parser/javascript/subexp_spec.js b/spec/parser/javascript/subexp_spec.js index cd559386..3073beb9 100644 --- a/spec/parser/javascript/subexp_spec.js +++ b/spec/parser/javascript/subexp_spec.js @@ -22,6 +22,9 @@ describe('parser/javascript/subexp.js', function() { '(?:test)': { regexp: jasmine.objectContaining({ textValue: 'test' }), proxy: jasmine.objectContaining({ textValue: 'test' }) + }, + '(?test)': { + regexp: jasmine.objectContaining({ textValue: 'test' }) } }, (content, str) => { it(`parses "${str}" as a Subexp`, function() { @@ -106,6 +109,10 @@ describe('parser/javascript/subexp.js', function() { '(?:test)': { label: '', groupCounter: 1 + }, + '(?test)': { + label: 'group \'name\'', + groupCounter: 1 } }, (data, str) => { it(`generates the correct label for "${str}"`, function() { diff --git a/src/js/parser/javascript/grammar.peg b/src/js/parser/javascript/grammar.peg index 37ef9d5f..3f2f2d77 100644 --- a/src/js/parser/javascript/grammar.peg +++ b/src/js/parser/javascript/grammar.peg @@ -11,7 +11,10 @@ grammar JavascriptRegexp repeat_spec <- ( "{" min:[0-9]+ "," max:[0-9]+ "}" / "{" min:[0-9]+ ",}" / "{" exact:[0-9]+ "}" ) - subexp <- "(" capture:( "?:" / "?=" / "?!" )? regexp ")" + subexp <- "(" capture:( "?:" / "?=" / "?!" / "?<" groupname:name ">" )? regexp ")" + name <- alpha (alpha / numeric)* + alpha <- [a-zA-Z] + numeric <- [0-9] charset <- "[" invert:"^"? parts:( charset_range / charset_terminal )* "]" charset_range <- first:charset_range_terminal "-" last:charset_range_terminal charset_terminal <- charset_escape diff --git a/src/js/parser/javascript/subexp.js b/src/js/parser/javascript/subexp.js index 9f97811f..d271ad5e 100644 --- a/src/js/parser/javascript/subexp.js +++ b/src/js/parser/javascript/subexp.js @@ -48,6 +48,10 @@ export default { label() { if (_.has(this.labelMap, this.properties.capture.textValue)) { return this.labelMap[this.properties.capture.textValue]; + } else if (this.properties.capture != undefined + && this.properties.capture.properties != undefined + && this.properties.capture.properties.groupname) { + return `group '${this.properties.capture.properties.groupname.textValue}'`; } else { return `group #${this.state.groupCounter++}`; }