diff --git a/src/index.html b/src/index.html index 8513cf7..b89817c 100644 --- a/src/index.html +++ b/src/index.html @@ -40,14 +40,26 @@ stroke: #000; } - .anchor text { + .anchor text, .any-character text { fill: #fff; } - .anchor rect { + .anchor rect, .any-character rect { fill: #6b6659; } + .escape text, .literal text { + fill: #000; + } + + .escape rect { + fill: #bada55; + } + + .literal rect { + fill: #dae9e5; + } + .placeholder text { fill: #fff; font-weight: bold; diff --git a/src/js/parser/javascript/any_character.js b/src/js/parser/javascript/any_character.js index bf8df15..b0751d1 100644 --- a/src/js/parser/javascript/any_character.js +++ b/src/js/parser/javascript/any_character.js @@ -2,5 +2,11 @@ import _ from 'lodash'; import Base from './base.js'; export default _.extend({}, Base, { - type: 'any_character' + type: 'any_character', + + render() { + this.container.addClass('any-character'); + + this.label = this.render_label(this.container, 'any character'); + } }); diff --git a/src/js/parser/javascript/escape.js b/src/js/parser/javascript/escape.js index d4e0980..97e2314 100644 --- a/src/js/parser/javascript/escape.js +++ b/src/js/parser/javascript/escape.js @@ -2,5 +2,63 @@ import _ from 'lodash'; import Base from './base.js'; export default _.extend({}, Base, { - type: 'escape' + type: 'escape', + + codeMap: { + b: 'word boundary', + B: 'non-word boundary', + d: 'digit', + D: 'non-digit', + f: 'form feed', + n: 'line feed', + r: 'carriage return', + s: 'white space', + S: 'non-white space', + t: 'tab', + v: 'vertical tab', + w: 'word', + W: 'non-word', + 1: 'Back reference (group = 1)', + 2: 'Back reference (group = 2)', + 3: 'Back reference (group = 3)', + 4: 'Back reference (group = 4)', + 5: 'Back reference (group = 5)', + 6: 'Back reference (group = 6)', + 7: 'Back reference (group = 7)', + 8: 'Back reference (group = 8)', + 9: 'Back reference (group = 9)', + 0: (arg) => { + if (arg) { + return 'octal: ' + arg; + } else { + return 'null'; + } + }, + c: (arg) => { + return 'ctrl-' + arg; + }, + x: (arg) => { + return '0x' + arg.toUpperCase(); + }, + u: (arg) => { + return 'U+' + arg.toUpperCase(); + } + }, + + render() { + var code = this.codeMap[this.esc.code.textValue]; + + if (_.isFunction(code)) { + code = code(this.esc.arg.textValue); + } + + this.container.addClass('escape'); + + this.label = this.render_label(this.container, code); + + this.label.select('rect').attr({ + rx: 3, + ry: 3 + }); + } }); diff --git a/src/js/parser/javascript/grammar.peg b/src/js/parser/javascript/grammar.peg index eabde42..1646db6 100644 --- a/src/js/parser/javascript/grammar.peg +++ b/src/js/parser/javascript/grammar.peg @@ -23,65 +23,21 @@ grammar JavascriptRegexp charset <- "[" "^"? ( charset_range / charset_terminal )* "]" charset_range <- charset_terminal "-" charset_terminal charset_terminal <- charset_escape / charset_literal - charset_escape <- ( backspace_esc - / control_esc - / digit_esc - / non_digit_esc - / form_feed_esc - / line_feed_esc - / carriage_return_esc - / white_space_esc - / non_white_space_esc - / tab_esc - / vertical_tab_esc - / word_esc - / non_word_esc - / octal_esc - / hex_esc - / unicode_esc - / null_esc ) + charset_escape <- "\\" esc:( + code:[bdDfnrsStvwW] arg:""? + / code:"0" arg:[0-7]+ + / code:"x" arg:( [0-9a-fA-F] [0-9a-fA-F] ) + / code:"u" arg:( [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] ) ) charset_literal <- [^\\\]] / ( "\\" . ) terminal <- any_character / escape / literal any_character <- "." - escape <- ( word_boundary_esc - / non_word_boundary_esc - / control_esc - / digit_esc - / non_digit_esc - / form_feed_esc - / line_feed_esc - / carriage_return_esc - / white_space_esc - / non_white_space_esc - / tab_esc - / vertical_tab_esc - / word_esc - / non_word_esc - / back_reference - / octal_esc - / hex_esc - / unicode_esc - / null_esc ) + escape <- "\\" esc:( + code:[bBdDfnrsStvwW1-9] arg:""? + / code:"c" arg:. + / code:"0" arg:[0-7]+ + / code:"x" arg:( [0-9a-fA-F] [0-9a-fA-F] ) + / code:"u" arg:( [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] ) + / code:"0" arg:""? ) literal <- ( ""? literal:[^|\\/.\[\(\)?+*$^] ) / ( "\\" literal:. ) - back_reference <- "\\" [1-9] - word_boundary_esc <- "\\b" - non_word_boundary_esc <- "\\B" - backspace_esc <- "\\b" - control_esc <- "\\b" . - digit_esc <- "\\d" - non_digit_esc <- "\\D" - form_feed_esc <- "\\f" - line_feed_esc <- "\\n" - carriage_return_esc <- "\\r" - white_space_esc <- "\\s" - non_white_space_esc <- "\\S" - tab_esc <- "\\t" - vertical_tab_esc <- "\\v" - word_esc <- "\\w" - non_word_esc <- "\\W" - octal_esc <- "\\0" [0-7]+ - hex_esc <- "\\x" [0-9a-fA-F] [0-9a-fA-F] - unicode_esc <- "\\u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] - null_esc <- "\\0" diff --git a/src/js/parser/javascript/literal.js b/src/js/parser/javascript/literal.js index f4540aa..798cd7c 100644 --- a/src/js/parser/javascript/literal.js +++ b/src/js/parser/javascript/literal.js @@ -2,5 +2,16 @@ import _ from 'lodash'; import Base from './base.js'; export default _.extend({}, Base, { - type: 'literal' + type: 'literal', + + render() { + this.container.addClass('literal'); + + this.label = this.render_label(this.container, '"' + this.literal.textValue + '"'); + + this.label.select('rect').attr({ + rx: 3, + ry: 3 + }); + } });