|
@@ -1,45 +1,52 @@
|
|
|
+"use strict";
|
|
|
+
|
|
|
var assert = require("assert.js").ok;
|
|
|
var Errors = require("errors.js");
|
|
|
var Lexer = require("lexer.js");
|
|
|
|
|
|
+function implicitParser(p){
|
|
|
+ return typeof p === "string" ? Lexer.literal(p) : p;
|
|
|
+}
|
|
|
+
|
|
|
+function argumentsToParsers(args){
|
|
|
+ var parsers = Array.prototype.slice.call(args);
|
|
|
+ for(var i = 0; i < parsers.length; ++i)
|
|
|
+ parsers[i] = implicitParser(parsers[i]);
|
|
|
+ return parsers;
|
|
|
+}
|
|
|
+
|
|
|
exports.and = function(/*...*/){
|
|
|
- var args = arguments;
|
|
|
- assert(args.length >= 2);
|
|
|
+ assert(arguments.length >= 2);
|
|
|
+ var parsers = argumentsToParsers(arguments);
|
|
|
|
|
|
return function(stream, context){
|
|
|
- for(var i = 0; i < args.length; ++i){
|
|
|
- if (i != 0)
|
|
|
+ for(var i = 0; i < parsers.length; ++i){
|
|
|
+ if (i)
|
|
|
Lexer.skipSpaces(stream, context);
|
|
|
|
|
|
- var p = args[i];
|
|
|
- if (typeof p == "string")
|
|
|
- p = Lexer.literal(p);
|
|
|
-
|
|
|
+ var p = parsers[i];
|
|
|
if (!p(stream, context))
|
|
|
return false;
|
|
|
}
|
|
|
- return true;
|
|
|
- }
|
|
|
-}
|
|
|
+ return true;
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
exports.or = function(/*...*/){
|
|
|
- var args = arguments;
|
|
|
- assert(args.length >= 2);
|
|
|
+ assert(arguments.length >= 2);
|
|
|
+ var parsers = argumentsToParsers(arguments);
|
|
|
|
|
|
return function(stream, context){
|
|
|
- for(var i = 0; i < args.length; ++i){
|
|
|
- var p = args[i];
|
|
|
- if (typeof p == "string")
|
|
|
- p = Lexer.literal(p);
|
|
|
-
|
|
|
+ for(var i = 0; i < parsers.length; ++i){
|
|
|
+ var p = parsers[i];
|
|
|
var savePos = stream.pos();
|
|
|
if (p(stream, context))
|
|
|
return true;
|
|
|
stream.setPos(savePos);
|
|
|
}
|
|
|
return false;
|
|
|
- }
|
|
|
-}
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
exports.repeat = function(p){
|
|
|
return function(stream, context){
|
|
@@ -50,50 +57,52 @@ exports.repeat = function(p){
|
|
|
}
|
|
|
stream.setPos(savePos);
|
|
|
return true;
|
|
|
- }
|
|
|
-}
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
-exports.optional = function(p){
|
|
|
+exports.optional = function(parser){
|
|
|
assert(arguments.length == 1);
|
|
|
- if (typeof(p) === "string")
|
|
|
- p = Lexer.literal(p);
|
|
|
+ var p = implicitParser(parser);
|
|
|
+
|
|
|
return function(stream, context){
|
|
|
var savePos = stream.pos();
|
|
|
if ( !p(stream, context))
|
|
|
stream.setPos(savePos);
|
|
|
return true;
|
|
|
- }
|
|
|
-}
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
-exports.required = function(parser, error){
|
|
|
- if (typeof(parser) === "string")
|
|
|
- parser = Lexer.literal(parser);
|
|
|
+exports.required = function(parserOrString, error){
|
|
|
+ var parser = implicitParser(parserOrString);
|
|
|
+
|
|
|
return function(stream, context){
|
|
|
if (!parser(stream, context))
|
|
|
- throw new Errors.Error(error);
|
|
|
+ throw new Errors.Error(error
|
|
|
+ ? error
|
|
|
+ : ("'" + parserOrString + "' expected"));
|
|
|
return true;
|
|
|
- }
|
|
|
-}
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
-exports.context = function(parser, contextFactory){
|
|
|
- return function(stream, context){
|
|
|
- var context = new contextFactory(context);
|
|
|
+exports.context = function(parser, ContextFactory){
|
|
|
+ return function(stream, child){
|
|
|
+ var context = new ContextFactory(child);
|
|
|
if (!parser(stream, context))
|
|
|
return false;
|
|
|
if (context.endParse)
|
|
|
return context.endParse() !== false;
|
|
|
return true;
|
|
|
- }
|
|
|
-}
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
exports.emit = function(parser, action){
|
|
|
assert(action);
|
|
|
- if (typeof(parser) === "string")
|
|
|
- parser = Lexer.literal(parser);
|
|
|
+ var p = implicitParser(parser);
|
|
|
+
|
|
|
return function(stream, context){
|
|
|
- if (!parser(stream, context))
|
|
|
+ if (!p(stream, context))
|
|
|
return false;
|
|
|
action(context);
|
|
|
return true;
|
|
|
- }
|
|
|
-}
|
|
|
+ };
|
|
|
+};
|