%x mu emu com raw %{ function strip(start, end) { return yytext = yytext.substr(start, yyleng-end); } %} LEFT_STRIP "~" RIGHT_STRIP "~" LOOKAHEAD [=~}\s\/.)|] LITERAL_LOOKAHEAD [~}\s)] /* ID is the inverse of control characters. Control characters ranges: [\s] Whitespace [!"#%-,\./] !, ", #, %, &, ', (, ), *, +, ,, ., /, Exceptions in range: $, - [;->@] ;, <, =, >, @, Exceptions in range: :, ? [\[-\^`] [, \, ], ^, `, Exceptions in range: _ [\{-~] {, |, }, ~ */ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD} %% [^\x00]*?/("{{") { if(yytext.slice(-2) === "\\\\") { strip(0,1); this.begin("mu"); } else if(yytext.slice(-1) === "\\") { strip(0,1); this.begin("emu"); } else { this.begin("mu"); } if(yytext) return 'CONTENT'; } [^\x00]+ return 'CONTENT'; // marks CONTENT up to the next mustache or escaped mustache [^\x00]{2,}?/("{{"|"\\{{"|"\\\\{{"|<>) { this.popState(); return 'CONTENT'; } // nested raw block will create stacked 'raw' condition "{{{{"/[^/] this.begin('raw'); return 'CONTENT'; "{{{{/"[^\s!"#%-,\.\/;->@\[-\^`\{-~]+/[=}\s\/.]"}}}}" { this.popState(); // Should be using `this.topState()` below, but it currently // returns the second top instead of the first top. Opened an // issue about it at https://github.com/zaach/jison/issues/291 if (this.conditionStack[this.conditionStack.length-1] === 'raw') { return 'CONTENT'; } else { yytext = yytext.substr(5, yyleng-9); return 'END_RAW_BLOCK'; } } [^\x00]*?/("{{{{") { return 'CONTENT'; } [\s\S]*?"--"{RIGHT_STRIP}?"}}" { this.popState(); return 'COMMENT'; } "(" return 'OPEN_SEXPR'; ")" return 'CLOSE_SEXPR'; "{{{{" { return 'OPEN_RAW_BLOCK'; } "}}}}" { this.popState(); this.begin('raw'); return 'CLOSE_RAW_BLOCK'; } "{{"{LEFT_STRIP}?">" return 'OPEN_PARTIAL'; "{{"{LEFT_STRIP}?"#>" return 'OPEN_PARTIAL_BLOCK'; "{{"{LEFT_STRIP}?"#""*"? return 'OPEN_BLOCK'; "{{"{LEFT_STRIP}?"/" return 'OPEN_ENDBLOCK'; "{{"{LEFT_STRIP}?"^"\s*{RIGHT_STRIP}?"}}" this.popState(); return 'INVERSE'; "{{"{LEFT_STRIP}?\s*"else"\s*{RIGHT_STRIP}?"}}" this.popState(); return 'INVERSE'; "{{"{LEFT_STRIP}?"^" return 'OPEN_INVERSE'; "{{"{LEFT_STRIP}?\s*"else" return 'OPEN_INVERSE_CHAIN'; "{{"{LEFT_STRIP}?"{" return 'OPEN_UNESCAPED'; "{{"{LEFT_STRIP}?"&" return 'OPEN'; "{{"{LEFT_STRIP}?"!--" { this.unput(yytext); this.popState(); this.begin('com'); } "{{"{LEFT_STRIP}?"!"[\s\S]*?"}}" { this.popState(); return 'COMMENT'; } "{{"{LEFT_STRIP}?"*"? return 'OPEN'; "=" return 'EQUALS'; ".." return 'ID'; "."/{LOOKAHEAD} return 'ID'; [\/.] return 'SEP'; \s+ // ignore whitespace "}"{RIGHT_STRIP}?"}}" this.popState(); return 'CLOSE_UNESCAPED'; {RIGHT_STRIP}?"}}" this.popState(); return 'CLOSE'; '"'("\\"["]|[^"])*'"' yytext = strip(1,2).replace(/\\"/g,'"'); return 'STRING'; "'"("\\"[']|[^'])*"'" yytext = strip(1,2).replace(/\\'/g,"'"); return 'STRING'; "@" return 'DATA'; "true"/{LITERAL_LOOKAHEAD} return 'BOOLEAN'; "false"/{LITERAL_LOOKAHEAD} return 'BOOLEAN'; "undefined"/{LITERAL_LOOKAHEAD} return 'UNDEFINED'; "null"/{LITERAL_LOOKAHEAD} return 'NULL'; \-?[0-9]+(?:\.[0-9]+)?/{LITERAL_LOOKAHEAD} return 'NUMBER'; "as"\s+"|" return 'OPEN_BLOCK_PARAMS'; "|" return 'CLOSE_BLOCK_PARAMS'; {ID} return 'ID'; '['('\\]'|[^\]])*']' yytext = yytext.replace(/\\([\\\]])/g,'$1'); return 'ID'; . return 'INVALID'; <> return 'EOF';