diff --git a/examples/unfinished/jsparse-demo/jsparse-demo.css b/examples/unfinished/jsparse-demo/jsparse-demo.css
index bea973c397..f0c71202e7 100644
--- a/examples/unfinished/jsparse-demo/jsparse-demo.css
+++ b/examples/unfinished/jsparse-demo/jsparse-demo.css
@@ -25,38 +25,82 @@ html, body { height: 100%; }
bottom: 0;
}
-#inputarea textarea {
+#inputarea {
border: 0;
border-right: 1px solid #555;
position: absolute;
height: 100%;
left: 0;
right: 50%;
+}
+
+#inputarea textarea {
+ position: absolute;
+ width: 100%;
+ height: 100%;
font-family: monospace;
font-size: 100%;
+ border: 0;
+}
+
+#outputoptions {
+ position: absolute;
+ left: 50%;
+ right: 0;
+ overflow: visible;
+ bottom: 0;
+ height: 29px;
+ border-top: 1px solid #555;
+
+ background: #ccc;
}
#output {
position: absolute;
- height: 100%;
left: 50%;
right: 0;
overflow: auto;
+ top: 0;
+ bottom: 30px;
font-family: monospace;
}
+#outputoptions .output-type {
+ text-decoration: none;
+ font-family: sans-serif;
+ font-size: 14px;
+ display: inline-block;
+ background: #e2e2e2;
+ vertical-align: top;
+ position: relative;
+ top: -1px;
+ padding: 3px 8px;
+ margin-left: 6px;
+ border-bottom-left-radius: 5px;
+ border-bottom-right-radius: 5px;
+ border: 1px solid #777;
+ border-top: 1px solid #555;
+ cursor: pointer;
+}
+
+#outputoptions .output-type.selected {
+ font-weight: bold;
+ background: #fff;
+ border-top: 1px solid #fff;
+}
+
#inputarea textarea, #output {
line-height: 130%;
}
-.lex { border: 1px solid #333; }
+.lex { border: 1px solid #333; cursor: pointer; }
.lex_keyword { background: #0f0; }
.lex_identifier { background: #ff0; }
.lex_punctuation { background: #0ff; }
.lex_error { background: #f00; }
-.lex_whitespace { background: #fcc; }
+.lex_whitespace, .lex_newline, .lex_eof { background: #fcc; }
.lex_comment { background: #ccc; }
.lex_regex { background: #f0f; }
diff --git a/examples/unfinished/jsparse-demo/jsparse-demo.html b/examples/unfinished/jsparse-demo/jsparse-demo.html
index fd7986ba16..ab3d3b36f6 100644
--- a/examples/unfinished/jsparse-demo/jsparse-demo.html
+++ b/examples/unfinished/jsparse-demo/jsparse-demo.html
@@ -22,6 +22,11 @@ whitespace is significant here; browser swallows initial
}}
+
+ {{#each outputTypes}}
+ {{name}}
+ {{/each}}
+
{{output}}
diff --git a/examples/unfinished/jsparse-demo/jsparse-demo.js b/examples/unfinished/jsparse-demo/jsparse-demo.js
index 03920abd4e..a8a063c187 100644
--- a/examples/unfinished/jsparse-demo/jsparse-demo.js
+++ b/examples/unfinished/jsparse-demo/jsparse-demo.js
@@ -4,6 +4,8 @@ if (Meteor.is_client) {
Meteor.startup(function () {
if (! Session.get("input"))
Session.set("input", "var x = 3");
+ if (! Session.get("output-type"))
+ Session.set("output-type", "parse");
});
Template.page.input = function () {
@@ -13,92 +15,103 @@ if (Meteor.is_client) {
Template.page.output = function () {
var input = Session.get("input") || "";
- // LEXER
- /*
- if (! input)
- return "";
-
- var L = new Lexer(input);
- var html = "";
- while (L.next() !== 'EOF') {
- if (L.type === "NEWLINE") {
- html += '
';
- } else {
- var text = Handlebars._escape(L.text || ' ');
- text = text.replace(/(?!.)\s/g, '
'); // for multiline comments
- text = text.replace(/\s/g, ' ');
- html += '' +
- text + '';
- if (L.type === "ERROR")
- break;
- }
- }*/
-
- // PARSER
- var html;
- var tree = null;
- var parser = new JSParser(input);
- try {
- tree = parser.getSyntaxTree();
- } catch (parseError) {
- var errorLexeme = parser.lexer.lastLexeme;
-
- html = Handlebars._escape(
- input.substring(0, errorLexeme.startPos()));
- html += Spark.setDataContext(
- errorLexeme,
- '' +
- Handlebars._escape(errorLexeme.text() || '') +
- '');
- html = html.replace(/(?!.)\s/g, '
');
- html += '' +
- Handlebars._escape(parseError.toString()) + '
';
- }
- if (tree) {
- var curPos = 0;
- var unclosedInfos = [];
- var toHtml = function (obj) {
- if (obj instanceof ParseNode) {
- var head = obj.name || '';
- var children = obj.children;
- var info = { startPos: curPos };
- var isStatement = (head.indexOf('Stmnt') >= 0);
- var html = Spark.setDataContext(
- info,
- '' + Handlebars._escape(head) + '
' +
- _.map(children, toHtml).join('') + '
');
- unclosedInfos.push(info);
- return html;
- } else if (obj.text) {
- // token
- _.each(unclosedInfos, function (info) {
- info.endPos = curPos;
- });
- curPos = obj.endPos();
- unclosedInfos.length = 0;
- var text = obj.text();
- // insert zero-width spaces to allow wrapping
- text = text.replace(/.{20}/g, "$&\n");
- text = Handlebars._escape(text);
- text = text.replace(/\n/g, '');
- return Spark.setDataContext(
- obj,
- '' + text + '
');
+ var outputType = Session.get("output-type");
+
+ if (outputType === "lex") {
+ // LEXER
+
+ var lexer = new JSLexer(input);
+ var html = "";
+ var L;
+ do {
+ L = lexer.next();
+ var content;
+ if (L.type() === "NEWLINE") {
+ content = '
';
+ } else if (L.type() === "EOF") {
+ content = Handlebars._escape("");
} else {
- // other?
- return '' +
- Handlebars._escape(JSON.stringify(obj)) + '
';
+ content = Handlebars._escape(L.text() || ' ');
+ content = content.replace(/(?!.)\s/g, '
'); // for multiline comments
+ content = content.replace(/\s/g, ' ');
}
- };
- html = toHtml(tree);
- curPos = parser.lexer.pos;
- _.each(unclosedInfos, function (info) {
- info.endPos = curPos;
- });
- }
+ html += Spark.setDataContext(
+ L,
+ '' +
+ content + '');
+ } while (! L.isError() && ! L.isEOF());
+ return new Handlebars.SafeString(html);
+
+ } else if (outputType === "parse") {
+
+ // PARSER
+ var html;
+ var tree = null;
+ var parser = new JSParser(input);
+ try {
+ tree = parser.getSyntaxTree();
+ } catch (parseError) {
+ var errorLexeme = parser.lexer.lastLexeme;
+
+ html = Handlebars._escape(
+ input.substring(0, errorLexeme.startPos()));
+ html += Spark.setDataContext(
+ errorLexeme,
+ '' +
+ Handlebars._escape(errorLexeme.text() || '') +
+ '');
+ html = html.replace(/(?!.)\s/g, '
');
+ html += '' +
+ Handlebars._escape(parseError.toString()) + '
';
+ }
+ if (tree) {
+ var curPos = 0;
+ var unclosedInfos = [];
+ var toHtml = function (obj) {
+ if (obj instanceof ParseNode) {
+ var head = obj.name || '';
+ var children = obj.children;
+ var info = { startPos: curPos };
+ var isStatement = (head.indexOf('Stmnt') >= 0);
+ var html = Spark.setDataContext(
+ info,
+ '' + Handlebars._escape(head) + '
' +
+ _.map(children, toHtml).join('') + '
');
+ unclosedInfos.push(info);
+ return html;
+ } else if (obj.text) {
+ // token
+ _.each(unclosedInfos, function (info) {
+ info.endPos = curPos;
+ });
+ curPos = obj.endPos();
+ unclosedInfos.length = 0;
+ var text = obj.text();
+ // insert zero-width spaces to allow wrapping
+ text = text.replace(/.{20}/g, "$&\n");
+ text = Handlebars._escape(text);
+ text = text.replace(/\n/g, '');
+ return Spark.setDataContext(
+ obj,
+ '' + text + '
');
+ } else {
+ // other?
+ return '' +
+ Handlebars._escape(JSON.stringify(obj)) + '
';
+ }
+ };
+ html = toHtml(tree);
+ curPos = parser.lexer.pos;
+ _.each(unclosedInfos, function (info) {
+ info.endPos = curPos;
+ });
+ }
- return new Handlebars.SafeString(html);
+ return new Handlebars.SafeString(html);
+ }
+ else return ''; // unknown output tab?
};
Template.page.events({
@@ -125,9 +138,25 @@ if (Meteor.is_client) {
'click .parseerror': function (event) {
selectInputText(this.startPos(), this.endPos());
return false;
- }
+ },
+ 'click .output-type': function (event) {
+ Session.set("output-type", this.value);
+ },
+ 'click .lex': function (event) {
+ selectInputText(this.startPos(), this.endPos());
+ return false;
+ },
});
+ Template.page.outputTypes = [
+ {name: "Lex", value: "lex"},
+ {name: "Parse", value: "parse"}
+ ];
+
+ Template.page.is_outputtype_selected = function (which) {
+ return Session.equals("output-type", which) ? "selected" : "";
+ };
+
var selectTextInArea = function (e, start, end){
e.focus();
if (e.setSelectionRange) {