Adding support for including ^ and $ in the middle of an expression

Closes #29
This commit is contained in:
Jeff Avallone
2016-07-26 22:27:17 -04:00
parent 851bc32141
commit 2ceb94fc42
6 changed files with 50 additions and 136 deletions
+15
View File
@@ -0,0 +1,15 @@
export default {
_render() {
return this.renderLabel(this.label).then(label => {
return label.addClass('anchor');
});
},
setup() {
if (this.textValue === '^') {
this.label = 'Start of line';
} else {
this.label = 'End of line';
}
}
};
+3 -4
View File
@@ -1,10 +1,9 @@
grammar JavascriptRegexp
root <- ( ( "/" regexp "/" flags:[igm]* ) / regexp flags:""? ) <Root>
regexp <- match:match alternates:( "|" match )* <Regexp>
match <- anchor_start:"^"?
(!repeat) parts:match_fragment*
anchor_end:"$"? <Match>
match_fragment <- content:( subexp / charset / terminal ) repeat:repeat? <MatchFragment>
match <- (!repeat) parts:match_fragment* <Match>
anchor <- ( "^" / "$" ) <Anchor>
match_fragment <- content:( anchor / subexp / charset / terminal ) repeat:repeat? <MatchFragment>
repeat <- spec:( repeat_any / repeat_required / repeat_optional / repeat_spec ) greedy:"?"? <Repeat>
repeat_any <- "*" <RepeatAny>
repeat_required <- "+" <RepeatRequired>
+6 -31
View File
@@ -29,39 +29,19 @@ export default {
// Renders the match into the currently set container.
_render() {
var start, end,
partPromises,
var partPromises,
items;
// A `^` at the beginning of the match leads to the "Start of line"
// indicator being rendered.
if (this.anchorStart) {
start = this.renderLabel('Start of line')
.then(label => {
return label.addClass('anchor');
});
}
// A `$` at the end of the match leads to the "End of line" indicator
// being rendered.
if (this.anchorEnd) {
end = this.renderLabel('End of line')
.then(label => {
return label.addClass('anchor');
});
}
// Render each of the match fragments.
partPromises = _.map(this.parts, part => {
return part.render(this.container.group());
});
items = _([start, partPromises, end]).flatten().compact().value();
items = _(partPromises).compact().value();
// Handle the situation where a regular expression of `()` is rendered.
// This leads to a Match node with no fragments, no start indicator, and
// no end indicator. Something must be rendered so that the anchor can be
// calculated based on it.
// This leads to a Match node with no fragments. Something must be rendered
// so that the anchor can be calculated based on it.
//
// Furthermore, the content rendered must have height and width or else the
// anchor calculations fail.
@@ -120,13 +100,8 @@ export default {
return result;
}, []);
// Indicates if the expression starts with a `^`.
this.anchorStart = (this.properties.anchor_start.textValue !== '');
// Indicates if the expression ends with a `$`.
this.anchorEnd = (this.properties.anchor_end.textValue !== '');
// When there are no anchors and only one part, then proxy to the part.
if (!this.anchorStart && !this.anchorEnd && this.parts.length === 1) {
// When there is only one part, then proxy to the part.
if (this.parts.length === 1) {
this.proxy = this.parts[0];
}
}
+2
View File
@@ -9,6 +9,7 @@ import Root from './root.js';
import Regexp from './regexp.js';
import Match from './match.js';
import MatchFragment from './match_fragment.js';
import Anchor from './anchor.js';
import Subexp from './subexp.js';
import Charset from './charset.js';
import CharsetEscape from './charset_escape.js';
@@ -35,6 +36,7 @@ parser.Parser.Root = { module: Root };
parser.Parser.Regexp = { module: Regexp };
parser.Parser.Match = { module: Match };
parser.Parser.MatchFragment = { module: MatchFragment };
parser.Parser.Anchor = { module: Anchor };
parser.Parser.Subexp = { module: Subexp };
parser.Parser.Charset = { module: Charset };
parser.Parser.CharsetEscape = { module: CharsetEscape };