1
0
Переглянути джерело

Parser changed to allow only associations in #{...}.

Test that used true expressions fixed to use associations.
Herbert Vojčík 11 роки тому
батько
коміт
049c2e4b00
4 змінених файлів з 294 додано та 62 видалено
  1. 2 2
      js/Compiler-Tests.js
  2. 2 2
      st/Compiler-Tests.st
  3. 273 57
      support/parser.js
  4. 17 1
      support/parser.pegjs

+ 2 - 2
js/Compiler-Tests.js

@@ -503,10 +503,10 @@ var $2,$1;
 $2="foo".__minus_gt((1));
 $ctx1.sendIdx["->"]=1;
 $1=globals.HashedCollection._from_([$2,"bar".__minus_gt((2))]);
-self._should_return_("foo\x0a\x09| x |\x0a\x09x := 'foo'->1.\x0a\x09^ #{ x. (true ifTrue: [ x := 'bar'->2 ]) }\x0a",$1);
+self._should_return_("foo\x0a\x09| x |\x0a\x09x := 'foo'.\x0a\x09^ #{ x->1. 'bar'->(true ifTrue: [ 2 ]) }\x0a",$1);
 return self}, function($ctx1) {$ctx1.fill(self,"testDynamicDictionaryElementsOrdered",{},globals.CodeGeneratorTest)})},
 args: [],
-source: "testDynamicDictionaryElementsOrdered\x0a\x09self should: 'foo\x0a\x09| x |\x0a\x09x := ''foo''->1.\x0a\x09^ #{ x. (true ifTrue: [ x := ''bar''->2 ]) }\x0a' return: #{'foo'->1. 'bar'->2}.",
+source: "testDynamicDictionaryElementsOrdered\x0a\x09self should: 'foo\x0a\x09| x |\x0a\x09x := ''foo''.\x0a\x09^ #{ x->1. ''bar''->(true ifTrue: [ 2 ]) }\x0a' return: #{'foo'->1. 'bar'->2}.",
 messageSends: ["should:return:", "->"],
 referencedClasses: []
 }),

+ 2 - 2
st/Compiler-Tests.st

@@ -198,8 +198,8 @@ testDynamicArrayElementsOrdered
 testDynamicDictionaryElementsOrdered
 	self should: 'foo
 	| x |
-	x := ''foo''->1.
-	^ #{ x. (true ifTrue: [ x := ''bar''->2 ]) }
+	x := ''foo''.
+	^ #{ x->1. ''bar''->(true ifTrue: [ 2 ]) }
 ' return: #{'foo'->1. 'bar'->2}.
 !
 

+ 273 - 57
support/parser.js

@@ -317,6 +317,10 @@ globals.SmalltalkParser = (function() {
                                      ._arguments_(pattern[1])
                                      ._nodes_([sequence]);
                          },
+        peg$c136 = "->",
+        peg$c137 = { type: "literal", value: "->", description: "\"->\"" },
+        peg$c138 = function(message, tail) { return tail._valueForReceiver_(message); },
+        peg$c139 = function(receiver, tail) { return tail._valueForReceiver_(receiver); },
 
         peg$currPos          = 0,
         peg$reportedPos      = 0,
@@ -488,7 +492,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsestart() {
       var s0;
 
-      var key    = peg$currPos * 56 + 0,
+      var key    = peg$currPos * 61 + 0,
           cached = peg$cache[key];
 
       if (cached) {
@@ -506,7 +510,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseseparator() {
       var s0, s1;
 
-      var key    = peg$currPos * 56 + 1,
+      var key    = peg$currPos * 61 + 1,
           cached = peg$cache[key];
 
       if (cached) {
@@ -545,7 +549,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsecomments() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 2,
+      var key    = peg$currPos * 61 + 2,
           cached = peg$cache[key];
 
       if (cached) {
@@ -670,7 +674,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsews() {
       var s0, s1;
 
-      var key    = peg$currPos * 56 + 3,
+      var key    = peg$currPos * 61 + 3,
           cached = peg$cache[key];
 
       if (cached) {
@@ -699,7 +703,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseidentifier() {
       var s0, s1, s2, s3;
 
-      var key    = peg$currPos * 56 + 4,
+      var key    = peg$currPos * 61 + 4,
           cached = peg$cache[key];
 
       if (cached) {
@@ -755,7 +759,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsekeyword() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 5,
+      var key    = peg$currPos * 61 + 5,
           cached = peg$cache[key];
 
       if (cached) {
@@ -794,7 +798,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseselector() {
       var s0, s1, s2, s3;
 
-      var key    = peg$currPos * 56 + 6,
+      var key    = peg$currPos * 61 + 6,
           cached = peg$cache[key];
 
       if (cached) {
@@ -850,7 +854,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseclassName() {
       var s0, s1, s2, s3;
 
-      var key    = peg$currPos * 56 + 7,
+      var key    = peg$currPos * 61 + 7,
           cached = peg$cache[key];
 
       if (cached) {
@@ -906,7 +910,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsestring() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 8,
+      var key    = peg$currPos * 61 + 8,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1004,7 +1008,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsesymbol() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 9,
+      var key    = peg$currPos * 61 + 9,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1043,7 +1047,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsebareSymbol() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 10,
+      var key    = peg$currPos * 61 + 10,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1079,7 +1083,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsenumber() {
       var s0, s1;
 
-      var key    = peg$currPos * 56 + 11,
+      var key    = peg$currPos * 61 + 11,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1112,7 +1116,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsenumberExp() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 12,
+      var key    = peg$currPos * 61 + 12,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1165,7 +1169,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsehex() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 13,
+      var key    = peg$currPos * 61 + 13,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1240,7 +1244,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsefloat() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 14,
+      var key    = peg$currPos * 61 + 14,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1342,7 +1346,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseinteger() {
       var s0, s1, s2, s3;
 
-      var key    = peg$currPos * 56 + 15,
+      var key    = peg$currPos * 61 + 15,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1405,7 +1409,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseliteralArray() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 16,
+      var key    = peg$currPos * 61 + 16,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1444,7 +1448,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsebareLiteralArray() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 17,
+      var key    = peg$currPos * 61 + 17,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1483,7 +1487,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseliteralArrayRest() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 18,
+      var key    = peg$currPos * 61 + 18,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1581,7 +1585,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsedynamicArray() {
       var s0, s1, s2, s3, s4, s5, s6;
 
-      var key    = peg$currPos * 56 + 19,
+      var key    = peg$currPos * 61 + 19,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1662,7 +1666,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsedynamicDictionary() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 20,
+      var key    = peg$currPos * 61 + 20,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1681,7 +1685,7 @@ globals.SmalltalkParser = (function() {
       if (s1 !== peg$FAILED) {
         s2 = peg$parsews();
         if (s2 !== peg$FAILED) {
-          s3 = peg$parseexpressions();
+          s3 = peg$parseassociations();
           if (s3 === peg$FAILED) {
             s3 = peg$c37;
           }
@@ -1728,7 +1732,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsepseudoVariable() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 21,
+      var key    = peg$currPos * 61 + 21,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1794,7 +1798,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseparseTimeLiteral() {
       var s0;
 
-      var key    = peg$currPos * 56 + 22,
+      var key    = peg$currPos * 61 + 22,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1824,7 +1828,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseruntimeLiteral() {
       var s0;
 
-      var key    = peg$currPos * 56 + 23,
+      var key    = peg$currPos * 61 + 23,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1848,7 +1852,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseliteral() {
       var s0;
 
-      var key    = peg$currPos * 56 + 24,
+      var key    = peg$currPos * 61 + 24,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1869,7 +1873,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsevariable() {
       var s0, s1;
 
-      var key    = peg$currPos * 56 + 25,
+      var key    = peg$currPos * 61 + 25,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1893,7 +1897,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsekeywordPair() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 26,
+      var key    = peg$currPos * 61 + 26,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1938,7 +1942,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsebinarySelector() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 27,
+      var key    = peg$currPos * 61 + 27,
           cached = peg$cache[key];
 
       if (cached) {
@@ -1983,7 +1987,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsekeywordPattern() {
       var s0, s1, s2, s3, s4, s5, s6;
 
-      var key    = peg$currPos * 56 + 28,
+      var key    = peg$currPos * 61 + 28,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2070,7 +2074,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsebinaryPattern() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 29,
+      var key    = peg$currPos * 61 + 29,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2115,7 +2119,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseunaryPattern() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 30,
+      var key    = peg$currPos * 61 + 30,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2148,7 +2152,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseexpression() {
       var s0;
 
-      var key    = peg$currPos * 56 + 31,
+      var key    = peg$currPos * 61 + 31,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2175,7 +2179,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseexpressionList() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 32,
+      var key    = peg$currPos * 61 + 32,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2226,7 +2230,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseexpressions() {
       var s0, s1, s2, s3;
 
-      var key    = peg$currPos * 56 + 33,
+      var key    = peg$currPos * 61 + 33,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2264,7 +2268,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseassignment() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 34,
+      var key    = peg$currPos * 61 + 34,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2321,7 +2325,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseret() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 35,
+      var key    = peg$currPos * 61 + 35,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2387,7 +2391,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsetemps() {
       var s0, s1, s2, s3, s4, s5, s6;
 
-      var key    = peg$currPos * 56 + 36,
+      var key    = peg$currPos * 61 + 36,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2485,7 +2489,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseblockParamList() {
       var s0, s1, s2, s3, s4, s5, s6;
 
-      var key    = peg$currPos * 56 + 37,
+      var key    = peg$currPos * 61 + 37,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2605,7 +2609,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsesubexpression() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 38,
+      var key    = peg$currPos * 61 + 38,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2668,7 +2672,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsestatements() {
       var s0, s1, s2, s3, s4, s5, s6, s7;
 
-      var key    = peg$currPos * 56 + 39,
+      var key    = peg$currPos * 61 + 39,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2836,7 +2840,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsesequence() {
       var s0;
 
-      var key    = peg$currPos * 56 + 40,
+      var key    = peg$currPos * 61 + 40,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2857,7 +2861,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsestSequence() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 41,
+      var key    = peg$currPos * 61 + 41,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2908,7 +2912,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseblock() {
       var s0, s1, s2, s3, s4, s5, s6, s7;
 
-      var key    = peg$currPos * 56 + 42,
+      var key    = peg$currPos * 61 + 42,
           cached = peg$cache[key];
 
       if (cached) {
@@ -2989,7 +2993,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseoperand() {
       var s0;
 
-      var key    = peg$currPos * 56 + 43,
+      var key    = peg$currPos * 61 + 43,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3013,7 +3017,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseunaryMessage() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 44,
+      var key    = peg$currPos * 61 + 44,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3067,7 +3071,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseunaryTail() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 45,
+      var key    = peg$currPos * 61 + 45,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3115,7 +3119,7 @@ globals.SmalltalkParser = (function() {
     function peg$parseunarySend() {
       var s0, s1, s2, s3;
 
-      var key    = peg$currPos * 56 + 46,
+      var key    = peg$currPos * 61 + 46,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3157,7 +3161,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsebinaryMessage() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 47,
+      var key    = peg$currPos * 61 + 47,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3205,7 +3209,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsebinaryTail() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 48,
+      var key    = peg$currPos * 61 + 48,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3241,7 +3245,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsebinarySend() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 49,
+      var key    = peg$currPos * 61 + 49,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3277,7 +3281,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsekeywordMessage() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 50,
+      var key    = peg$currPos * 61 + 50,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3349,7 +3353,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsekeywordSend() {
       var s0, s1, s2;
 
-      var key    = peg$currPos * 56 + 51,
+      var key    = peg$currPos * 61 + 51,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3382,7 +3386,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsemessage() {
       var s0;
 
-      var key    = peg$currPos * 56 + 52,
+      var key    = peg$currPos * 61 + 52,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3406,7 +3410,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsecascade() {
       var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
 
-      var key    = peg$currPos * 56 + 53,
+      var key    = peg$currPos * 61 + 53,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3535,7 +3539,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsejsStatement() {
       var s0, s1, s2, s3, s4;
 
-      var key    = peg$currPos * 56 + 54,
+      var key    = peg$currPos * 61 + 54,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3633,7 +3637,7 @@ globals.SmalltalkParser = (function() {
     function peg$parsemethod() {
       var s0, s1, s2, s3, s4, s5;
 
-      var key    = peg$currPos * 56 + 55,
+      var key    = peg$currPos * 61 + 55,
           cached = peg$cache[key];
 
       if (cached) {
@@ -3690,6 +3694,218 @@ globals.SmalltalkParser = (function() {
       return s0;
     }
 
+    function peg$parseassociationMessage() {
+      var s0, s1, s2, s3, s4;
+
+      var key    = peg$currPos * 61 + 56,
+          cached = peg$cache[key];
+
+      if (cached) {
+        peg$currPos = cached.nextPos;
+        return cached.result;
+      }
+
+      s0 = peg$currPos;
+      s1 = peg$parsews();
+      if (s1 !== peg$FAILED) {
+        if (input.substr(peg$currPos, 2) === peg$c136) {
+          s2 = peg$c136;
+          peg$currPos += 2;
+        } else {
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c137); }
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parsews();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseunarySend();
+            if (s4 === peg$FAILED) {
+              s4 = peg$parseoperand();
+            }
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c116(s2, s4);
+              s0 = s1;
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c1;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c1;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c1;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c1;
+      }
+
+      peg$cache[key] = { nextPos: peg$currPos, result: s0 };
+
+      return s0;
+    }
+
+    function peg$parseassociationTail() {
+      var s0, s1, s2;
+
+      var key    = peg$currPos * 61 + 57,
+          cached = peg$cache[key];
+
+      if (cached) {
+        peg$currPos = cached.nextPos;
+        return cached.result;
+      }
+
+      s0 = peg$parseassociationMessage();
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = peg$parsebinaryMessage();
+        if (s1 !== peg$FAILED) {
+          s2 = peg$parseassociationTail();
+          if (s2 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c138(s1, s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c1;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c1;
+        }
+      }
+
+      peg$cache[key] = { nextPos: peg$currPos, result: s0 };
+
+      return s0;
+    }
+
+    function peg$parseassociationSend() {
+      var s0, s1, s2;
+
+      var key    = peg$currPos * 61 + 58,
+          cached = peg$cache[key];
+
+      if (cached) {
+        peg$currPos = cached.nextPos;
+        return cached.result;
+      }
+
+      s0 = peg$currPos;
+      s1 = peg$parseunarySend();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseassociationTail();
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c139(s1, s2);
+          s0 = s1;
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c1;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c1;
+      }
+
+      peg$cache[key] = { nextPos: peg$currPos, result: s0 };
+
+      return s0;
+    }
+
+    function peg$parseassociationList() {
+      var s0, s1, s2, s3, s4;
+
+      var key    = peg$currPos * 61 + 59,
+          cached = peg$cache[key];
+
+      if (cached) {
+        peg$currPos = cached.nextPos;
+        return cached.result;
+      }
+
+      s0 = peg$currPos;
+      s1 = peg$parsews();
+      if (s1 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 46) {
+          s2 = peg$c47;
+          peg$currPos++;
+        } else {
+          s2 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c48); }
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parsews();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseassociationSend();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c85(s4);
+              s0 = s1;
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c1;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c1;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c1;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c1;
+      }
+
+      peg$cache[key] = { nextPos: peg$currPos, result: s0 };
+
+      return s0;
+    }
+
+    function peg$parseassociations() {
+      var s0, s1, s2, s3;
+
+      var key    = peg$currPos * 61 + 60,
+          cached = peg$cache[key];
+
+      if (cached) {
+        peg$currPos = cached.nextPos;
+        return cached.result;
+      }
+
+      s0 = peg$currPos;
+      s1 = peg$parseassociationSend();
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$parseassociationList();
+        while (s3 !== peg$FAILED) {
+          s2.push(s3);
+          s3 = peg$parseassociationList();
+        }
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c86(s1, s2);
+          s0 = s1;
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c1;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c1;
+      }
+
+      peg$cache[key] = { nextPos: peg$currPos, result: s0 };
+
+      return s0;
+    }
+
     peg$result = peg$startRuleFunction();
 
     if (peg$result !== peg$FAILED && peg$currPos === input.length) {

+ 17 - 1
support/parser.pegjs

@@ -47,7 +47,7 @@ dynamicArray   = "{" ws expressions:expressions? ws "."? "}" {
                             ._source_(text())
                             ._nodes_(expressions || []);
                  }
-dynamicDictionary = "#{" ws expressions: expressions? ws "}" {
+dynamicDictionary = "#{" ws expressions: associations? ws "}" {
                         return globals.DynamicDictionaryNode._new()
                                ._position_((line()).__at(column()))
                                ._source_(text())
@@ -257,3 +257,19 @@ method         = ws pattern:(keywordPattern / binaryPattern / unaryPattern) ws s
                              ._nodes_([sequence]);
                  }
 
+
+associationMessage  = ws selector:"->" ws arg:(unarySend / operand) {
+                     return globals.SendNode._new()
+                            ._position_((line()).__at(column()))
+                            ._source_(text())
+                            ._selector_(selector)
+                            ._arguments_([arg]);
+                 }
+
+associationTail     = message:associationMessage / message:binaryMessage tail:associationTail  { return tail._valueForReceiver_(message); }
+
+associationSend     = receiver:unarySend tail:associationTail { return tail._valueForReceiver_(receiver); }
+
+associationList = ws "." ws expression:associationSend {return expression;}
+associations    = first:associationSend others:associationList* { return [first].concat(others); }
+