parser.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. "use strict";
  2. var assert = require("assert.js").ok;
  3. var Errors = require("errors.js");
  4. var Lexer = require("lexer.js");
  5. var Stream = require("oberon.js/Stream.js");
  6. function implicitParser(p){
  7. return typeof p === "string" ? Lexer.literal(p) : p;
  8. }
  9. function argumentsToParsers(args){
  10. var parsers = Array.prototype.slice.call(args);
  11. for(var i = 0; i < parsers.length; ++i)
  12. parsers[i] = implicitParser(parsers[i]);
  13. return parsers;
  14. }
  15. exports.and = function(/*...*/){
  16. assert(arguments.length >= 2);
  17. var parsers = argumentsToParsers(arguments);
  18. return function(stream, context){
  19. for(var i = 0; i < parsers.length; ++i){
  20. if (i)
  21. Lexer.skipSpaces(stream, context);
  22. var p = parsers[i];
  23. if (!p(stream, context))
  24. return false;
  25. }
  26. return true;
  27. };
  28. };
  29. exports.or = function(/*...*/){
  30. assert(arguments.length >= 2);
  31. var parsers = argumentsToParsers(arguments);
  32. return function(stream, context){
  33. for(var i = 0; i < parsers.length; ++i){
  34. var p = parsers[i];
  35. var savePos = Stream.pos(stream);
  36. if (p(stream, context))
  37. return true;
  38. Stream.setPos(stream, savePos);
  39. }
  40. return false;
  41. };
  42. };
  43. exports.repeat = function(p){
  44. return function(stream, context){
  45. var savePos = Stream.pos(stream);
  46. while (!Stream.eof(stream) && p(stream, context)){
  47. Lexer.skipSpaces(stream, context);
  48. savePos = Stream.pos(stream);
  49. }
  50. Stream.setPos(stream, savePos);
  51. return true;
  52. };
  53. };
  54. exports.optional = function(parser){
  55. assert(arguments.length == 1);
  56. var p = implicitParser(parser);
  57. return function(stream, context){
  58. var savePos = Stream.pos(stream);
  59. if ( !p(stream, context))
  60. Stream.setPos(stream, savePos);
  61. return true;
  62. };
  63. };
  64. exports.required = function(parserOrString, error){
  65. var parser = implicitParser(parserOrString);
  66. return function(stream, context){
  67. if (!parser(stream, context))
  68. throw new Errors.Error(error
  69. ? error
  70. : ("'" + parserOrString + "' expected"));
  71. return true;
  72. };
  73. };
  74. exports.context = function(parser, ContextFactory){
  75. return function(stream, child){
  76. var context = new ContextFactory(child);
  77. if (!parser(stream, context))
  78. return false;
  79. if (context.endParse)
  80. return context.endParse() !== false;
  81. return true;
  82. };
  83. };
  84. exports.emit = function(parser, action){
  85. assert(action);
  86. var p = implicitParser(parser);
  87. return function(stream, context){
  88. if (!p(stream, context))
  89. return false;
  90. action(context);
  91. return true;
  92. };
  93. };