123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- "use strict";
- var Class = require("rtl.js").Class;
- var Code = require("js/Code.js");
- var ContextExpression = require("js/ContextExpression.js");
- var ContextHierarchy = require("js/ContextHierarchy.js");
- var ContextType = require("js/ContextType.js");
- var Errors = require("js/Errors.js");
- var LanguageContext = require("js/LanguageContext.js");
- var oc = require("oc.js");
- var makeRTL = require("rtl_code.js").makeRTL;
- var Scope = require("js/Scope.js");
- var Stream = require("js/Stream.js");
- var Test = require("test.js");
- var TestError = Test.TestError;
- function context(grammar, source){
- return {grammar: grammar, source: source};
- }
- function pass(/*...*/){return Array.prototype.slice.call(arguments);}
- function fail(/*...*/){return Array.prototype.slice.call(arguments);}
- var TestModuleGenerator = Class.extend({
- init: function TestModuleGenerator(){},
- prolog: function(){return undefined;},
- epilog: function(){return undefined;}
- });
- var TestContextRoot = Class.extend.call(ContextHierarchy.Root, {
- init: function TestContextRoot(language, moduleResolver){
- var rtl = new makeRTL(language.rtl);
- ContextHierarchy.Root.call(
- this,
- { codeTraits: language.makeCodeTraits(language.codeGenerator.nil, rtl),
- moduleGenerator: function(){return new TestModuleGenerator();},
- rtl: rtl,
- types: language.types,
- stdSymbols: language.stdSymbols,
- moduleResolver: moduleResolver
- });
- this.pushScope(new Scope.Module("test", language.stdSymbols));
- },
- qualifyScope: function(){return "";},
- handleMessage: function(msg){
- if (msg instanceof ContextType.DescribeScopeMsg)
- msg.result = new ContextType.ScopeInfo("test", 0);
- },
- handleLiteral: function(){}
- });
- var TestContext = Class.extend.call(ContextExpression.ExpressionHandler, {
- init: function TestContext(language, moduleResolver){
- ContextExpression.ExpressionHandler.call(this, new TestContextRoot(language, moduleResolver));
- },
- handleExpression: function(){}
- });
- function makeContext(language, moduleResolver){return new TestContext(language, moduleResolver);}
- function testWithSetup(setup, pass, fail){
- return function(){
- var test = setup();
- var i;
- for(i = 0; i < pass.length; ++i)
- test.expectOK(pass[i]);
-
- if (fail)
- for(i = 0; i < fail.length; ++i){
- var f = fail[i];
- test.expectError(f[0], f[1]);
- }
- };
- }
- function parseInContext(grammar, s, context){
- var stream = new Stream.Type(s);
- if (!grammar(stream, context) || !Stream.eof(stream))
- throw new Errors.Error("not parsed");
- }
- function runAndHandleErrors(action, s, handlerError){
- try {
- action(s);
- }
- catch (x){
- if (!(x instanceof Errors.Error))
- throw new Error("'" + s + "': " + x + "\n"
- + (x.stack ? x.stack : "(no stack)"));
-
- if (handlerError)
- handlerError(x);
- //else
- // throw x;
- // console.log(s + ": " + x);
- return false;
- }
- return true;
- }
- function setup(run){
- return {
- expectOK: function(s){
- function handleError(e){throw new TestError(s + "\n\t" + e);}
- if (!runAndHandleErrors(run, s, handleError))
- throw new TestError(s + ": not parsed");
- },
- expectError: function(s, error){
- function handleError(actualError){
- var sErr = actualError.toString();
- if (sErr != error)
- throw new TestError(s + "\n\texpected error: " + error + "\n\tgot: " + sErr );
- }
- if (runAndHandleErrors(run, s, handleError))
- throw new TestError(s + ": should not be parsed, expect error: " + error);
- }
- };
- }
- function parseUsingGrammar(parser, language, s, cxFactory){
- var baseContext = makeContext(language);
- var context = cxFactory ? cxFactory(baseContext) : baseContext;
- parseInContext(parser, s, context);
- if (context.root)
- context.root().currentScope().close();
- }
- function setupParser(parser, language, contextFactory){
- function parseImpl(s){
- return parseUsingGrammar(parser, language, s, contextFactory);
- }
- return setup(parseImpl);
- }
- function compileModule(src, language){
- var imported = oc.compileModule(language.grammar, new Stream.Type(src), makeContext(language));
- return imported.symbol().info();
- }
- function makeModuleResolver(moduleReader, language){
- return moduleReader ? function(name){ return compileModule(moduleReader(name), language); }
- : undefined;
- }
- function setupWithContext(fixture, contextGrammar, language){
- function innerMakeContext(){
- var context = makeContext(language, makeModuleResolver(fixture.moduleReader, language));
- var source = fixture.source;
- try {
- parseInContext(contextGrammar, source, context);
- }
- catch (x) {
- if (x instanceof Errors.Error)
- throw new TestError("setup error: " + x + "\n" + source);
- throw x;
- }
- return context;
- }
- return setupParser(fixture.grammar, language, innerMakeContext);
- }
- function testWithContext(fixture, contextGrammar, language, pass, fail){
- return testWithSetup(
- setupWithContext.bind(undefined, fixture, contextGrammar, language),
- pass,
- fail);
- }
- function testWithGrammar(parser, language, pass, fail){
- return testWithSetup(
- function(){return setupParser(parser, language);},
- pass,
- fail);
- }
- function testWithModule(src, language, pass, fail){
- var grammar = language.grammar;
- return testWithSetup(
- function(){
- var module = compileModule(src, language);
- return setup(function(s){
- oc.compileModule(grammar,
- new Stream.Type(s),
- new TestContext(language, function(){return module;}));
- });},
- pass,
- fail);
- }
- function nthLine(s, n){
- var result = 0;
- while (n--)
- result = s.indexOf('\n', result) + 1;
- return result;
- }
- function assert(cond){
- if (!cond){
- var stack = new Error().stack;
- var from = nthLine(stack, 2);
- stack = stack.substring(from, stack.indexOf('\n', from));
- throw new TestError("assertion failed: " + stack);
- }
- }
- function expectEq(x1, x2){
- if (x1 == x2)
- return;
- throw new TestError("'" + x1 + "' != '" + x2 + "'");
- }
- exports.assert = assert;
- exports.expectEq = expectEq;
- exports.context = context;
- exports.pass = pass;
- exports.fail = fail;
- exports.setupParser = setupParser;
- exports.testWithContext = testWithContext;
- exports.testWithGrammar = testWithGrammar;
- exports.testWithModule = testWithModule;
- exports.testWithSetup = testWithSetup;
|