Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

bsjs: good looking "new" expr implementation

* grammar: better error reporting
  • Loading branch information...
commit 94084ba2246f600d5c14263886048ebf71a58ded 1 parent 36ff541
Fedor Indutny indutny authored
5 lib/ometajs/compiler/ir.js
View
@@ -167,9 +167,10 @@ IR.prototype.render = function render() {
parent = ast[2];
ast[3].forEach(function(rule) {
+ var name = rule[1] || '';
buf.push(
- ast[1], '.prototype[', JSON.stringify(rule[1]), ']',
- ' = function $' + rule[1].replace(/[^\w]+/g, '') + '() {'
+ ast[1], '.prototype[', JSON.stringify(name), ']',
+ ' = function $' + name.replace(/[^\w]+/g, '') + '() {'
);
args(rule[2]);
17 lib/ometajs/core/grammar.js
View
@@ -11,7 +11,8 @@ function AbstractGrammar(source) {
this._name = 'AbstractGrammar';
this._errorRule = '';
- this._errorOffset = '';
+ this._errorHistory = '';
+ this._errorOffset = -1;
this._errorSource = source;
}
util.inherits(AbstractGrammar, ometajs.core.AbstractParser);
@@ -51,10 +52,14 @@ AbstractGrammar.matchAll = function matchAll(source, rule, args, errback) {
current = 0,
error = grmr._errorStack || new Error();
- if (Array.isArray(source)) {
- // TODO: Implement me!
+ if (Array.isArray(grmr._errorSource)) {
+ var strArray = util.inspect(grmr._errorSource, false, 4);
+ error.message = grmr._errorRule + ' rule failed at: ' +
+ strArray + ':' +
+ grmr._errorOffset;
} 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)) {
current += source.length + 1;
return false;
@@ -91,8 +96,10 @@ AbstractGrammar.matchAll = function matchAll(source, rule, args, errback) {
// Internal method for tracking errors
//
AbstractGrammar.prototype._lastError = function _lastError(rule) {
- if (this._errorOffset <= this._offset) {
+ if (this._errorHistory <= this._history &&
+ this._errorOffset <= this._offset) {
this._errorRule = rule;
+ this._errorHistory = this._history;
this._errorOffset = this._offset;
this._errorSource = this._source;
}
45 lib/ometajs/grammars/bsjs.js
View
@@ -500,25 +500,46 @@ BSJSParser.prototype["primExpr"] = function $primExpr() {
return this._atomic(function() {
var p;
return this._rule("primExpr", false, [], null, this["primExpr"]) && (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 ]);
+ 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() {
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));
}) || this._atomic(function() {
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));
+ }));
+ }) || 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() {
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 ]);
}) || this._atomic(function() {
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 ]);
- }) || 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() {
return this._rule("primExprHd", false, [], null, this["primExprHd"]);
});
};
@@ -1037,7 +1058,12 @@ BSJSIdentity.prototype["send"] = function $send() {
BSJSIdentity.prototype["new"] = function $new() {
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"]);
}) && (args = this._getIntermediate(), true) && this._exec([ "new", cls ].concat(args));
};
@@ -1300,7 +1326,12 @@ BSJSTranslator.prototype["send"] = function $send() {
BSJSTranslator.prototype["new"] = function $new() {
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"]);
}) && (args = this._getIntermediate(), true) && this._exec("new " + cls + "(" + args.join(",") + ")");
};
25 lib/ometajs/grammars/bsjs.ometajs
View
@@ -79,14 +79,19 @@ ometa BSJSParser {
postfix = primExpr:p ( spacesNoNl ("++"|"--"):op -> [#postop, op, p]
| empty -> p
),
- primExpr = primExpr:p ( "[" expr:i "]" -> [#getp, i, p]
- | "." "name":m "(" listOf(#asgnExpr, ','):as ")" -> [#send, m, p].concat(as)
+ primExpr = primExpr:p ( "(" listOf(#asgnExpr, ','):as ")" -> [#call, p].concat(as)
+ | "." "name":m "(" listOf(#asgnExpr, ','):as ")" -> [#send, m, p].concat(as)
| "." spaces @iName:m "(" listOf(#asgnExpr, ','):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)
+ isKeyword(m) -> [#send, m, 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 = "(" expr:e ")" -> e
| "this" -> [#this]
@@ -218,7 +223,9 @@ ometa BSJSIdentity {
func :args curlyTrans:body -> [#func, args, body],
call trans:fn trans*:args -> ([#call, fn].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)),
varItem = [:n trans:v] -> [n, v]
| [:n] -> [n],
@@ -271,7 +278,9 @@ ometa BSJSTranslator {
func :args curlyTrans:body -> ('(function (' + args.join(',') + ')' + body + ')'),
call trans:fn trans*:args -> (fn + '(' + 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(',')),
varItem = [:n trans:v] -> (n + ' = ' + v)
| [:n] -> n,
Please sign in to comment.
Something went wrong with that request. Please try again.