Skip to content

Commit

Permalink
bsjs: good looking "new" expr implementation
Browse files Browse the repository at this point in the history
* grammar: better error reporting
  • Loading branch information
indutny committed May 26, 2012
1 parent 36ff541 commit 94084ba
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 22 deletions.
5 changes: 3 additions & 2 deletions lib/ometajs/compiler/ir.js
Expand Up @@ -167,9 +167,10 @@ IR.prototype.render = function render() {
parent = ast[2]; parent = ast[2];


ast[3].forEach(function(rule) { ast[3].forEach(function(rule) {
var name = rule[1] || '';
buf.push( buf.push(
ast[1], '.prototype[', JSON.stringify(rule[1]), ']', ast[1], '.prototype[', JSON.stringify(name), ']',
' = function $' + rule[1].replace(/[^\w]+/g, '') + '() {' ' = function $' + name.replace(/[^\w]+/g, '') + '() {'
); );


args(rule[2]); args(rule[2]);
Expand Down
17 changes: 12 additions & 5 deletions lib/ometajs/core/grammar.js
Expand Up @@ -11,7 +11,8 @@ function AbstractGrammar(source) {
this._name = 'AbstractGrammar'; this._name = 'AbstractGrammar';


this._errorRule = ''; this._errorRule = '';
this._errorOffset = ''; this._errorHistory = '';
this._errorOffset = -1;
this._errorSource = source; this._errorSource = source;
} }
util.inherits(AbstractGrammar, ometajs.core.AbstractParser); util.inherits(AbstractGrammar, ometajs.core.AbstractParser);
Expand Down Expand Up @@ -51,10 +52,14 @@ AbstractGrammar.matchAll = function matchAll(source, rule, args, errback) {
current = 0, current = 0,
error = grmr._errorStack || new Error(); error = grmr._errorStack || new Error();


if (Array.isArray(source)) { if (Array.isArray(grmr._errorSource)) {
// TODO: Implement me! var strArray = util.inspect(grmr._errorSource, false, 4);
error.message = grmr._errorRule + ' rule failed at: ' +
strArray + ':' +
grmr._errorOffset;
} else { } else {
source.split(/\n/g).some(function (source, i) { (grmr._errorSource || '').toString().split(/\n/g)
.some(function (source, i) {
if (grmr._errorOffset > (current + source.length + 1)) { if (grmr._errorOffset > (current + source.length + 1)) {
current += source.length + 1; current += source.length + 1;
return false; return false;
Expand Down Expand Up @@ -91,8 +96,10 @@ AbstractGrammar.matchAll = function matchAll(source, rule, args, errback) {
// Internal method for tracking errors // Internal method for tracking errors
// //
AbstractGrammar.prototype._lastError = function _lastError(rule) { AbstractGrammar.prototype._lastError = function _lastError(rule) {
if (this._errorOffset <= this._offset) { if (this._errorHistory <= this._history &&
this._errorOffset <= this._offset) {
this._errorRule = rule; this._errorRule = rule;
this._errorHistory = this._history;
this._errorOffset = this._offset; this._errorOffset = this._offset;
this._errorSource = this._source; this._errorSource = this._source;
} }
Expand Down
45 changes: 38 additions & 7 deletions lib/ometajs/grammars/bsjs.js
Expand Up @@ -500,24 +500,45 @@ BSJSParser.prototype["primExpr"] = function $primExpr() {
return this._atomic(function() { return this._atomic(function() {
var p; var p;
return this._rule("primExpr", false, [], null, this["primExpr"]) && (p = this._getIntermediate(), true) && (this._atomic(function() { return this._rule("primExpr", false, [], null, this["primExpr"]) && (p = this._getIntermediate(), true) && (this._atomic(function() {
var i; var as;
return this._rule("token", true, [ "[" ], null, this["token"]) && this._rule("expr", false, [], null, this["expr"]) && (i = this._getIntermediate(), true) && this._rule("token", true, [ "]" ], null, this["token"]) && this._exec([ "getp", i, p ]); return this._rule("token", true, [ "(" ], null, this["token"]) && this._rule("listOf", false, [ "asgnExpr", "," ], null, this["listOf"]) && (as = this._getIntermediate(), true) && this._rule("token", true, [ ")" ], null, this["token"]) && this._exec([ "call", p ].concat(as));
}) || this._atomic(function() { }) || this._atomic(function() {
var m, as; var m, as;
return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("token", true, [ "name" ], null, this["token"]) && (m = this._getIntermediate(), true) && this._rule("token", true, [ "(" ], null, this["token"]) && this._rule("listOf", false, [ "asgnExpr", "," ], null, this["listOf"]) && (as = this._getIntermediate(), true) && this._rule("token", true, [ ")" ], null, this["token"]) && this._exec([ "send", m, p ].concat(as)); return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("token", true, [ "name" ], null, this["token"]) && (m = this._getIntermediate(), true) && this._rule("token", true, [ "(" ], null, this["token"]) && this._rule("listOf", false, [ "asgnExpr", "," ], null, this["listOf"]) && (as = this._getIntermediate(), true) && this._rule("token", true, [ ")" ], null, this["token"]) && this._exec([ "send", m, p ].concat(as));
}) || this._atomic(function() { }) || this._atomic(function() {
var m, as; var m, as;
return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("spaces", false, [], null, this["spaces"]) && this._rule("iName", true, [], null, this["iName"]) && (m = this._getIntermediate(), true) && this._rule("token", true, [ "(" ], null, this["token"]) && this._rule("listOf", false, [ "asgnExpr", "," ], null, this["listOf"]) && (as = this._getIntermediate(), true) && this._rule("token", true, [ ")" ], null, this["token"]) && this._rule("isKeyword", false, [ m ], null, this["isKeyword"]) && this._exec([ "send", m, p ].concat(as)); return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("spaces", false, [], null, this["spaces"]) && this._rule("iName", true, [], null, this["iName"]) && (m = this._getIntermediate(), true) && this._rule("token", true, [ "(" ], null, this["token"]) && this._rule("listOf", false, [ "asgnExpr", "," ], null, this["listOf"]) && (as = this._getIntermediate(), true) && this._rule("token", true, [ ")" ], null, this["token"]) && this._rule("isKeyword", false, [ m ], null, this["isKeyword"]) && this._exec([ "send", m, p ].concat(as));
}));
}) || this._atomic(function() {
return this._rule("memberExpr", false, [], null, this["memberExpr"]);
});
};

BSJSParser.prototype["memberExpr"] = function $memberExpr() {
return this._atomic(function() {
var p;
return this._rule("memberExpr", false, [], null, this["memberExpr"]) && (p = this._getIntermediate(), true) && (this._atomic(function() {
var i;
return this._rule("token", true, [ "[" ], null, this["token"]) && this._rule("expr", false, [], null, this["expr"]) && (i = this._getIntermediate(), true) && this._rule("token", true, [ "]" ], null, this["token"]) && this._exec([ "getp", i, p ]);
}) || this._atomic(function() { }) || this._atomic(function() {
var f; var f;
return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("token", true, [ "name" ], null, this["token"]) && (f = this._getIntermediate(), true) && this._exec([ "getp", [ "string", f ], p ]); return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("token", true, [ "name" ], null, this["token"]) && (f = this._getIntermediate(), true) && this._exec([ "getp", [ "string", f ], p ]);
}) || this._atomic(function() { }) || this._atomic(function() {
var f; var f;
return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("spaces", false, [], null, this["spaces"]) && this._rule("iName", true, [], null, this["iName"]) && (f = this._getIntermediate(), true) && this._rule("isKeyword", false, [ f ], null, this["isKeyword"]) && this._exec([ "getp", [ "string", f ], p ]); return this._rule("token", true, [ "." ], null, this["token"]) && this._rule("spaces", false, [], null, this["spaces"]) && this._rule("iName", true, [], null, this["iName"]) && (f = this._getIntermediate(), true) && this._rule("isKeyword", false, [ f ], null, this["isKeyword"]) && this._exec([ "getp", [ "string", f ], p ]);
}) || this._atomic(function() {
var as;
return this._rule("token", true, [ "(" ], null, this["token"]) && this._rule("listOf", false, [ "asgnExpr", "," ], null, this["listOf"]) && (as = this._getIntermediate(), true) && this._rule("token", true, [ ")" ], null, this["token"]) && this._exec([ "call", p ].concat(as));
})); }));
}) || this._atomic(function() {
return this._rule("newExpr", false, [], null, this["newExpr"]);
});
};

BSJSParser.prototype["newExpr"] = function $newExpr() {
return this._atomic(function() {
var n, as;
return this._rule("token", true, [ "new" ], null, this["token"]) && this._rule("memberExpr", false, [], null, this["memberExpr"]) && (n = this._getIntermediate(), true) && this._rule("token", true, [ "(" ], null, this["token"]) && this._rule("listOf", false, [ "asgnExpr", "," ], null, this["listOf"]) && (as = this._getIntermediate(), true) && this._rule("token", true, [ ")" ], null, this["token"]) && this._exec([ "new", n ].concat(as));
}) || this._atomic(function() {
var n;
return this._rule("token", true, [ "new" ], null, this["token"]) && this._rule("memberExpr", false, [], null, this["memberExpr"]) && (n = this._getIntermediate(), true) && this._exec([ "new", n ]);
}) || this._atomic(function() { }) || this._atomic(function() {
return this._rule("primExprHd", false, [], null, this["primExprHd"]); return this._rule("primExprHd", false, [], null, this["primExprHd"]);
}); });
Expand Down Expand Up @@ -1037,7 +1058,12 @@ BSJSIdentity.prototype["send"] = function $send() {


BSJSIdentity.prototype["new"] = function $new() { BSJSIdentity.prototype["new"] = function $new() {
var cls, args; var cls, args;
return this._skip() && (cls = this._getIntermediate(), true) && this._any(function() { return (this._atomic(function() {
var str;
return this._skip() && (str = this._getIntermediate(), true) && typeof str === "string" && this._exec(str);
}) || this._atomic(function() {
return this._rule("trans", false, [], null, this["trans"]);
})) && (cls = this._getIntermediate(), true) && this._any(function() {
return this._rule("trans", false, [], null, this["trans"]); return this._rule("trans", false, [], null, this["trans"]);
}) && (args = this._getIntermediate(), true) && this._exec([ "new", cls ].concat(args)); }) && (args = this._getIntermediate(), true) && this._exec([ "new", cls ].concat(args));
}; };
Expand Down Expand Up @@ -1300,7 +1326,12 @@ BSJSTranslator.prototype["send"] = function $send() {


BSJSTranslator.prototype["new"] = function $new() { BSJSTranslator.prototype["new"] = function $new() {
var cls, args; var cls, args;
return this._skip() && (cls = this._getIntermediate(), true) && this._any(function() { return (this._atomic(function() {
var str;
return this._skip() && (str = this._getIntermediate(), true) && typeof str === "string" && this._exec(str);
}) || this._atomic(function() {
return this._rule("trans", false, [], null, this["trans"]);
})) && (cls = this._getIntermediate(), true) && this._any(function() {
return this._rule("trans", false, [], null, this["trans"]); return this._rule("trans", false, [], null, this["trans"]);
}) && (args = this._getIntermediate(), true) && this._exec("new " + cls + "(" + args.join(",") + ")"); }) && (args = this._getIntermediate(), true) && this._exec("new " + cls + "(" + args.join(",") + ")");
}; };
Expand Down
25 changes: 17 additions & 8 deletions lib/ometajs/grammars/bsjs.ometajs
Expand Up @@ -79,14 +79,19 @@ ometa BSJSParser {
postfix = primExpr:p ( spacesNoNl ("++"|"--"):op -> [#postop, op, p] postfix = primExpr:p ( spacesNoNl ("++"|"--"):op -> [#postop, op, p]
| empty -> p | empty -> p
), ),
primExpr = primExpr:p ( "[" expr:i "]" -> [#getp, i, p] primExpr = primExpr:p ( "(" listOf(#asgnExpr, ','):as ")" -> [#call, p].concat(as)
| "." "name":m "(" listOf(#asgnExpr, ','):as ")" -> [#send, m, p].concat(as) | "." "name":m "(" listOf(#asgnExpr, ','):as ")" -> [#send, m, p].concat(as)
| "." spaces @iName:m "(" listOf(#asgnExpr, ','):as ")" | "." spaces @iName:m "(" listOf(#asgnExpr, ','):as ")"
isKeyword(m) -> [#send, m, p].concat(as) isKeyword(m) -> [#send, m, p].concat(as)
| "." "name":f -> [#getp, [#string, f], p]
| "." spaces @iName:f isKeyword(f) -> [#getp, [#string, f], p]
| "(" listOf(#asgnExpr, ','):as ")" -> [#call, p].concat(as)
) )
| memberExpr,
memberExpr = memberExpr:p ( "[" expr:i "]" -> [#getp, i, p]
| "." "name":f -> [#getp, [#string, f], p]
| "." spaces @iName:f isKeyword(f) -> [#getp, [#string, f], p]
)
| newExpr,
newExpr = "new" memberExpr:n "(" listOf(#asgnExpr, ","):as ")" -> [#new, n].concat(as)
| "new" memberExpr:n -> [#new, n]
| primExprHd, | primExprHd,
primExprHd = "(" expr:e ")" -> e primExprHd = "(" expr:e ")" -> e
| "this" -> [#this] | "this" -> [#this]
Expand Down Expand Up @@ -218,7 +223,9 @@ ometa BSJSIdentity {
func :args curlyTrans:body -> [#func, args, body], func :args curlyTrans:body -> [#func, args, body],
call trans:fn trans*:args -> ([#call, fn].concat(args)), call trans:fn trans*:args -> ([#call, fn].concat(args)),
send :msg trans:recv trans*:args -> ([#send, msg, recv].concat(args)), send :msg trans:recv trans*:args -> ([#send, msg, recv].concat(args)),
new :cls trans*:args -> ([#new, cls].concat(args)), new ( anything:str ?(typeof str === 'string') -> str
| trans
):cls trans*:args -> ([#new, cls].concat(args)),
var varItem+:vs -> ([#var].concat(vs)), var varItem+:vs -> ([#var].concat(vs)),
varItem = [:n trans:v] -> [n, v] varItem = [:n trans:v] -> [n, v]
| [:n] -> [n], | [:n] -> [n],
Expand Down Expand Up @@ -271,7 +278,9 @@ ometa BSJSTranslator {
func :args curlyTrans:body -> ('(function (' + args.join(',') + ')' + body + ')'), func :args curlyTrans:body -> ('(function (' + args.join(',') + ')' + body + ')'),
call trans:fn trans*:args -> (fn + '(' + args.join(',') + ')'), call trans:fn trans*:args -> (fn + '(' + args.join(',') + ')'),
send :msg trans:recv trans*:args -> (recv + '.' + msg + '(' + args.join(',') + ')'), send :msg trans:recv trans*:args -> (recv + '.' + msg + '(' + args.join(',') + ')'),
new :cls trans*:args -> ('new ' + cls + '(' + args.join(',') + ')'), new ( anything:str ?(typeof str === 'string') -> str
| trans
):cls trans*:args -> ('new ' + cls + '(' + args.join(',') + ')'),
var varItem+:vs -> ('var ' + vs.join(',')), var varItem+:vs -> ('var ' + vs.join(',')),
varItem = [:n trans:v] -> (n + ' = ' + v) varItem = [:n trans:v] -> (n + ' = ' + v)
| [:n] -> n, | [:n] -> n,
Expand Down

0 comments on commit 94084ba

Please sign in to comment.