From 2ff8172f33592bb6eccb0e190691292ddb1d5018 Mon Sep 17 00:00:00 2001 From: "Elf M. Sternberg" Date: Tue, 11 Jun 2013 09:05:32 -0700 Subject: [PATCH] Now have a 'when' (when the variable is true in *any* recent context) and 'if' (if the variable is true only in the *most* recent context). Added to the lexer a handler to determine if the block name is valid. This duplicates code from the parser, but it allows the lexer to tell the user when he's being dumb. --- lib/engine.js | 16 ++-- lib/lexer.js | 191 ++++++++++++++++++++++++++-------------------- lib/parser.js | 12 ++- src/engine.coffee | 9 ++- src/lexer.peg | 15 ++++ src/parser.coffee | 10 ++- 6 files changed, 160 insertions(+), 93 deletions(-) diff --git a/lib/engine.js b/lib/engine.js index 9ac237f..ae4f492 100644 --- a/lib/engine.js +++ b/lib/engine.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript 1.6.1 (function() { - var exports, fromFile, fs, parse, render, tumble; + var fromFile, fs, parse, render, tumble; tumble = require('./lexer').parse; @@ -18,15 +18,21 @@ fromFile = function(path, options, callback) { return fs.readFile(path, 'utf8', function(err, str) { - if (err) { - return callback(err); + if (callback) { + if (err) { + return callback(err); + } + console.log(str, options); + return callback(null, render(str, options, callback)); + } + if (err) { + throw err; } - return render(str, options, callback); }); }; fromFile.render = render; - exports = fromFile; + module.exports = fromFile; }).call(this); diff --git a/lib/lexer.js b/lib/lexer.js index 89973a5..c501c82 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -76,37 +76,38 @@ module.exports = (function() { peg$c3 = null, peg$c4 = ":", peg$c5 = "\":\"", - peg$c6 = function(b, n) { return {type: b, name: n }; }, - peg$c7 = "/", - peg$c8 = "\"/\"", - peg$c9 = "tagname", - peg$c10 = /^[a-zA-Z]/, - peg$c11 = "[a-zA-Z]", - peg$c12 = function(t) { return t.join(''); }, - peg$c13 = "", - peg$c14 = /^[a-zA-Z:\/]/, - peg$c15 = "[a-zA-Z:\\/]", - peg$c16 = "{", - peg$c17 = "\"{\"", - peg$c18 = "}", - peg$c19 = "\"}\"", - peg$c20 = "\n", - peg$c21 = "\"\\n\"", - peg$c22 = "\r\n", - peg$c23 = "\"\\r\\n\"", - peg$c24 = "\r", - peg$c25 = "\"\\r\"", - peg$c26 = "\u2028", - peg$c27 = "\"\\u2028\"", - peg$c28 = "\u2029", - peg$c29 = "\"\\u2029\"", - peg$c30 = "any character", - peg$c31 = function(c) {return c}, - peg$c32 = function(bs) { return { unit: 'text', content: bs.join('') } }, - peg$c33 = "variable", - peg$c34 = function(t) { return { unit: 'variable', name: t }; }, - peg$c35 = function(t, ps, n) { return (t.type == n.type) && (t.name == n.name) }, - peg$c36 = function(t, ps, n) { return {unit: 'block', type:t.type, name:t.name, content: ps } }, + peg$c6 = function(b, n) { return is_valid_block_type(b); }, + peg$c7 = "", + peg$c8 = function(b, n) { return {type: b, name: n }; }, + peg$c9 = "/", + peg$c10 = "\"/\"", + peg$c11 = "tagname", + peg$c12 = /^[a-zA-Z]/, + peg$c13 = "[a-zA-Z]", + peg$c14 = function(t) { return t.join(''); }, + peg$c15 = /^[a-zA-Z:\/]/, + peg$c16 = "[a-zA-Z:\\/]", + peg$c17 = "{", + peg$c18 = "\"{\"", + peg$c19 = "}", + peg$c20 = "\"}\"", + peg$c21 = "\n", + peg$c22 = "\"\\n\"", + peg$c23 = "\r\n", + peg$c24 = "\"\\r\\n\"", + peg$c25 = "\r", + peg$c26 = "\"\\r\"", + peg$c27 = "\u2028", + peg$c28 = "\"\\u2028\"", + peg$c29 = "\u2029", + peg$c30 = "\"\\u2029\"", + peg$c31 = "any character", + peg$c32 = function(c) {return c}, + peg$c33 = function(bs) { return { unit: 'text', content: bs.join('') } }, + peg$c34 = "variable", + peg$c35 = function(t) { return { unit: 'variable', name: t }; }, + peg$c36 = function(t, ps, n) { return (t.type == n.type) && (t.name == n.name) }, + peg$c37 = function(t, ps, n) { return {unit: 'block', type:t.type, name:t.name, content: ps } }, peg$currPos = 0, peg$reportedPos = 0, @@ -239,7 +240,7 @@ module.exports = (function() { } function peg$parsetag_start() { - var s0, s1, s2, s3, s4, s5; + var s0, s1, s2, s3, s4, s5, s6; peg$silentFails++; s0 = peg$currPos; @@ -259,13 +260,25 @@ module.exports = (function() { if (s4 !== null) { s5 = peg$parserd(); if (s5 !== null) { - peg$reportedPos = s0; - s1 = peg$c6(s2,s4); - if (s1 === null) { - peg$currPos = s0; - s0 = s1; + peg$reportedPos = peg$currPos; + s6 = peg$c6(s2,s4); + if (s6) { + s6 = peg$c7; } else { - s0 = s1; + s6 = peg$c3; + } + if (s6 !== null) { + peg$reportedPos = s0; + s1 = peg$c8(s2,s4); + if (s1 === null) { + peg$currPos = s0; + s0 = s1; + } else { + s0 = s1; + } + } else { + peg$currPos = s0; + s0 = peg$c3; } } else { peg$currPos = s0; @@ -303,11 +316,11 @@ module.exports = (function() { s1 = peg$parseld(); if (s1 !== null) { if (input.charCodeAt(peg$currPos) === 47) { - s2 = peg$c7; + s2 = peg$c9; peg$currPos++; } else { s2 = null; - if (peg$silentFails === 0) { peg$fail(peg$c8); } + if (peg$silentFails === 0) { peg$fail(peg$c10); } } if (s2 !== null) { s3 = peg$parsetagname(); @@ -325,7 +338,7 @@ module.exports = (function() { s6 = peg$parserd(); if (s6 !== null) { peg$reportedPos = s0; - s1 = peg$c6(s3,s5); + s1 = peg$c8(s3,s5); if (s1 === null) { peg$currPos = s0; s0 = s1; @@ -366,22 +379,22 @@ module.exports = (function() { peg$silentFails++; s0 = peg$currPos; s1 = []; - if (peg$c10.test(input.charAt(peg$currPos))) { + if (peg$c12.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = null; - if (peg$silentFails === 0) { peg$fail(peg$c11); } + if (peg$silentFails === 0) { peg$fail(peg$c13); } } if (s2 !== null) { while (s2 !== null) { s1.push(s2); - if (peg$c10.test(input.charAt(peg$currPos))) { + if (peg$c12.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = null; - if (peg$silentFails === 0) { peg$fail(peg$c11); } + if (peg$silentFails === 0) { peg$fail(peg$c13); } } } } else { @@ -389,7 +402,7 @@ module.exports = (function() { } if (s1 !== null) { peg$reportedPos = s0; - s1 = peg$c12(s1); + s1 = peg$c14(s1); } if (s1 === null) { peg$currPos = s0; @@ -400,7 +413,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === null) { s1 = null; - if (peg$silentFails === 0) { peg$fail(peg$c9); } + if (peg$silentFails === 0) { peg$fail(peg$c11); } } return s0; @@ -419,7 +432,7 @@ module.exports = (function() { s5 = peg$parserd(); peg$silentFails--; if (s5 === null) { - s4 = peg$c13; + s4 = peg$c7; } else { peg$currPos = s4; s4 = peg$c3; @@ -430,18 +443,18 @@ module.exports = (function() { s6 = peg$parseeol(); peg$silentFails--; if (s6 === null) { - s5 = peg$c13; + s5 = peg$c7; } else { peg$currPos = s5; s5 = peg$c3; } if (s5 !== null) { - if (peg$c14.test(input.charAt(peg$currPos))) { + if (peg$c15.test(input.charAt(peg$currPos))) { s6 = input.charAt(peg$currPos); peg$currPos++; } else { s6 = null; - if (peg$silentFails === 0) { peg$fail(peg$c15); } + if (peg$silentFails === 0) { peg$fail(peg$c16); } } if (s6 !== null) { s4 = [s4, s5, s6]; @@ -467,7 +480,7 @@ module.exports = (function() { s5 = peg$parserd(); peg$silentFails--; if (s5 === null) { - s4 = peg$c13; + s4 = peg$c7; } else { peg$currPos = s4; s4 = peg$c3; @@ -478,18 +491,18 @@ module.exports = (function() { s6 = peg$parseeol(); peg$silentFails--; if (s6 === null) { - s5 = peg$c13; + s5 = peg$c7; } else { peg$currPos = s5; s5 = peg$c3; } if (s5 !== null) { - if (peg$c14.test(input.charAt(peg$currPos))) { + if (peg$c15.test(input.charAt(peg$currPos))) { s6 = input.charAt(peg$currPos); peg$currPos++; } else { s6 = null; - if (peg$silentFails === 0) { peg$fail(peg$c15); } + if (peg$silentFails === 0) { peg$fail(peg$c16); } } if (s6 !== null) { s4 = [s4, s5, s6]; @@ -535,11 +548,11 @@ module.exports = (function() { var s0; if (input.charCodeAt(peg$currPos) === 123) { - s0 = peg$c16; + s0 = peg$c17; peg$currPos++; } else { s0 = null; - if (peg$silentFails === 0) { peg$fail(peg$c17); } + if (peg$silentFails === 0) { peg$fail(peg$c18); } } return s0; @@ -549,11 +562,11 @@ module.exports = (function() { var s0; if (input.charCodeAt(peg$currPos) === 125) { - s0 = peg$c18; + s0 = peg$c19; peg$currPos++; } else { s0 = null; - if (peg$silentFails === 0) { peg$fail(peg$c19); } + if (peg$silentFails === 0) { peg$fail(peg$c20); } } return s0; @@ -563,43 +576,43 @@ module.exports = (function() { var s0; if (input.charCodeAt(peg$currPos) === 10) { - s0 = peg$c20; + s0 = peg$c21; peg$currPos++; } else { s0 = null; - if (peg$silentFails === 0) { peg$fail(peg$c21); } + if (peg$silentFails === 0) { peg$fail(peg$c22); } } if (s0 === null) { - if (input.substr(peg$currPos, 2) === peg$c22) { - s0 = peg$c22; + if (input.substr(peg$currPos, 2) === peg$c23) { + s0 = peg$c23; peg$currPos += 2; } else { s0 = null; - if (peg$silentFails === 0) { peg$fail(peg$c23); } + if (peg$silentFails === 0) { peg$fail(peg$c24); } } if (s0 === null) { if (input.charCodeAt(peg$currPos) === 13) { - s0 = peg$c24; + s0 = peg$c25; peg$currPos++; } else { s0 = null; - if (peg$silentFails === 0) { peg$fail(peg$c25); } + if (peg$silentFails === 0) { peg$fail(peg$c26); } } if (s0 === null) { if (input.charCodeAt(peg$currPos) === 8232) { - s0 = peg$c26; + s0 = peg$c27; peg$currPos++; } else { s0 = null; - if (peg$silentFails === 0) { peg$fail(peg$c27); } + if (peg$silentFails === 0) { peg$fail(peg$c28); } } if (s0 === null) { if (input.charCodeAt(peg$currPos) === 8233) { - s0 = peg$c28; + s0 = peg$c29; peg$currPos++; } else { s0 = null; - if (peg$silentFails === 0) { peg$fail(peg$c29); } + if (peg$silentFails === 0) { peg$fail(peg$c30); } } } } @@ -620,7 +633,7 @@ module.exports = (function() { s4 = peg$parsetag(); peg$silentFails--; if (s4 === null) { - s3 = peg$c13; + s3 = peg$c7; } else { peg$currPos = s3; s3 = peg$c3; @@ -631,11 +644,11 @@ module.exports = (function() { peg$currPos++; } else { s4 = null; - if (peg$silentFails === 0) { peg$fail(peg$c30); } + if (peg$silentFails === 0) { peg$fail(peg$c31); } } if (s4 !== null) { peg$reportedPos = s2; - s3 = peg$c31(s4); + s3 = peg$c32(s4); if (s3 === null) { peg$currPos = s2; s2 = s3; @@ -659,7 +672,7 @@ module.exports = (function() { s4 = peg$parsetag(); peg$silentFails--; if (s4 === null) { - s3 = peg$c13; + s3 = peg$c7; } else { peg$currPos = s3; s3 = peg$c3; @@ -670,11 +683,11 @@ module.exports = (function() { peg$currPos++; } else { s4 = null; - if (peg$silentFails === 0) { peg$fail(peg$c30); } + if (peg$silentFails === 0) { peg$fail(peg$c31); } } if (s4 !== null) { peg$reportedPos = s2; - s3 = peg$c31(s4); + s3 = peg$c32(s4); if (s3 === null) { peg$currPos = s2; s2 = s3; @@ -695,7 +708,7 @@ module.exports = (function() { } if (s1 !== null) { peg$reportedPos = s0; - s1 = peg$c32(s1); + s1 = peg$c33(s1); } if (s1 === null) { peg$currPos = s0; @@ -719,7 +732,7 @@ module.exports = (function() { s3 = peg$parserd(); if (s3 !== null) { peg$reportedPos = s0; - s1 = peg$c34(s2); + s1 = peg$c35(s2); if (s1 === null) { peg$currPos = s0; s0 = s1; @@ -741,7 +754,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === null) { s1 = null; - if (peg$silentFails === 0) { peg$fail(peg$c33); } + if (peg$silentFails === 0) { peg$fail(peg$c34); } } return s0; @@ -763,15 +776,15 @@ module.exports = (function() { s3 = peg$parsetag_end(); if (s3 !== null) { peg$reportedPos = peg$currPos; - s4 = peg$c35(s1,s2,s3); + s4 = peg$c36(s1,s2,s3); if (s4) { - s4 = peg$c13; + s4 = peg$c7; } else { s4 = peg$c3; } if (s4 !== null) { peg$reportedPos = s0; - s1 = peg$c36(s1,s2,s3); + s1 = peg$c37(s1,s2,s3); if (s1 === null) { peg$currPos = s0; s0 = s1; @@ -798,6 +811,20 @@ module.exports = (function() { return s0; } + + var _VALID_BLOCK_TYPES = ['if', 'when', 'template', 'many', 'each', 'block']; + var _VBT_LENGTH = _VALID_BLOCK_TYPES.length; + + function is_valid_block_type(b) { + for(i = 0; i < _VBT_LENGTH; i++) { + if (_VALID_BLOCK_TYPES[i] == b) { + return true; + } + } + return false; + } + + peg$result = peg$startRuleFunction(); if (peg$result !== null && peg$currPos === input.length) { diff --git a/lib/parser.js b/lib/parser.js index a5f8b34..df06619 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -64,7 +64,7 @@ return r; }; - Contexter.prototype["if"] = function(name, cb) { + Contexter.prototype.when = function(name, cb) { var p; p = this.has_any_one(name); if (p) { @@ -74,6 +74,16 @@ } }; + Contexter.prototype["if"] = function(name, cb) { + var p; + p = this.has(name); + if (p) { + return cb(this); + } else { + return ''; + } + }; + Contexter.prototype.block = function(name, cb) { var p; p = this.has_any_one(name); diff --git a/src/engine.coffee b/src/engine.coffee index 67d8f8c..21aad69 100644 --- a/src/engine.coffee +++ b/src/engine.coffee @@ -10,9 +10,12 @@ render = (str, options, callback) -> fromFile = (path, options, callback) -> fs.readFile path, 'utf8', (err, str) -> - return callback(err) if err - render(str, options, callback) + if callback + return callback(err) if err + console.log(str, options); + return callback(null, render(str, options, callback)) + throw err if err fromFile.render = render -exports = fromFile +module.exports = fromFile diff --git a/src/lexer.peg b/src/lexer.peg index 17d5423..35586d3 100644 --- a/src/lexer.peg +++ b/src/lexer.peg @@ -1,4 +1,18 @@ // -*- mode: javascript -*- +{ + var _VALID_BLOCK_TYPES = ['if', 'when', 'template', 'many', 'each', 'block']; + var _VBT_LENGTH = _VALID_BLOCK_TYPES.length; + + function is_valid_block_type(b) { + for(i = 0; i < _VBT_LENGTH; i++) { + if (_VALID_BLOCK_TYPES[i] == b) { + return true; + } + } + return false; + } +} + document = ps:part* @@ -9,6 +23,7 @@ part tag_start "tag_start" = ld b:tagname ":" n:tagname rd + &{ return is_valid_block_type(b); } { return {type: b, name: n }; } tag_end diff --git a/src/parser.coffee b/src/parser.coffee index a6a3429..ad2a645 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -39,12 +39,18 @@ class Contexter @depth-- r - if: (name, cb) -> - # Execute and return this specifiecd block if and only if the + when: (name, cb) -> + # Execute and return this specified block if and only if the # requested context is valid. p = @has_any_one(name) if p then cb(@) else '' + if: (name, cb) -> + # Execute and return this specifiecd block if and only if the + # requested context is valid AND current + p = @has(name) + if p then cb(@) else '' + block: (name, cb) -> # Execute and return this specified block if and only if the # requested context is valid and entrant.