Преглед на файлове

Merge pull request #443 from herby/parser

Fix and enhancement of parser. Fixes #309.
Nicolas Petton преди 11 години
родител
ревизия
260fd9f23f
променени са 2 файла, в които са добавени 328 реда и са изтрити 166 реда
  1. 318 160
      js/parser.js
  2. 10 6
      js/parser.pegjs

+ 318 - 160
js/parser.js

@@ -43,17 +43,23 @@ smalltalk.parser = (function(){
         "identifier": parse_identifier,
         "varIdentifier": parse_varIdentifier,
         "keyword": parse_keyword,
+        "selector": parse_selector,
         "className": parse_className,
         "string": parse_string,
         "symbol": parse_symbol,
+        "bareSymbol": parse_bareSymbol,
         "number": parse_number,
         "hex": parse_hex,
         "float": parse_float,
         "integer": parse_integer,
         "literalArray": parse_literalArray,
+        "bareLiteralArray": parse_bareLiteralArray,
+        "literalArrayRest": parse_literalArrayRest,
         "dynamicArray": parse_dynamicArray,
         "dynamicDictionary": parse_dynamicDictionary,
         "pseudoVariable": parse_pseudoVariable,
+        "parseTimeLiteral": parse_parseTimeLiteral,
+        "runtimeLiteral": parse_runtimeLiteral,
         "literal": parse_literal,
         "variable": parse_variable,
         "classReference": parse_classReference,
@@ -575,6 +581,75 @@ smalltalk.parser = (function(){
         return result0;
       }
       
+      function parse_selector() {
+        var cacheKey = "selector@" + pos.offset;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = clone(cachedResult.nextPos);
+          return cachedResult.result;
+        }
+        
+        var result0, result1, result2;
+        var pos0, pos1;
+        
+        pos0 = clone(pos);
+        pos1 = clone(pos);
+        if (/^[a-zA-Z]/.test(input.charAt(pos.offset))) {
+          result0 = input.charAt(pos.offset);
+          advance(pos, 1);
+        } else {
+          result0 = null;
+          if (reportFailures === 0) {
+            matchFailed("[a-zA-Z]");
+          }
+        }
+        if (result0 !== null) {
+          result1 = [];
+          if (/^[a-zA-Z0-9:]/.test(input.charAt(pos.offset))) {
+            result2 = input.charAt(pos.offset);
+            advance(pos, 1);
+          } else {
+            result2 = null;
+            if (reportFailures === 0) {
+              matchFailed("[a-zA-Z0-9:]");
+            }
+          }
+          while (result2 !== null) {
+            result1.push(result2);
+            if (/^[a-zA-Z0-9:]/.test(input.charAt(pos.offset))) {
+              result2 = input.charAt(pos.offset);
+              advance(pos, 1);
+            } else {
+              result2 = null;
+              if (reportFailures === 0) {
+                matchFailed("[a-zA-Z0-9:]");
+              }
+            }
+          }
+          if (result1 !== null) {
+            result0 = [result0, result1];
+          } else {
+            result0 = null;
+            pos = clone(pos1);
+          }
+        } else {
+          result0 = null;
+          pos = clone(pos1);
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, line, column, first, others) {return first + others.join("")})(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]);
+        }
+        if (result0 === null) {
+          pos = clone(pos0);
+        }
+        
+        cache[cacheKey] = {
+          nextPos: clone(pos),
+          result:  result0
+        };
+        return result0;
+      }
+      
       function parse_className() {
         var cacheKey = "className@" + pos.offset;
         var cachedResult = cache[cacheKey];
@@ -774,8 +849,8 @@ smalltalk.parser = (function(){
           return cachedResult.result;
         }
         
-        var result0, result1, result2, result3;
-        var pos0, pos1, pos2;
+        var result0, result1;
+        var pos0, pos1;
         
         pos0 = clone(pos);
         pos1 = clone(pos);
@@ -789,96 +864,7 @@ smalltalk.parser = (function(){
           }
         }
         if (result0 !== null) {
-          result1 = [];
-          pos2 = clone(pos);
-          if (/^[a-zA-Z0-9:]/.test(input.charAt(pos.offset))) {
-            result3 = input.charAt(pos.offset);
-            advance(pos, 1);
-          } else {
-            result3 = null;
-            if (reportFailures === 0) {
-              matchFailed("[a-zA-Z0-9:]");
-            }
-          }
-          if (result3 !== null) {
-            result2 = [];
-            while (result3 !== null) {
-              result2.push(result3);
-              if (/^[a-zA-Z0-9:]/.test(input.charAt(pos.offset))) {
-                result3 = input.charAt(pos.offset);
-                advance(pos, 1);
-              } else {
-                result3 = null;
-                if (reportFailures === 0) {
-                  matchFailed("[a-zA-Z0-9:]");
-                }
-              }
-            }
-          } else {
-            result2 = null;
-          }
-          if (result2 !== null) {
-            result2 = (function(offset, line, column, digits) {return digits.join("")})(pos2.offset, pos2.line, pos2.column, result2);
-          }
-          if (result2 === null) {
-            pos = clone(pos2);
-          }
-          if (result2 === null) {
-            pos2 = clone(pos);
-            result2 = parse_string();
-            if (result2 !== null) {
-              result2 = (function(offset, line, column, node) {return node._value()})(pos2.offset, pos2.line, pos2.column, result2);
-            }
-            if (result2 === null) {
-              pos = clone(pos2);
-            }
-          }
-          while (result2 !== null) {
-            result1.push(result2);
-            pos2 = clone(pos);
-            if (/^[a-zA-Z0-9:]/.test(input.charAt(pos.offset))) {
-              result3 = input.charAt(pos.offset);
-              advance(pos, 1);
-            } else {
-              result3 = null;
-              if (reportFailures === 0) {
-                matchFailed("[a-zA-Z0-9:]");
-              }
-            }
-            if (result3 !== null) {
-              result2 = [];
-              while (result3 !== null) {
-                result2.push(result3);
-                if (/^[a-zA-Z0-9:]/.test(input.charAt(pos.offset))) {
-                  result3 = input.charAt(pos.offset);
-                  advance(pos, 1);
-                } else {
-                  result3 = null;
-                  if (reportFailures === 0) {
-                    matchFailed("[a-zA-Z0-9:]");
-                  }
-                }
-              }
-            } else {
-              result2 = null;
-            }
-            if (result2 !== null) {
-              result2 = (function(offset, line, column, digits) {return digits.join("")})(pos2.offset, pos2.line, pos2.column, result2);
-            }
-            if (result2 === null) {
-              pos = clone(pos2);
-            }
-            if (result2 === null) {
-              pos2 = clone(pos);
-              result2 = parse_string();
-              if (result2 !== null) {
-                result2 = (function(offset, line, column, node) {return node._value()})(pos2.offset, pos2.line, pos2.column, result2);
-              }
-              if (result2 === null) {
-                pos = clone(pos2);
-              }
-            }
-          }
+          result1 = parse_bareSymbol();
           if (result1 !== null) {
             result0 = [result0, result1];
           } else {
@@ -889,11 +875,51 @@ smalltalk.parser = (function(){
           result0 = null;
           pos = clone(pos1);
         }
+        if (result0 !== null) {
+          result0 = (function(offset, line, column, rest) {return rest})(pos0.offset, pos0.line, pos0.column, result0[1]);
+        }
+        if (result0 === null) {
+          pos = clone(pos0);
+        }
+        
+        cache[cacheKey] = {
+          nextPos: clone(pos),
+          result:  result0
+        };
+        return result0;
+      }
+      
+      function parse_bareSymbol() {
+        var cacheKey = "bareSymbol@" + pos.offset;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = clone(cachedResult.nextPos);
+          return cachedResult.result;
+        }
+        
+        var result0;
+        var pos0, pos1;
+        
+        pos0 = clone(pos);
+        result0 = parse_selector();
+        if (result0 === null) {
+          result0 = parse_binarySelector();
+          if (result0 === null) {
+            pos1 = clone(pos);
+            result0 = parse_string();
+            if (result0 !== null) {
+              result0 = (function(offset, line, column, node) {return node._value()})(pos1.offset, pos1.line, pos1.column, result0);
+            }
+            if (result0 === null) {
+              pos = clone(pos1);
+            }
+          }
+        }
         if (result0 !== null) {
           result0 = (function(offset, line, column, val) {
                               return smalltalk.ValueNode._new()
-                                     ._value_(val.join("").replace(/\"/ig, '"'))
-                          })(pos0.offset, pos0.line, pos0.column, result0[1]);
+                                     ._value_(val)
+                          })(pos0.offset, pos0.line, pos0.column, result0);
         }
         if (result0 === null) {
           pos = clone(pos0);
@@ -1231,8 +1257,8 @@ smalltalk.parser = (function(){
           return cachedResult.result;
         }
         
-        var result0, result1, result2, result3, result4;
-        var pos0, pos1, pos2, pos3;
+        var result0, result1;
+        var pos0, pos1;
         
         pos0 = clone(pos);
         pos1 = clone(pos);
@@ -1246,72 +1272,166 @@ smalltalk.parser = (function(){
           }
         }
         if (result0 !== null) {
-          result1 = parse_ws();
+          result1 = parse_literalArrayRest();
+          if (result1 !== null) {
+            result0 = [result0, result1];
+          } else {
+            result0 = null;
+            pos = clone(pos1);
+          }
+        } else {
+          result0 = null;
+          pos = clone(pos1);
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, line, column, rest) {return rest})(pos0.offset, pos0.line, pos0.column, result0[1]);
+        }
+        if (result0 === null) {
+          pos = clone(pos0);
+        }
+        
+        cache[cacheKey] = {
+          nextPos: clone(pos),
+          result:  result0
+        };
+        return result0;
+      }
+      
+      function parse_bareLiteralArray() {
+        var cacheKey = "bareLiteralArray@" + pos.offset;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = clone(cachedResult.nextPos);
+          return cachedResult.result;
+        }
+        
+        var result0, result1;
+        var pos0, pos1;
+        
+        pos0 = clone(pos);
+        pos1 = clone(pos);
+        if (input.charCodeAt(pos.offset) === 40) {
+          result0 = "(";
+          advance(pos, 1);
+        } else {
+          result0 = null;
+          if (reportFailures === 0) {
+            matchFailed("\"(\"");
+          }
+        }
+        if (result0 !== null) {
+          result1 = parse_literalArrayRest();
           if (result1 !== null) {
-            result2 = [];
+            result0 = [result0, result1];
+          } else {
+            result0 = null;
+            pos = clone(pos1);
+          }
+        } else {
+          result0 = null;
+          pos = clone(pos1);
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, line, column, rest) {return rest})(pos0.offset, pos0.line, pos0.column, result0[1]);
+        }
+        if (result0 === null) {
+          pos = clone(pos0);
+        }
+        
+        cache[cacheKey] = {
+          nextPos: clone(pos),
+          result:  result0
+        };
+        return result0;
+      }
+      
+      function parse_literalArrayRest() {
+        var cacheKey = "literalArrayRest@" + pos.offset;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = clone(cachedResult.nextPos);
+          return cachedResult.result;
+        }
+        
+        var result0, result1, result2, result3;
+        var pos0, pos1, pos2, pos3;
+        
+        pos0 = clone(pos);
+        pos1 = clone(pos);
+        result0 = parse_ws();
+        if (result0 !== null) {
+          result1 = [];
+          pos2 = clone(pos);
+          pos3 = clone(pos);
+          result2 = parse_parseTimeLiteral();
+          if (result2 === null) {
+            result2 = parse_bareLiteralArray();
+            if (result2 === null) {
+              result2 = parse_bareSymbol();
+            }
+          }
+          if (result2 !== null) {
+            result3 = parse_ws();
+            if (result3 !== null) {
+              result2 = [result2, result3];
+            } else {
+              result2 = null;
+              pos = clone(pos3);
+            }
+          } else {
+            result2 = null;
+            pos = clone(pos3);
+          }
+          if (result2 !== null) {
+            result2 = (function(offset, line, column, lit) {return lit._value()})(pos2.offset, pos2.line, pos2.column, result2[0]);
+          }
+          if (result2 === null) {
+            pos = clone(pos2);
+          }
+          while (result2 !== null) {
+            result1.push(result2);
             pos2 = clone(pos);
             pos3 = clone(pos);
-            result3 = parse_literal();
-            if (result3 !== null) {
-              result4 = parse_ws();
-              if (result4 !== null) {
-                result3 = [result3, result4];
+            result2 = parse_parseTimeLiteral();
+            if (result2 === null) {
+              result2 = parse_bareLiteralArray();
+              if (result2 === null) {
+                result2 = parse_bareSymbol();
+              }
+            }
+            if (result2 !== null) {
+              result3 = parse_ws();
+              if (result3 !== null) {
+                result2 = [result2, result3];
               } else {
-                result3 = null;
+                result2 = null;
                 pos = clone(pos3);
               }
             } else {
-              result3 = null;
+              result2 = null;
               pos = clone(pos3);
             }
-            if (result3 !== null) {
-              result3 = (function(offset, line, column, lit) {return lit._value()})(pos2.offset, pos2.line, pos2.column, result3[0]);
+            if (result2 !== null) {
+              result2 = (function(offset, line, column, lit) {return lit._value()})(pos2.offset, pos2.line, pos2.column, result2[0]);
             }
-            if (result3 === null) {
+            if (result2 === null) {
               pos = clone(pos2);
             }
-            while (result3 !== null) {
-              result2.push(result3);
-              pos2 = clone(pos);
-              pos3 = clone(pos);
-              result3 = parse_literal();
-              if (result3 !== null) {
-                result4 = parse_ws();
-                if (result4 !== null) {
-                  result3 = [result3, result4];
-                } else {
-                  result3 = null;
-                  pos = clone(pos3);
-                }
+          }
+          if (result1 !== null) {
+            result2 = parse_ws();
+            if (result2 !== null) {
+              if (input.charCodeAt(pos.offset) === 41) {
+                result3 = ")";
+                advance(pos, 1);
               } else {
                 result3 = null;
-                pos = clone(pos3);
-              }
-              if (result3 !== null) {
-                result3 = (function(offset, line, column, lit) {return lit._value()})(pos2.offset, pos2.line, pos2.column, result3[0]);
-              }
-              if (result3 === null) {
-                pos = clone(pos2);
+                if (reportFailures === 0) {
+                  matchFailed("\")\"");
+                }
               }
-            }
-            if (result2 !== null) {
-              result3 = parse_ws();
               if (result3 !== null) {
-                if (input.charCodeAt(pos.offset) === 41) {
-                  result4 = ")";
-                  advance(pos, 1);
-                } else {
-                  result4 = null;
-                  if (reportFailures === 0) {
-                    matchFailed("\")\"");
-                  }
-                }
-                if (result4 !== null) {
-                  result0 = [result0, result1, result2, result3, result4];
-                } else {
-                  result0 = null;
-                  pos = clone(pos1);
-                }
+                result0 = [result0, result1, result2, result3];
               } else {
                 result0 = null;
                 pos = clone(pos1);
@@ -1332,7 +1452,7 @@ smalltalk.parser = (function(){
           result0 = (function(offset, line, column, lits) {
                              return smalltalk.ValueNode._new()
                                     ._value_(lits)
-                         })(pos0.offset, pos0.line, pos0.column, result0[2]);
+                         })(pos0.offset, pos0.line, pos0.column, result0[1]);
         }
         if (result0 === null) {
           pos = clone(pos0);
@@ -1597,8 +1717,8 @@ smalltalk.parser = (function(){
         return result0;
       }
       
-      function parse_literal() {
-        var cacheKey = "literal@" + pos.offset;
+      function parse_parseTimeLiteral() {
+        var cacheKey = "parseTimeLiteral@" + pos.offset;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = clone(cachedResult.nextPos);
@@ -1613,18 +1733,9 @@ smalltalk.parser = (function(){
           if (result0 === null) {
             result0 = parse_literalArray();
             if (result0 === null) {
-              result0 = parse_dynamicDictionary();
+              result0 = parse_string();
               if (result0 === null) {
-                result0 = parse_dynamicArray();
-                if (result0 === null) {
-                  result0 = parse_string();
-                  if (result0 === null) {
-                    result0 = parse_symbol();
-                    if (result0 === null) {
-                      result0 = parse_block();
-                    }
-                  }
-                }
+                result0 = parse_symbol();
               }
             }
           }
@@ -1637,6 +1748,53 @@ smalltalk.parser = (function(){
         return result0;
       }
       
+      function parse_runtimeLiteral() {
+        var cacheKey = "runtimeLiteral@" + pos.offset;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = clone(cachedResult.nextPos);
+          return cachedResult.result;
+        }
+        
+        var result0;
+        
+        result0 = parse_dynamicDictionary();
+        if (result0 === null) {
+          result0 = parse_dynamicArray();
+          if (result0 === null) {
+            result0 = parse_block();
+          }
+        }
+        
+        cache[cacheKey] = {
+          nextPos: clone(pos),
+          result:  result0
+        };
+        return result0;
+      }
+      
+      function parse_literal() {
+        var cacheKey = "literal@" + pos.offset;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = clone(cachedResult.nextPos);
+          return cachedResult.result;
+        }
+        
+        var result0;
+        
+        result0 = parse_runtimeLiteral();
+        if (result0 === null) {
+          result0 = parse_parseTimeLiteral();
+        }
+        
+        cache[cacheKey] = {
+          nextPos: clone(pos),
+          result:  result0
+        };
+        return result0;
+      }
+      
       function parse_variable() {
         var cacheKey = "variable@" + pos.offset;
         var cachedResult = cache[cacheKey];

+ 10 - 6
js/parser.pegjs

@@ -6,18 +6,18 @@ ws             = (separator / comments)*
 identifier     = first:[a-zA-Z] others:[a-zA-Z0-9]* {return first + others.join("")}
 varIdentifier  = first:[a-z] others:[a-zA-Z0-9]* {return first + others.join("")}
 keyword        = first:identifier last:[:] {return first + last}
+selector      = first:[a-zA-Z] others:[a-zA-Z0-9\:]* {return first + others.join("")}
 className      = first:[A-Z] others:[a-zA-Z0-9]* {return first + others.join("")}
 string         = ['] val:(("''" {return "'"} / [^'])*) ['] {
                      return smalltalk.ValueNode._new()
                             ._value_(val.join("").replace(/\"/ig, '"'))
                  }
 
-symbol         = "#"val:(
-                         digits:[a-zA-Z0-9\:]+ {return digits.join("")}
-                       / node:string {return node._value()})*
+symbol         = "#" rest:bareSymbol {return rest}
+bareSymbol         = val:(selector / binarySelector / node:string {return node._value()})
                   {
                       return smalltalk.ValueNode._new()
-                             ._value_(val.join("").replace(/\"/ig, '"'))
+                             ._value_(val)
                   }
 number         = n:(hex / float / integer) {
                      return smalltalk.ValueNode._new()
@@ -26,7 +26,9 @@ number         = n:(hex / float / integer) {
 hex            = neg:[-]? "16r" num:[0-9a-fA-F]+ {return parseInt((neg + num.join("")), 16)}
 float          = neg:[-]?int:[0-9]+ "." dec:[0-9]+ {return parseFloat((neg + int.join("") + "." + dec.join("")), 10)}
 integer        = neg:[-]?digits:[0-9]+ {return (parseInt(neg+digits.join(""), 10))}
-literalArray   = "#(" ws lits:(lit:literal ws {return lit._value()})* ws ")" {
+literalArray   = "#(" rest:literalArrayRest {return rest}
+bareLiteralArray   = "(" rest:literalArrayRest {return rest}
+literalArrayRest   = ws lits:(lit:(parseTimeLiteral / bareLiteralArray / bareSymbol) ws {return lit._value()})* ws ")" {
                      return smalltalk.ValueNode._new()
                             ._value_(lits)
                  }
@@ -45,7 +47,9 @@ pseudoVariable = val:(
                        return smalltalk.ValueNode._new()
                               ._value_(val)
                    }
-literal        = pseudoVariable / number / literalArray / dynamicDictionary / dynamicArray / string / symbol / block
+parseTimeLiteral        = pseudoVariable / number / literalArray / string / symbol
+runtimeLiteral        = dynamicDictionary / dynamicArray / block
+literal        = runtimeLiteral / parseTimeLiteral
 
 
 variable       = identifier:varIdentifier {