Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Remove JS.Class from involvement in constructing parser classes and s…

…yntax nodes. Generated parsers are now completely self-contained.
  • Loading branch information...
commit 522fc631cd0357b02b262aa7cdbb92b040a9752f 1 parent 6624357
James Coglan authored
59 source/canopy/builder.js
View
@@ -34,6 +34,7 @@ Canopy.extend(Canopy.Builder.prototype, {
delimitField_: function() {
this.write(this._methodSeparator);
+ if (this._methodSeparator) this.newline_();
this._methodSeparator = ',';
},
@@ -72,10 +73,10 @@ Canopy.extend(Canopy.Builder.prototype, {
builder.line_(klass + ' = ' + nodeType);
});
this.else_(function(builder) {
- builder.line_(klass + ' = this.klass.SyntaxNode');
+ builder.line_(klass + ' = SyntaxNode');
});
} else {
- klass = this.tempVar_('klass', 'this.klass.SyntaxNode');
+ klass = this.tempVar_('klass', 'SyntaxNode');
}
this.line_(address + ' = new ' + klass + '(' + expression + of + elements + labelled + ')');
@@ -86,14 +87,14 @@ Canopy.extend(Canopy.Builder.prototype, {
extendNode_: function(address, nodeType) {
if (!nodeType) return;
this.unless_(nodeType + ' instanceof Function', function(builder) {
- builder.line_(address + '.extend(' + nodeType + ')');
+ builder.line_('extend(' + address + ', ' + nodeType + ')');
});
},
failure_: function(address, expected) {
this.line_(address + ' = null');
var input = this.input_(), of = this.offset_(), slice = this.slice_(1);
- var error = 'this.error = this.klass.lastError';
+ var error = 'this.error = this.constructor.lastError';
this.if_('!this.error || this.error.offset <= ' + of, function(builder) {
builder.line_(error + ' = {input: ' + input +
', offset: ' + of +
@@ -104,53 +105,35 @@ Canopy.extend(Canopy.Builder.prototype, {
nameSpace_: function(objectName) {
var parts = objectName.split('.');
- this.line_('(function() {');
- this.indent_(function() {
- this.var_('namespace', 'this');
- for (var i = 0, n = parts.length; i < n - 1; i++)
- this.line_('namespace = namespace.' + parts[i] + ' = namespace.' + parts[i] + ' || {}');
- this.if_('typeof exports === "object"', function(builder) {
- builder.line_('exports.' + parts[0] + ' = this.' + parts[0]);
- });
- }, this);
- this.line_('})()');
+ this.var_('namespace', 'this');
+ for (var i = 0, n = parts.length; i < n - 1; i++)
+ this.line_('namespace = namespace.' + parts[i] + ' = namespace.' + parts[i] + ' || {}');
},
- module_: function(name, block, context) {
- this.newline_();
- this.write(name + ' = new JS.Module("' + name + '", {');
+ closure_: function(block, context) {
+ this.write('(function() {');
new Canopy.Builder(this).indent_(block, context);
this.newline_();
- this.write('});');
+ this.write('})();');
+ this.newline_();
+ this.newline_();
},
- class_: function(name, block, context) {
+ function_: function(name, args, block, context) {
this.newline_();
- this.write(name + ' = new JS.Class("' + name + '", {');
+ this.write(name + ' = function(' + args.join(', ') + ') {');
new Canopy.Builder(this).indent_(block, context);
this.newline_();
- this.write('});');
- },
-
- include_: function(name) {
- this.delimitField_();
+ this.write('};');
this.newline_();
- this.write('include: ' + name);
},
- classMethods_: function(block, context) {
- this.delimitField_();
+ module_: function(name, block, context) {
this.newline_();
- this.write('extend: {');
+ this.write(name + ' = {');
new Canopy.Builder(this).indent_(block, context);
this.newline_();
- this.write('}');
- },
-
- field_: function(name, value) {
- this.delimitField_();
- this.newline_();
- this.write(name + ': ' + value);
+ this.write('};');
},
method_: function(name, args, block, context) {
@@ -188,6 +171,10 @@ Canopy.extend(Canopy.Builder.prototype, {
this.write('}');
},
+ for_: function(condition, block, context) {
+ this.conditional_('for', condition, block, context);
+ },
+
while_: function(condition, block, context) {
this.conditional_('while', condition, block, context);
},
69 source/canopy/compiler/grammar.js
View
@@ -12,41 +12,47 @@ Canopy.Compiler.Grammar = {
},
compile: function(builder) {
- builder.nameSpace_(this.grammarName());
- builder.newline_();
-
- builder.module_(this.grammarName(), function(builder) {
- builder.field_('root', '"' + this.rules.elements[0].grammar_rule.name() + '"');
- this.rules.forEach(function(rule) {
- rule.grammar_rule.compile(builder);
+ builder.closure_(function(builder) {
+ builder.function_('var extend', ['destination', 'source'], function(builder) {
+ builder.line_('if (!source) return destination');
+ builder.for_('var key in source', function(builder) {
+ builder.if_('destination[key] !== source[key]', function(builder) {
+ builder.line_('destination[key] = source[key]');
+ });
+ });
+ builder.return_('destination');
});
- }, this);
- builder.newline_();
-
- builder.class_(this.grammarName() + 'Parser', function(builder) {
- builder.include_(this.grammarName());
- builder.method_('initialize', ['input'], function(builder) {
+
+ builder.nameSpace_(this.grammarName());
+ builder.newline_();
+
+ builder.module_(this.grammarName(), function(builder) {
+ this.rules.forEach(function(rule) {
+ rule.grammar_rule.compile(builder);
+ });
+ }, this);
+ builder.newline_();
+
+ var parser = this.grammarName() + 'Parser',
+ root = this.rules.elements[0].grammar_rule.name();
+
+ builder.function_(parser, ['input'], function(builder) {
builder.ivar_('input', 'input');
builder.ivar_('offset', '0');
builder.ivar_('nodeCache', '{}');
});
- builder.method_('parse', [], function(builder) {
- builder.var_('result', 'this["__consume__" + this.root]()');
+ builder.function_(parser + '.prototype.parse', [], function(builder) {
+ builder.var_('result', 'this.__consume__' + root + '()');
builder.return_(builder.offset_() + ' === ' + builder.input_() + '.length ? result : null');
});
- builder.classMethods_(function(builder) {
- builder.method_('parse', ['input'], function(builder) {
- builder.var_('parser', 'new this(input)');
- builder.return_('parser.parse()');
- });
+ builder.function_(parser + '.parse', ['input'], function(builder) {
+ builder.var_('parser', 'new this(input)');
+ builder.return_('parser.parse()');
});
- }, this);
- builder.newline_();
-
- builder.class_(this.grammarName() + 'Parser.SyntaxNode', function(builder) {
- builder.include_('JS.Enumerable');
+ builder.line_('extend(' + parser + '.prototype, ' + this.grammarName() + ')');
+ builder.newline_();
- builder.method_('initialize', ['textValue', 'offset', 'elements', 'properties'], function(builder) {
+ builder.function_('var SyntaxNode', ['textValue', 'offset', 'elements', 'properties'], function(builder) {
builder.line_('this.textValue = textValue');
builder.line_('this.offset = offset');
builder.line_('this.elements = elements || []');
@@ -54,17 +60,18 @@ Canopy.Compiler.Grammar = {
builder.line_('if (!properties) return');
builder.line_('for (var key in properties) this[key] = properties[key]');
});
-
- builder.method_('forEach', ['block', 'context'], function(builder) {
+ builder.function_('SyntaxNode.prototype.forEach', ['block', 'context'], function(builder) {
builder.newline_();
builder.write('for (var i = 0, n = this.elements.length; i < n; i++)');
builder.indent_(function(builder) {
builder.line_('block.call(context, this.elements[i], i)');
});
});
- });
- builder.newline_();
- builder.line_(this.grammarName() + 'Parser.formatError = ' + Canopy.formatError.toString());
+ builder.line_(parser + '.SyntaxNode = SyntaxNode');
+
+ builder.newline_();
+ builder.line_(this.grammarName() + 'Parser.formatError = ' + Canopy.formatError.toString());
+ }, this);
}
};
4,312 source/canopy/meta_grammar.js
View
2,170 additions, 2,142 deletions not shown
2  spec/browser.html
View
@@ -3,12 +3,10 @@
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Canopy test runner</title>
- <link rel="stylesheet" type="text/css" href="../vendor/js.class/test/testui.css">
</head>
<body>
<script type="text/javascript">CWD = '..'</script>
<script type="text/javascript" src="../node_modules/jsclass/min/loader.js"></script>
- <script type="text/javascript" src="../node_modules/jsclass/min/core.js"></script>
<script type="text/javascript" src="../lib/canopy-min.js"></script>
<script type="text/javascript" src="../spec/runner.js"></script>
</body>
18 spec/canopy/compiler/choice_part_spec.js
View
@@ -7,7 +7,11 @@ function() { with(this) {
Canopy.compile('grammar ClassTypeTest\
rule <- "content" <NodeType>')
- NodeType = new JS.Class(ClassTypeTestParser.SyntaxNode)
+ NodeType = function(text, offset, children) {
+ this.textValue = text
+ this.offset = 0
+ this.elements = children
+ }
}})
it('creates nodes using the named type', function() { with(this) {
@@ -21,7 +25,7 @@ function() { with(this) {
describe('when the node type is a mixin', function() { with(this) {
before(function() { with(this) {
- NodeType = new JS.Module({ custom: function(){} })
+ NodeType = { custom: function() { return 'pass!' } }
Canopy.compile('grammar ModuleTypeTest\
rule <- "content" <NodeType>')
@@ -29,7 +33,7 @@ function() { with(this) {
it('creates nodes using the named type', function() { with(this) {
var result = ModuleTypeTestParser.parse('content')
- assertKindOf( NodeType, result )
+ assertEqual( 'pass!', result.custom() )
assertRespondTo( result, 'custom' )
}})
@@ -40,27 +44,27 @@ function() { with(this) {
describe('when the underlying parser is a choice', function() { with(this) {
before(function() { with(this) {
- NodeType = new JS.Module({ custom: function(){} })
+ NodeType = { custom: function() { return 'pass!' } }
Canopy.compile('grammar TypedChoiceTest\
rule <- ("content" / "booya") <NodeType>')
}})
it('extends the chosen node with the mixin', function() { with(this) {
- assertKindOf( NodeType, TypedChoiceTestParser.parse('booya') )
+ assertEqual( 'pass!', TypedChoiceTestParser.parse('content').custom() )
}})
}})
describe('when the underlying parser is a maybe', function() { with(this) {
before(function() { with(this) {
- NodeType = new JS.Module({ custom: function(){} })
+ NodeType = { custom: function() { return 'pass!' } }
Canopy.compile('grammar TypedMaybeTest\
rule <- "content"? <NodeType>')
}})
it('extends the chosen node with the mixin', function() { with(this) {
- assertKindOf( NodeType, TypedMaybeTestParser.parse('content') )
+ assertEqual( 'pass!', TypedMaybeTestParser.parse('content').custom() )
}})
}})
2  spec/canopy/meta_grammar_parser_spec.js
View
@@ -1,4 +1,4 @@
-Canopy.MetaGrammarParserSpec = JS.Test.describe(Canopy.MetaGrammarParser,
+Canopy.MetaGrammarParserSpec = JS.Test.describe("Canopy.MetaGrammarParser",
function() { with(this) {
describe('with an any-char rule', function() { with(this) {
before(function() { with(this) {
2  spec/console.js
View
@@ -14,12 +14,10 @@ JSCLASS_PATH = 'node_modules/jsclass/min'
if (typeof require === 'function') {
require('../' + JSCLASS_PATH + '/loader')
- JS.require('JS.Class')
Canopy = require('../lib/canopy-min')
require('./runner')
} else {
load(JSCLASS_PATH + '/loader.js')
- JS.require('JS.Class')
load('lib/canopy-min.js')
load('spec/runner.js')
}
Please sign in to comment.
Something went wrong with that request. Please try again.