Permalink
Browse files

add object + array literal syntax (and treat commas in a all lists as…

… whitespace)
  • Loading branch information...
1 parent 2d04df3 commit 2017d837adf866edde1badf2543246caeac0bdde @smtlaissezfaire committed Feb 10, 2013
Showing with 118 additions and 4 deletions.
  1. +3 −2 README.md
  2. +30 −2 lib/loop/grammar.jison
  3. +30 −0 lib/loop/grammar/token-builders.js
  4. +55 −0 spec/compile-integration-spec.js
View
@@ -34,7 +34,8 @@ Proposed syntax:
7 => 7
"foo" => "foo"
'foo' => 'foo'
- [1,2,3] => ([] 1 2 3) (in the future: [1 2 3] ?)
+ [1,2,3] => ([] 1 2 3) (syntactic sugar: [1 2 3] or [1,2,3] or [1,2,3,])
+ { a: 'b', c: 'd' } => ({} a 'b' c 'd') (syntactic sugar: { a 'b' c 'd' } or { a 'b', c 'd'} or { a 'b', c 'd',})
foo => foo
foo() => (foo)
function() { x + x } => (function () (+ x x))
@@ -55,7 +56,7 @@ Proposed syntax:
foo.bar() => (foo.bar)
foo = {} => (= foo {})
- { a: 'b', c: 'd' } => ({} a 'b' c 'd') (in the future: { a 'b' c 'd' } ?)
+
[1,2,3,4] => [ 1 2 3 4 ]
x[2] => ([] x 2)
@@ -11,6 +11,11 @@
"." return "DOT";
"(" return "OPEN_PAREN";
")" return "CLOSE_PAREN";
+"{" return "OPEN_BRACE";
+"}" return "CLOSE_BRACE";
+"[" return "OPEN_BRACKET";
+"]" return "CLOSE_BRACKET";
+"," return "COMMA";
[0-9]+ return "INT";
([^\(\)\s\n\r])+ return "SYMBOL";
@@ -30,6 +35,8 @@ prog
s-expression
: list { $$ = $1; }
+ | object-literal { $$ = $1; }
+ | array-literal { $$ = $1; }
| property-access { $$ = $1; }
| atom { $$ = $1; }
| comment { $$ = $1; }
@@ -44,9 +51,30 @@ list
}
;
+object-literal
+ : OPEN_BRACE list-members CLOSE_BRACE {
+ $$ = require("./grammar/token-builders").makeObjectLiteral($2, @2);
+ }
+ | OPEN_BRACE CLOSE_BRACE {
+ $$ = require("./grammar/token-builders").makeObjectLiteral(null, @1);
+ }
+;
+
+array-literal
+ : OPEN_BRACKET list-members CLOSE_BRACKET {
+ $$ = require("./grammar/token-builders").makeArrayLiteral($2, @2);
+ }
+ | OPEN_BRACKET CLOSE_BRACKET {
+ $$ = require("./grammar/token-builders").makeArrayLiteral(null, @1);
+ }
+;
+
+
list-members
- : list-members s-expression { $$ = $1.concat($2); }
- | s-expression { $$ = [$1]; }
+ : list-members s-expression COMMA { $$ = $1.concat($2); }
+ | list-members COMMA s-expression { $$ = $1.concat($3); }
+ | list-members s-expression { $$ = $1.concat($2) }
+ | s-expression { $$ = [$1]; }
;
property-access
@@ -47,6 +47,36 @@ tokenBuilders.makeString = function(str, sourceInfo) {
};
};
+tokenBuilders.makeObjectLiteral = function(listMembers, sourceInfo) {
+ if (listMembers) {
+ var list = [];
+ list.push(this.makeSymbol("{}", sourceInfo));
+ var i;
+ for (i = 0; i < listMembers.length; i++) {
+ var listMember = listMembers[i];
+ list.push(listMember);
+ }
+ return this.makeList(list, sourceInfo);
+ } else {
+ return this.makeSymbol("{}", sourceInfo);
+ }
+};
+
+tokenBuilders.makeArrayLiteral = function(listMembers, sourceInfo) {
+ if (listMembers) {
+ var list = [];
+ list.push(this.makeSymbol("[]", sourceInfo));
+ var i;
+ for (i = 0; i < listMembers.length; i++) {
+ var listMember = listMembers[i];
+ list.push(listMember);
+ }
+ return this.makeList(list, sourceInfo);
+ } else {
+ return this.makeSymbol("[]", sourceInfo);
+ }
+};
+
tokenBuilders.makePropertyAccess = function(key, value, sourceInfo) {
return {
type: 'prop-access',
@@ -395,5 +395,60 @@ vows.describe("integration spec").addBatch({
var expected = '1+2+3+4+5';
assert.equal(loop.compile(source), expected);
+ },
+
+ 'it should use { } as an object literal syntax': function() {
+ var source = '(define x { y "foo" })';
+ var expected = 'var x={y:"foo"}';
+ assert.equal(loop.compile(source), expected);
+ },
+
+ 'it should allow multiple in an object literal values': function() {
+ var source = '(define x { y "foo" z 100 })';
+ var expected = 'var x={y:"foo",z:100}';
+ assert.equal(loop.compile(source), expected);
+ },
+
+ 'it should allow no values in an object literal': function() {
+ var source = '(define x {})';
+ var expected = 'var x={}';
+ assert.equal(loop.compile(source), expected);
+ },
+
+ 'it should allow an object literal off on its own': function() {
+ var source = '{}';
+ var expected = '{}';
+ assert.equal(loop.compile(source), expected);
+ },
+
+ 'it should allow commas in the object literal': function() {
+ var source = '(define x { one 1, two 2})';
+ var expected = 'var x={one:1,two:2}';
+ assert.equal(loop.compile(source), expected);
+
+ source = '(define x { one 1, two 2,})';
+ assert.equal(loop.compile(source), expected);
+ },
+
+ 'it should allow optional commas in a list': function() {
+ var source = "(define x ([] 1 2 3 4))";
+ var expected = 'var x=[1,2,3,4]';
+ assert.equal(loop.compile(source), expected);
+
+ source = "(define x ([] 1, 2, 3, 4))";
+ assert.equal(loop.compile(source), expected);
+ },
+ 'it should allow an object literal with []': function() {
+ var source = "(define x [1 2 3 4])";
+ var expected = 'var x=[1,2,3,4]';
+ assert.equal(loop.compile(source), expected);
+
+ source = "(define x [1, 2, 3, 4])";
+ assert.equal(loop.compile(source), expected);
+ },
+ 'it should allow an object literal with no values': function() {
+ var source = "(define x [])";
+ var expected = 'var x=[]';
+ assert.equal(loop.compile(source), expected);
}
}).export(module);

0 comments on commit 2017d83

Please sign in to comment.