Fixing bug whereby parser would fail when array entry does not have a trailing comma

In our testing, we've hit projects where trailing commas are not present with array entries.
diff --git a/lib/parser/pbxproj.js b/lib/parser/pbxproj.js
index 545cbe4..f574479 100644
--- a/lib/parser/pbxproj.js
+++ b/lib/parser/pbxproj.js
@@ -1,2702 +1,1843 @@
-module.exports = (function(){
-  /* Generated by PEG.js 0.6.2 (http://pegjs.majda.cz/). */
-  
-  var result = {
-    /*
-     * Parses the input with a generated parser. If the parsing is successfull,
-     * returns a value explicitly or implicitly specified by the grammar from
-     * which the parser was generated (see |PEG.buildParser|). If the parsing is
-     * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
-     */
-    parse: function(input, startRule) {
-      var parseFunctions = {
-        "Alpha": parse_Alpha,
-        "Array": parse_Array,
-        "ArrayBody": parse_ArrayBody,
-        "ArrayEntry": parse_ArrayEntry,
-        "Assignment": parse_Assignment,
-        "AssignmentList": parse_AssignmentList,
-        "Char": parse_Char,
-        "CommentedArrayEntry": parse_CommentedArrayEntry,
-        "CommentedAssignment": parse_CommentedAssignment,
-        "CommentedIdentifier": parse_CommentedIdentifier,
-        "CommentedValue": parse_CommentedValue,
-        "DecimalValue": parse_DecimalValue,
-        "DelimitedSection": parse_DelimitedSection,
-        "DelimitedSectionBegin": parse_DelimitedSectionBegin,
-        "DelimitedSectionEnd": parse_DelimitedSectionEnd,
-        "Digit": parse_Digit,
-        "DoubleQuote": parse_DoubleQuote,
-        "EmptyArray": parse_EmptyArray,
-        "EmptyBody": parse_EmptyBody,
-        "EscapedQuote": parse_EscapedQuote,
-        "Identifier": parse_Identifier,
-        "InlineComment": parse_InlineComment,
-        "InlineCommentClose": parse_InlineCommentClose,
-        "InlineCommentOpen": parse_InlineCommentOpen,
-        "IntegerValue": parse_IntegerValue,
-        "LineTerminator": parse_LineTerminator,
-        "LiteralChar": parse_LiteralChar,
-        "LiteralString": parse_LiteralString,
-        "NewLine": parse_NewLine,
-        "NonLine": parse_NonLine,
-        "NonQuote": parse_NonQuote,
-        "NonTerminator": parse_NonTerminator,
-        "NumberValue": parse_NumberValue,
-        "Object": parse_Object,
-        "OneLineString": parse_OneLineString,
-        "Project": parse_Project,
-        "QuotedBody": parse_QuotedBody,
-        "QuotedString": parse_QuotedString,
-        "SimpleArrayEntry": parse_SimpleArrayEntry,
-        "SimpleAssignment": parse_SimpleAssignment,
-        "SingleLineComment": parse_SingleLineComment,
-        "StringValue": parse_StringValue,
-        "Value": parse_Value,
-        "_": parse__,
-        "whitespace": parse_whitespace
-      };
-      
-      if (startRule !== undefined) {
-        if (parseFunctions[startRule] === undefined) {
-          throw new Error("Invalid rule name: " + quote(startRule) + ".");
+module.exports = (function() {
+  /*
+   * Generated by PEG.js 0.8.0.
+   *
+   * http://pegjs.majda.cz/
+   */
+
+  function peg$subclass(child, parent) {
+    function ctor() { this.constructor = child; }
+    ctor.prototype = parent.prototype;
+    child.prototype = new ctor();
+  }
+
+  function SyntaxError(message, expected, found, offset, line, column) {
+    this.message  = message;
+    this.expected = expected;
+    this.found    = found;
+    this.offset   = offset;
+    this.line     = line;
+    this.column   = column;
+
+    this.name     = "SyntaxError";
+  }
+
+  peg$subclass(SyntaxError, Error);
+
+  function parse(input) {
+    var options = arguments.length > 1 ? arguments[1] : {},
+
+        peg$FAILED = {},
+
+        peg$startRuleFunctions = { Project: peg$parseProject },
+        peg$startRuleFunction  = peg$parseProject,
+
+        peg$c0 = peg$FAILED,
+        peg$c1 = null,
+        peg$c2 = function(headComment, obj) {
+                var proj = Object.create(null)
+                proj.project = obj
+
+                if (headComment) {
+                    proj.headComment = headComment
+                }
+
+                return proj;
+            },
+        peg$c3 = "{",
+        peg$c4 = { type: "literal", value: "{", description: "\"{\"" },
+        peg$c5 = "}",
+        peg$c6 = { type: "literal", value: "}", description: "\"}\"" },
+        peg$c7 = function(obj) { return obj },
+        peg$c8 = function() { return Object.create(null) },
+        peg$c9 = [],
+        peg$c10 = function(head, tail) { 
+              if (tail) return merge(head,tail)
+              else return head
+            },
+        peg$c11 = function(head, tail) {
+              if (tail) return merge(head,tail)
+              else return head
+            },
+        peg$c12 = "=",
+        peg$c13 = { type: "literal", value: "=", description: "\"=\"" },
+        peg$c14 = ";",
+        peg$c15 = { type: "literal", value: ";", description: "\";\"" },
+        peg$c16 = function(id, val) { 
+              var result = Object.create(null);
+              result[id] = val
+              return result
+            },
+        peg$c17 = function(commentedId, val) {
+                var result = Object.create(null),
+                    commentKey = commentedId.id + '_comment';
+
+                result[commentedId.id] = val;
+                result[commentKey] = commentedId[commentKey];
+                return result;
+
+            },
+        peg$c18 = function(id, commentedVal) {
+                var result = Object.create(null);
+                result[id] = commentedVal.value;
+                result[id + "_comment"] = commentedVal.comment;
+                return result;
+            },
+        peg$c19 = function(id, comment) {
+                var result = Object.create(null);
+                result.id = id;
+                result[id + "_comment"] = comment.trim();
+                return result
+            },
+        peg$c20 = function(literal, comment) {
+                var result = Object.create(null)
+                result.comment = comment.trim();
+                result.value = literal.trim();
+                return result;
+            },
+        peg$c21 = /^[^*]/,
+        peg$c22 = { type: "class", value: "[^*]", description: "[^*]" },
+        peg$c23 = function(body) { return body.join('') },
+        peg$c24 = "/*",
+        peg$c25 = { type: "literal", value: "/*", description: "\"/*\"" },
+        peg$c26 = "*/",
+        peg$c27 = { type: "literal", value: "*/", description: "\"*/\"" },
+        peg$c28 = function(begin, fields) {
+                var section = Object.create(null);
+                section[begin.name] = fields
+
+                return section
+            },
+        peg$c29 = "/* Begin ",
+        peg$c30 = { type: "literal", value: "/* Begin ", description: "\"/* Begin \"" },
+        peg$c31 = " section */",
+        peg$c32 = { type: "literal", value: " section */", description: "\" section */\"" },
+        peg$c33 = function(sectionName) { return { name: sectionName } },
+        peg$c34 = "/* End ",
+        peg$c35 = { type: "literal", value: "/* End ", description: "\"/* End \"" },
+        peg$c36 = "(",
+        peg$c37 = { type: "literal", value: "(", description: "\"(\"" },
+        peg$c38 = ")",
+        peg$c39 = { type: "literal", value: ")", description: "\")\"" },
+        peg$c40 = function(arr) { return arr },
+        peg$c41 = function() { return [] },
+        peg$c42 = function(head, tail) {
+                if (tail) {
+                    tail.unshift(head);
+                    return tail;
+                } else {
+                    return [head];
+                }
+            },
+        peg$c43 = function(val) { return val },
+        peg$c44 = function(val, comment) {
+                var result = Object.create(null);
+                result.value = val.trim();
+                result.comment = comment.trim();
+                return result;
+            },
+        peg$c45 = ",",
+        peg$c46 = { type: "literal", value: ",", description: "\",\"" },
+        peg$c47 = void 0,
+        peg$c48 = /^[A-Za-z0-9_.]/,
+        peg$c49 = { type: "class", value: "[A-Za-z0-9_.]", description: "[A-Za-z0-9_.]" },
+        peg$c50 = function(id) { return id.join('') },
+        peg$c51 = ".",
+        peg$c52 = { type: "literal", value: ".", description: "\".\"" },
+        peg$c53 = function(decimal) { 
+                // store decimals as strings
+                // as JS doesn't differentiate bw strings and numbers
+                return decimal.join('')
+            },
+        peg$c54 = function(number) { return parseInt(number.join(''), 10) },
+        peg$c55 = function(str) { return '"' + str + '"' },
+        peg$c56 = function(str) { return str.join('') },
+        peg$c57 = { type: "any", description: "any character" },
+        peg$c58 = function(char) { return char },
+        peg$c59 = "\\",
+        peg$c60 = { type: "literal", value: "\\", description: "\"\\\\\"" },
+        peg$c61 = function() { return '\\"' },
+        peg$c62 = function(literal) { return literal.join('') },
+        peg$c63 = /^[^;,\n]/,
+        peg$c64 = { type: "class", value: "[^;,\\n]", description: "[^;,\\n]" },
+        peg$c65 = "//",
+        peg$c66 = { type: "literal", value: "//", description: "\"//\"" },
+        peg$c67 = function(contents) { return contents },
+        peg$c68 = function(contents) { return contents.join('') },
+        peg$c69 = /^[0-9]/,
+        peg$c70 = { type: "class", value: "[0-9]", description: "[0-9]" },
+        peg$c71 = /^[A-Za-z]/,
+        peg$c72 = { type: "class", value: "[A-Za-z]", description: "[A-Za-z]" },
+        peg$c73 = "\"",
+        peg$c74 = { type: "literal", value: "\"", description: "\"\\\"\"" },
+        peg$c75 = { type: "other", description: "whitespace" },
+        peg$c76 = /^[\t ]/,
+        peg$c77 = { type: "class", value: "[\\t ]", description: "[\\t ]" },
+        peg$c78 = /^[\n\r]/,
+        peg$c79 = { type: "class", value: "[\\n\\r]", description: "[\\n\\r]" },
+
+        peg$currPos          = 0,
+        peg$reportedPos      = 0,
+        peg$cachedPos        = 0,
+        peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
+        peg$maxFailPos       = 0,
+        peg$maxFailExpected  = [],
+        peg$silentFails      = 0,
+
+        peg$result;
+
+    if ("startRule" in options) {
+      if (!(options.startRule in peg$startRuleFunctions)) {
+        throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
+      }
+
+      peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
+    }
+
+    function text() {
+      return input.substring(peg$reportedPos, peg$currPos);
+    }
+
+    function offset() {
+      return peg$reportedPos;
+    }
+
+    function line() {
+      return peg$computePosDetails(peg$reportedPos).line;
+    }
+
+    function column() {
+      return peg$computePosDetails(peg$reportedPos).column;
+    }
+
+    function expected(description) {
+      throw peg$buildException(
+        null,
+        [{ type: "other", description: description }],
+        peg$reportedPos
+      );
+    }
+
+    function error(message) {
+      throw peg$buildException(message, null, peg$reportedPos);
+    }
+
+    function peg$computePosDetails(pos) {
+      function advance(details, startPos, endPos) {
+        var p, ch;
+
+        for (p = startPos; p < endPos; p++) {
+          ch = input.charAt(p);
+          if (ch === "\n") {
+            if (!details.seenCR) { details.line++; }
+            details.column = 1;
+            details.seenCR = false;
+          } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
+            details.line++;
+            details.column = 1;
+            details.seenCR = true;
+          } else {
+            details.column++;
+            details.seenCR = false;
+          }
+        }
+      }
+
+      if (peg$cachedPos !== pos) {
+        if (peg$cachedPos > pos) {
+          peg$cachedPos = 0;
+          peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
+        }
+        advance(peg$cachedPosDetails, peg$cachedPos, pos);
+        peg$cachedPos = pos;
+      }
+
+      return peg$cachedPosDetails;
+    }
+
+    function peg$fail(expected) {
+      if (peg$currPos < peg$maxFailPos) { return; }
+
+      if (peg$currPos > peg$maxFailPos) {
+        peg$maxFailPos = peg$currPos;
+        peg$maxFailExpected = [];
+      }
+
+      peg$maxFailExpected.push(expected);
+    }
+
+    function peg$buildException(message, expected, pos) {
+      function cleanupExpected(expected) {
+        var i = 1;
+
+        expected.sort(function(a, b) {
+          if (a.description < b.description) {
+            return -1;
+          } else if (a.description > b.description) {
+            return 1;
+          } else {
+            return 0;
+          }
+        });
+
+        while (i < expected.length) {
+          if (expected[i - 1] === expected[i]) {
+            expected.splice(i, 1);
+          } else {
+            i++;
+          }
+        }
+      }
+
+      function buildMessage(expected, found) {
+        function stringEscape(s) {
+          function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
+
+          return s
+            .replace(/\\/g,   '\\\\')
+            .replace(/"/g,    '\\"')
+            .replace(/\x08/g, '\\b')
+            .replace(/\t/g,   '\\t')
+            .replace(/\n/g,   '\\n')
+            .replace(/\f/g,   '\\f')
+            .replace(/\r/g,   '\\r')
+            .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
+            .replace(/[\x10-\x1F\x80-\xFF]/g,    function(ch) { return '\\x'  + hex(ch); })
+            .replace(/[\u0180-\u0FFF]/g,         function(ch) { return '\\u0' + hex(ch); })
+            .replace(/[\u1080-\uFFFF]/g,         function(ch) { return '\\u'  + hex(ch); });
+        }
+
+        var expectedDescs = new Array(expected.length),
+            expectedDesc, foundDesc, i;
+
+        for (i = 0; i < expected.length; i++) {
+          expectedDescs[i] = expected[i].description;
+        }
+
+        expectedDesc = expected.length > 1
+          ? expectedDescs.slice(0, -1).join(", ")
+              + " or "
+              + expectedDescs[expected.length - 1]
+          : expectedDescs[0];
+
+        foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
+
+        return "Expected " + expectedDesc + " but " + foundDesc + " found.";
+      }
+
+      var posDetails = peg$computePosDetails(pos),
+          found      = pos < input.length ? input.charAt(pos) : null;
+
+      if (expected !== null) {
+        cleanupExpected(expected);
+      }
+
+      return new SyntaxError(
+        message !== null ? message : buildMessage(expected, found),
+        expected,
+        found,
+        pos,
+        posDetails.line,
+        posDetails.column
+      );
+    }
+
+    function peg$parseProject() {
+      var s0, s1, s2, s3, s4, s5, s6;
+
+      s0 = peg$currPos;
+      s1 = peg$parseSingleLineComment();
+      if (s1 === peg$FAILED) {
+        s1 = peg$c1;
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseInlineComment();
+        if (s2 === peg$FAILED) {
+          s2 = peg$c1;
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parse_();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseObject();
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parseNewLine();
+              if (s5 !== peg$FAILED) {
+                s6 = peg$parse_();
+                if (s6 !== peg$FAILED) {
+                  peg$reportedPos = s0;
+                  s1 = peg$c2(s1, s4);
+                  s0 = s1;
+                } else {
+                  peg$currPos = s0;
+                  s0 = peg$c0;
+                }
+              } else {
+                peg$currPos = s0;
+                s0 = peg$c0;
+              }
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c0;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
       } else {
-        startRule = "Project";
+        peg$currPos = s0;
+        s0 = peg$c0;
       }
-      
-      var pos = 0;
-      var reportMatchFailures = true;
-      var rightmostMatchFailuresPos = 0;
-      var rightmostMatchFailuresExpected = [];
-      var cache = {};
-      
-      function padLeft(input, padding, length) {
-        var result = input;
-        
-        var padLength = length - input.length;
-        for (var i = 0; i < padLength; i++) {
-          result = padding + result;
+
+      return s0;
+    }
+
+    function peg$parseObject() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      if (input.charCodeAt(peg$currPos) === 123) {
+        s1 = peg$c3;
+        peg$currPos++;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c4); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseAssignmentList();
+        if (s2 === peg$FAILED) {
+          s2 = peg$parseEmptyBody();
         }
-        
-        return result;
-      }
-      
-      function escape(ch) {
-        var charCode = ch.charCodeAt(0);
-        
-        if (charCode <= 0xFF) {
-          var escapeChar = 'x';
-          var length = 2;
+        if (s2 !== peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 125) {
+            s3 = peg$c5;
+            peg$currPos++;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c6); }
+          }
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c7(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
         } else {
-          var escapeChar = 'u';
-          var length = 4;
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
       }
-      
-      function quote(s) {
-        /*
-         * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
-         * string literal except for the closing quote character, backslash,
-         * carriage return, line separator, paragraph separator, and line feed.
-         * Any character may appear in the form of an escape sequence.
-         */
-        return '"' + s
-          .replace(/\\/g, '\\\\')            // backslash
-          .replace(/"/g, '\\"')              // closing quote character
-          .replace(/\r/g, '\\r')             // carriage return
-          .replace(/\n/g, '\\n')             // line feed
-          .replace(/[\x80-\uFFFF]/g, escape) // non-ASCII characters
-          + '"';
+
+      return s0;
+    }
+
+    function peg$parseEmptyBody() {
+      var s0, s1;
+
+      s0 = peg$currPos;
+      s1 = peg$parse_();
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c8();
       }
-      
-      function matchFailed(failure) {
-        if (pos < rightmostMatchFailuresPos) {
-          return;
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseAssignmentList() {
+      var s0, s1, s2, s3, s4, s5;
+
+      s0 = peg$currPos;
+      s1 = peg$parse_();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseAssignment();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parse_();
+          if (s3 !== peg$FAILED) {
+            s4 = [];
+            s5 = peg$parseAssignmentList();
+            while (s5 !== peg$FAILED) {
+              s4.push(s5);
+              s5 = peg$parseAssignmentList();
+            }
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parse_();
+              if (s5 !== peg$FAILED) {
+                peg$reportedPos = s0;
+                s1 = peg$c10(s2, s4);
+                s0 = s1;
+              } else {
+                peg$currPos = s0;
+                s0 = peg$c0;
+              }
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c0;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        if (pos > rightmostMatchFailuresPos) {
-          rightmostMatchFailuresPos = pos;
-          rightmostMatchFailuresExpected = [];
-        }
-        
-        rightmostMatchFailuresExpected.push(failure);
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
       }
-      
-      function parse_Project() {
-        var cacheKey = 'Project@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = peg$parse_();
+        if (s1 !== peg$FAILED) {
+          s2 = peg$parseDelimitedSection();
+          if (s2 !== peg$FAILED) {
+            s3 = peg$parse_();
+            if (s3 !== peg$FAILED) {
+              s4 = [];
+              s5 = peg$parseAssignmentList();
+              while (s5 !== peg$FAILED) {
+                s4.push(s5);
+                s5 = peg$parseAssignmentList();
+              }
+              if (s4 !== peg$FAILED) {
+                peg$reportedPos = s0;
+                s1 = peg$c11(s2, s4);
+                s0 = s1;
+              } else {
+                peg$currPos = s0;
+                s0 = peg$c0;
+              }
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c0;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result10 = parse_SingleLineComment();
-        var result3 = result10 !== null ? result10 : '';
-        if (result3 !== null) {
-          var result9 = parse_InlineComment();
-          var result4 = result9 !== null ? result9 : '';
-          if (result4 !== null) {
-            var result5 = parse__();
-            if (result5 !== null) {
-              var result6 = parse_Object();
-              if (result6 !== null) {
-                var result7 = parse_NewLine();
-                if (result7 !== null) {
-                  var result8 = parse__();
-                  if (result8 !== null) {
-                    var result1 = [result3, result4, result5, result6, result7, result8];
+      }
+
+      return s0;
+    }
+
+    function peg$parseAssignment() {
+      var s0;
+
+      s0 = peg$parseSimpleAssignment();
+      if (s0 === peg$FAILED) {
+        s0 = peg$parseCommentedAssignment();
+      }
+
+      return s0;
+    }
+
+    function peg$parseSimpleAssignment() {
+      var s0, s1, s2, s3, s4, s5, s6;
+
+      s0 = peg$currPos;
+      s1 = peg$parseIdentifier();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parse_();
+        if (s2 !== peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 61) {
+            s3 = peg$c12;
+            peg$currPos++;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c13); }
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parse_();
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parseValue();
+              if (s5 !== peg$FAILED) {
+                if (input.charCodeAt(peg$currPos) === 59) {
+                  s6 = peg$c14;
+                  peg$currPos++;
+                } else {
+                  s6 = peg$FAILED;
+                  if (peg$silentFails === 0) { peg$fail(peg$c15); }
+                }
+                if (s6 !== peg$FAILED) {
+                  peg$reportedPos = s0;
+                  s1 = peg$c16(s1, s5);
+                  s0 = s1;
+                } else {
+                  peg$currPos = s0;
+                  s0 = peg$c0;
+                }
+              } else {
+                peg$currPos = s0;
+                s0 = peg$c0;
+              }
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c0;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseCommentedAssignment() {
+      var s0, s1, s2, s3, s4, s5, s6;
+
+      s0 = peg$currPos;
+      s1 = peg$parseCommentedIdentifier();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parse_();
+        if (s2 !== peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 61) {
+            s3 = peg$c12;
+            peg$currPos++;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c13); }
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parse_();
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parseValue();
+              if (s5 !== peg$FAILED) {
+                if (input.charCodeAt(peg$currPos) === 59) {
+                  s6 = peg$c14;
+                  peg$currPos++;
+                } else {
+                  s6 = peg$FAILED;
+                  if (peg$silentFails === 0) { peg$fail(peg$c15); }
+                }
+                if (s6 !== peg$FAILED) {
+                  peg$reportedPos = s0;
+                  s1 = peg$c17(s1, s5);
+                  s0 = s1;
+                } else {
+                  peg$currPos = s0;
+                  s0 = peg$c0;
+                }
+              } else {
+                peg$currPos = s0;
+                s0 = peg$c0;
+              }
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c0;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = peg$parseIdentifier();
+        if (s1 !== peg$FAILED) {
+          s2 = peg$parse_();
+          if (s2 !== peg$FAILED) {
+            if (input.charCodeAt(peg$currPos) === 61) {
+              s3 = peg$c12;
+              peg$currPos++;
+            } else {
+              s3 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c13); }
+            }
+            if (s3 !== peg$FAILED) {
+              s4 = peg$parse_();
+              if (s4 !== peg$FAILED) {
+                s5 = peg$parseCommentedValue();
+                if (s5 !== peg$FAILED) {
+                  if (input.charCodeAt(peg$currPos) === 59) {
+                    s6 = peg$c14;
+                    peg$currPos++;
                   } else {
-                    var result1 = null;
-                    pos = savedPos1;
+                    s6 = peg$FAILED;
+                    if (peg$silentFails === 0) { peg$fail(peg$c15); }
                   }
-                } else {
-                  var result1 = null;
-                  pos = savedPos1;
-                }
-              } else {
-                var result1 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(headComment, obj) {
-                  var proj = Object.create(null)
-                  proj.project = obj
-          
-                  if (headComment) {
-                      proj.headComment = headComment
-                  }
-          
-                  return proj;
-              })(result1[0], result1[3])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_Object() {
-        var cacheKey = 'Object@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        if (input.substr(pos, 1) === "{") {
-          var result3 = "{";
-          pos += 1;
-        } else {
-          var result3 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"{\"");
-          }
-        }
-        if (result3 !== null) {
-          var result7 = parse_AssignmentList();
-          if (result7 !== null) {
-            var result4 = result7;
-          } else {
-            var result6 = parse_EmptyBody();
-            if (result6 !== null) {
-              var result4 = result6;
-            } else {
-              var result4 = null;;
-            };
-          }
-          if (result4 !== null) {
-            if (input.substr(pos, 1) === "}") {
-              var result5 = "}";
-              pos += 1;
-            } else {
-              var result5 = null;
-              if (reportMatchFailures) {
-                matchFailed("\"}\"");
-              }
-            }
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(obj) { return obj })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_EmptyBody() {
-        var cacheKey = 'EmptyBody@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var result1 = parse__();
-        var result2 = result1 !== null
-          ? (function() { return Object.create(null) })()
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_AssignmentList() {
-        var cacheKey = 'AssignmentList@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos2 = pos;
-        var savedPos3 = pos;
-        var result12 = parse__();
-        if (result12 !== null) {
-          var result13 = parse_Assignment();
-          if (result13 !== null) {
-            var result14 = parse__();
-            if (result14 !== null) {
-              var result15 = [];
-              var result17 = parse_AssignmentList();
-              while (result17 !== null) {
-                result15.push(result17);
-                var result17 = parse_AssignmentList();
-              }
-              if (result15 !== null) {
-                var result16 = parse__();
-                if (result16 !== null) {
-                  var result10 = [result12, result13, result14, result15, result16];
-                } else {
-                  var result10 = null;
-                  pos = savedPos3;
-                }
-              } else {
-                var result10 = null;
-                pos = savedPos3;
-              }
-            } else {
-              var result10 = null;
-              pos = savedPos3;
-            }
-          } else {
-            var result10 = null;
-            pos = savedPos3;
-          }
-        } else {
-          var result10 = null;
-          pos = savedPos3;
-        }
-        var result11 = result10 !== null
-          ? (function(head, tail) { 
-                if (tail) return merge(head,tail)
-                else return head
-              })(result10[1], result10[3])
-          : null;
-        if (result11 !== null) {
-          var result9 = result11;
-        } else {
-          var result9 = null;
-          pos = savedPos2;
-        }
-        if (result9 !== null) {
-          var result0 = result9;
-        } else {
-          var savedPos0 = pos;
-          var savedPos1 = pos;
-          var result4 = parse__();
-          if (result4 !== null) {
-            var result5 = parse_DelimitedSection();
-            if (result5 !== null) {
-              var result6 = parse__();
-              if (result6 !== null) {
-                var result7 = [];
-                var result8 = parse_AssignmentList();
-                while (result8 !== null) {
-                  result7.push(result8);
-                  var result8 = parse_AssignmentList();
-                }
-                if (result7 !== null) {
-                  var result2 = [result4, result5, result6, result7];
-                } else {
-                  var result2 = null;
-                  pos = savedPos1;
-                }
-              } else {
-                var result2 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result2 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result2 = null;
-            pos = savedPos1;
-          }
-          var result3 = result2 !== null
-            ? (function(head, tail) {
-                  if (tail) return merge(head,tail)
-                  else return head
-                })(result2[1], result2[3])
-            : null;
-          if (result3 !== null) {
-            var result1 = result3;
-          } else {
-            var result1 = null;
-            pos = savedPos0;
-          }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_Assignment() {
-        var cacheKey = 'Assignment@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result2 = parse_SimpleAssignment();
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result1 = parse_CommentedAssignment();
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_SimpleAssignment() {
-        var cacheKey = 'SimpleAssignment@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_Identifier();
-        if (result3 !== null) {
-          var result4 = parse__();
-          if (result4 !== null) {
-            if (input.substr(pos, 1) === "=") {
-              var result5 = "=";
-              pos += 1;
-            } else {
-              var result5 = null;
-              if (reportMatchFailures) {
-                matchFailed("\"=\"");
-              }
-            }
-            if (result5 !== null) {
-              var result6 = parse__();
-              if (result6 !== null) {
-                var result7 = parse_Value();
-                if (result7 !== null) {
-                  if (input.substr(pos, 1) === ";") {
-                    var result8 = ";";
-                    pos += 1;
+                  if (s6 !== peg$FAILED) {
+                    peg$reportedPos = s0;
+                    s1 = peg$c18(s1, s5);
+                    s0 = s1;
                   } else {
-                    var result8 = null;
-                    if (reportMatchFailures) {
-                      matchFailed("\";\"");
-                    }
-                  }
-                  if (result8 !== null) {
-                    var result1 = [result3, result4, result5, result6, result7, result8];
-                  } else {
-                    var result1 = null;
-                    pos = savedPos1;
+                    peg$currPos = s0;
+                    s0 = peg$c0;
                   }
                 } else {
-                  var result1 = null;
-                  pos = savedPos1;
+                  peg$currPos = s0;
+                  s0 = peg$c0;
                 }
               } else {
-                var result1 = null;
-                pos = savedPos1;
+                peg$currPos = s0;
+                s0 = peg$c0;
               }
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              peg$currPos = s0;
+              s0 = peg$c0;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            peg$currPos = s0;
+            s0 = peg$c0;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        var result2 = result1 !== null
-          ? (function(id, val) { 
-                var result = Object.create(null);
-                result[id] = val
-                return result
-              })(result1[0], result1[4])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
       }
-      
-      function parse_CommentedAssignment() {
-        var cacheKey = 'CommentedAssignment@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
+
+      return s0;
+    }
+
+    function peg$parseCommentedIdentifier() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      s1 = peg$parseIdentifier();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parse_();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseInlineComment();
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c19(s1, s3);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        
-        var savedPos2 = pos;
-        var savedPos3 = pos;
-        var result13 = parse_CommentedIdentifier();
-        if (result13 !== null) {
-          var result14 = parse__();
-          if (result14 !== null) {
-            if (input.substr(pos, 1) === "=") {
-              var result15 = "=";
-              pos += 1;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseCommentedValue() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      s1 = peg$parseValue();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parse_();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseInlineComment();
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c20(s1, s3);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseInlineComment() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      s1 = peg$parseInlineCommentOpen();
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        if (peg$c21.test(input.charAt(peg$currPos))) {
+          s3 = input.charAt(peg$currPos);
+          peg$currPos++;
+        } else {
+          s3 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c22); }
+        }
+        if (s3 !== peg$FAILED) {
+          while (s3 !== peg$FAILED) {
+            s2.push(s3);
+            if (peg$c21.test(input.charAt(peg$currPos))) {
+              s3 = input.charAt(peg$currPos);
+              peg$currPos++;
             } else {
-              var result15 = null;
-              if (reportMatchFailures) {
-                matchFailed("\"=\"");
-              }
+              s3 = peg$FAILED;
+              if (peg$silentFails === 0) { peg$fail(peg$c22); }
             }
-            if (result15 !== null) {
-              var result16 = parse__();
-              if (result16 !== null) {
-                var result17 = parse_Value();
-                if (result17 !== null) {
-                  if (input.substr(pos, 1) === ";") {
-                    var result18 = ";";
-                    pos += 1;
-                  } else {
-                    var result18 = null;
-                    if (reportMatchFailures) {
-                      matchFailed("\";\"");
-                    }
-                  }
-                  if (result18 !== null) {
-                    var result11 = [result13, result14, result15, result16, result17, result18];
-                  } else {
-                    var result11 = null;
-                    pos = savedPos3;
-                  }
-                } else {
-                  var result11 = null;
-                  pos = savedPos3;
-                }
+          }
+        } else {
+          s2 = peg$c0;
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseInlineCommentClose();
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c23(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseInlineCommentOpen() {
+      var s0;
+
+      if (input.substr(peg$currPos, 2) === peg$c24) {
+        s0 = peg$c24;
+        peg$currPos += 2;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c25); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseInlineCommentClose() {
+      var s0;
+
+      if (input.substr(peg$currPos, 2) === peg$c26) {
+        s0 = peg$c26;
+        peg$currPos += 2;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c27); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseDelimitedSection() {
+      var s0, s1, s2, s3, s4, s5;
+
+      s0 = peg$currPos;
+      s1 = peg$parseDelimitedSectionBegin();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parse_();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseAssignmentList();
+          if (s3 === peg$FAILED) {
+            s3 = peg$parseEmptyBody();
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parse_();
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parseDelimitedSectionEnd();
+              if (s5 !== peg$FAILED) {
+                peg$reportedPos = s0;
+                s1 = peg$c28(s1, s3);
+                s0 = s1;
               } else {
-                var result11 = null;
-                pos = savedPos3;
+                peg$currPos = s0;
+                s0 = peg$c0;
               }
             } else {
-              var result11 = null;
-              pos = savedPos3;
+              peg$currPos = s0;
+              s0 = peg$c0;
             }
           } else {
-            var result11 = null;
-            pos = savedPos3;
+            peg$currPos = s0;
+            s0 = peg$c0;
           }
         } else {
-          var result11 = null;
-          pos = savedPos3;
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        var result12 = result11 !== null
-          ? (function(commentedId, val) {
-                  var result = Object.create(null),
-                      commentKey = commentedId.id + '_comment';
-          
-                  result[commentedId.id] = val;
-                  result[commentKey] = commentedId[commentKey];
-                  return result;
-          
-              })(result11[0], result11[4])
-          : null;
-        if (result12 !== null) {
-          var result10 = result12;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseDelimitedSectionBegin() {
+      var s0, s1, s2, s3, s4;
+
+      s0 = peg$currPos;
+      if (input.substr(peg$currPos, 9) === peg$c29) {
+        s1 = peg$c29;
+        peg$currPos += 9;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c30); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseIdentifier();
+        if (s2 !== peg$FAILED) {
+          if (input.substr(peg$currPos, 11) === peg$c31) {
+            s3 = peg$c31;
+            peg$currPos += 11;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c32); }
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseNewLine();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c33(s2);
+              s0 = s1;
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c0;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
         } else {
-          var result10 = null;
-          pos = savedPos2;
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        if (result10 !== null) {
-          var result0 = result10;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseDelimitedSectionEnd() {
+      var s0, s1, s2, s3, s4;
+
+      s0 = peg$currPos;
+      if (input.substr(peg$currPos, 7) === peg$c34) {
+        s1 = peg$c34;
+        peg$currPos += 7;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c35); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseIdentifier();
+        if (s2 !== peg$FAILED) {
+          if (input.substr(peg$currPos, 11) === peg$c31) {
+            s3 = peg$c31;
+            peg$currPos += 11;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c32); }
+          }
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseNewLine();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c33(s2);
+              s0 = s1;
+            } else {
+              peg$currPos = s0;
+              s0 = peg$c0;
+            }
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
         } else {
-          var savedPos0 = pos;
-          var savedPos1 = pos;
-          var result4 = parse_Identifier();
-          if (result4 !== null) {
-            var result5 = parse__();
-            if (result5 !== null) {
-              if (input.substr(pos, 1) === "=") {
-                var result6 = "=";
-                pos += 1;
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseArray() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      if (input.charCodeAt(peg$currPos) === 40) {
+        s1 = peg$c36;
+        peg$currPos++;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c37); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseArrayBody();
+        if (s2 === peg$FAILED) {
+          s2 = peg$parseEmptyArray();
+        }
+        if (s2 !== peg$FAILED) {
+          if (input.charCodeAt(peg$currPos) === 41) {
+            s3 = peg$c38;
+            peg$currPos++;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c39); }
+          }
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c40(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseEmptyArray() {
+      var s0, s1;
+
+      s0 = peg$currPos;
+      s1 = peg$parse_();
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c41();
+      }
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseArrayBody() {
+      var s0, s1, s2, s3, s4, s5;
+
+      s0 = peg$currPos;
+      s1 = peg$parse_();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseArrayEntry();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parse_();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseArrayBody();
+            if (s4 === peg$FAILED) {
+              s4 = peg$c1;
+            }
+            if (s4 !== peg$FAILED) {
+              s5 = peg$parse_();
+              if (s5 !== peg$FAILED) {
+                peg$reportedPos = s0;
+                s1 = peg$c42(s2, s4);
+                s0 = s1;
               } else {
-                var result6 = null;
-                if (reportMatchFailures) {
-                  matchFailed("\"=\"");
-                }
-              }
-              if (result6 !== null) {
-                var result7 = parse__();
-                if (result7 !== null) {
-                  var result8 = parse_CommentedValue();
-                  if (result8 !== null) {
-                    if (input.substr(pos, 1) === ";") {
-                      var result9 = ";";
-                      pos += 1;
-                    } else {
-                      var result9 = null;
-                      if (reportMatchFailures) {
-                        matchFailed("\";\"");
-                      }
-                    }
-                    if (result9 !== null) {
-                      var result2 = [result4, result5, result6, result7, result8, result9];
-                    } else {
-                      var result2 = null;
-                      pos = savedPos1;
-                    }
-                  } else {
-                    var result2 = null;
-                    pos = savedPos1;
-                  }
-                } else {
-                  var result2 = null;
-                  pos = savedPos1;
-                }
-              } else {
-                var result2 = null;
-                pos = savedPos1;
+                peg$currPos = s0;
+                s0 = peg$c0;
               }
             } else {
-              var result2 = null;
-              pos = savedPos1;
+              peg$currPos = s0;
+              s0 = peg$c0;
             }
           } else {
-            var result2 = null;
-            pos = savedPos1;
+            peg$currPos = s0;
+            s0 = peg$c0;
           }
-          var result3 = result2 !== null
-            ? (function(id, commentedVal) {
-                    var result = Object.create(null);
-                    result[id] = commentedVal.value;
-                    result[id + "_comment"] = commentedVal.comment;
-                    return result;
-                })(result2[0], result2[4])
-            : null;
-          if (result3 !== null) {
-            var result1 = result3;
-          } else {
-            var result1 = null;
-            pos = savedPos0;
-          }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
       }
-      
-      function parse_CommentedIdentifier() {
-        var cacheKey = 'CommentedIdentifier@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
+
+      return s0;
+    }
+
+    function peg$parseArrayEntry() {
+      var s0;
+
+      s0 = peg$parseSimpleArrayEntry();
+      if (s0 === peg$FAILED) {
+        s0 = peg$parseCommentedArrayEntry();
+      }
+
+      return s0;
+    }
+
+    function peg$parseSimpleArrayEntry() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      s1 = peg$parseValue();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseEndArrayEntry();
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c43(s1);
+          s0 = s1;
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_Identifier();
-        if (result3 !== null) {
-          var result4 = parse__();
-          if (result4 !== null) {
-            var result5 = parse_InlineComment();
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseCommentedArrayEntry() {
+      var s0, s1, s2, s3, s4;
+
+      s0 = peg$currPos;
+      s1 = peg$parseValue();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parse_();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseInlineComment();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseEndArrayEntry();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c44(s1, s3);
+              s0 = s1;
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              peg$currPos = s0;
+              s0 = peg$c0;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            peg$currPos = s0;
+            s0 = peg$c0;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        var result2 = result1 !== null
-          ? (function(id, comment) {
-                  var result = Object.create(null);
-                  result.id = id;
-                  result[id + "_comment"] = comment.trim();
-                  return result
-              })(result1[0], result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
       }
-      
-      function parse_CommentedValue() {
-        var cacheKey = 'CommentedValue@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
+
+      return s0;
+    }
+
+    function peg$parseEndArrayEntry() {
+      var s0, s1, s2, s3;
+
+      if (input.charCodeAt(peg$currPos) === 44) {
+        s0 = peg$c45;
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c46); }
+      }
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = peg$parse_();
+        if (s1 !== peg$FAILED) {
+          s2 = peg$currPos;
+          peg$silentFails++;
+          if (input.charCodeAt(peg$currPos) === 41) {
+            s3 = peg$c38;
+            peg$currPos++;
+          } else {
+            s3 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c39); }
+          }
+          peg$silentFails--;
+          if (s3 !== peg$FAILED) {
+            peg$currPos = s2;
+            s2 = peg$c47;
+          } else {
+            s2 = peg$c0;
+          }
+          if (s2 !== peg$FAILED) {
+            s1 = [s1, s2];
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_Value();
-        if (result3 !== null) {
-          var result4 = parse__();
-          if (result4 !== null) {
-            var result5 = parse_InlineComment();
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
+      }
+
+      return s0;
+    }
+
+    function peg$parseIdentifier() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      s1 = [];
+      if (peg$c48.test(input.charAt(peg$currPos))) {
+        s2 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s2 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c49); }
+      }
+      if (s2 !== peg$FAILED) {
+        while (s2 !== peg$FAILED) {
+          s1.push(s2);
+          if (peg$c48.test(input.charAt(peg$currPos))) {
+            s2 = input.charAt(peg$currPos);
+            peg$currPos++;
+          } else {
+            s2 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c49); }
+          }
+        }
+      } else {
+        s1 = peg$c0;
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c50(s1);
+      }
+      s0 = s1;
+      if (s0 === peg$FAILED) {
+        s0 = peg$parseQuotedString();
+      }
+
+      return s0;
+    }
+
+    function peg$parseValue() {
+      var s0;
+
+      s0 = peg$parseObject();
+      if (s0 === peg$FAILED) {
+        s0 = peg$parseArray();
+        if (s0 === peg$FAILED) {
+          s0 = peg$parseNumberValue();
+          if (s0 === peg$FAILED) {
+            s0 = peg$parseStringValue();
+          }
+        }
+      }
+
+      return s0;
+    }
+
+    function peg$parseNumberValue() {
+      var s0;
+
+      s0 = peg$parseDecimalValue();
+      if (s0 === peg$FAILED) {
+        s0 = peg$parseIntegerValue();
+      }
+
+      return s0;
+    }
+
+    function peg$parseDecimalValue() {
+      var s0, s1, s2, s3, s4;
+
+      s0 = peg$currPos;
+      s1 = peg$currPos;
+      s2 = peg$parseIntegerValue();
+      if (s2 !== peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 46) {
+          s3 = peg$c51;
+          peg$currPos++;
+        } else {
+          s3 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c52); }
+        }
+        if (s3 !== peg$FAILED) {
+          s4 = peg$parseIntegerValue();
+          if (s4 !== peg$FAILED) {
+            s2 = [s2, s3, s4];
+            s1 = s2;
+          } else {
+            peg$currPos = s1;
+            s1 = peg$c0;
+          }
+        } else {
+          peg$currPos = s1;
+          s1 = peg$c0;
+        }
+      } else {
+        peg$currPos = s1;
+        s1 = peg$c0;
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c53(s1);
+      }
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseIntegerValue() {
+      var s0, s1, s2, s3, s4;
+
+      s0 = peg$currPos;
+      s1 = peg$currPos;
+      peg$silentFails++;
+      s2 = peg$parseAlpha();
+      peg$silentFails--;
+      if (s2 === peg$FAILED) {
+        s1 = peg$c47;
+      } else {
+        peg$currPos = s1;
+        s1 = peg$c0;
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = [];
+        s3 = peg$parseDigit();
+        if (s3 !== peg$FAILED) {
+          while (s3 !== peg$FAILED) {
+            s2.push(s3);
+            s3 = peg$parseDigit();
+          }
+        } else {
+          s2 = peg$c0;
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$currPos;
+          peg$silentFails++;
+          s4 = peg$parseNonTerminator();
+          peg$silentFails--;
+          if (s4 === peg$FAILED) {
+            s3 = peg$c47;
+          } else {
+            peg$currPos = s3;
+            s3 = peg$c0;
+          }
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c54(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseStringValue() {
+      var s0;
+
+      s0 = peg$parseQuotedString();
+      if (s0 === peg$FAILED) {
+        s0 = peg$parseLiteralString();
+      }
+
+      return s0;
+    }
+
+    function peg$parseQuotedString() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      s1 = peg$parseDoubleQuote();
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseQuotedBody();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseDoubleQuote();
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c55(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseQuotedBody() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$parseNonQuote();
+      if (s2 !== peg$FAILED) {
+        while (s2 !== peg$FAILED) {
+          s1.push(s2);
+          s2 = peg$parseNonQuote();
+        }
+      } else {
+        s1 = peg$c0;
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c56(s1);
+      }
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseNonQuote() {
+      var s0, s1, s2;
+
+      s0 = peg$parseEscapedQuote();
+      if (s0 === peg$FAILED) {
+        s0 = peg$currPos;
+        s1 = peg$currPos;
+        peg$silentFails++;
+        s2 = peg$parseDoubleQuote();
+        peg$silentFails--;
+        if (s2 === peg$FAILED) {
+          s1 = peg$c47;
+        } else {
+          peg$currPos = s1;
+          s1 = peg$c0;
+        }
+        if (s1 !== peg$FAILED) {
+          if (input.length > peg$currPos) {
+            s2 = input.charAt(peg$currPos);
+            peg$currPos++;
+          } else {
+            s2 = peg$FAILED;
+            if (peg$silentFails === 0) { peg$fail(peg$c57); }
+          }
+          if (s2 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c58(s2);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      }
+
+      return s0;
+    }
+
+    function peg$parseEscapedQuote() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      if (input.charCodeAt(peg$currPos) === 92) {
+        s1 = peg$c59;
+        peg$currPos++;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c60); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseDoubleQuote();
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c61();
+          s0 = s1;
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseLiteralString() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$parseLiteralChar();
+      if (s2 !== peg$FAILED) {
+        while (s2 !== peg$FAILED) {
+          s1.push(s2);
+          s2 = peg$parseLiteralChar();
+        }
+      } else {
+        s1 = peg$c0;
+      }
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c62(s1);
+      }
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseLiteralChar() {
+      var s0, s1, s2, s3;
+
+      s0 = peg$currPos;
+      s1 = peg$currPos;
+      peg$silentFails++;
+      s2 = peg$parseInlineCommentOpen();
+      peg$silentFails--;
+      if (s2 === peg$FAILED) {
+        s1 = peg$c47;
+      } else {
+        peg$currPos = s1;
+        s1 = peg$c0;
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$currPos;
+        peg$silentFails++;
+        s3 = peg$parseLineTerminator();
+        peg$silentFails--;
+        if (s3 === peg$FAILED) {
+          s2 = peg$c47;
+        } else {
+          peg$currPos = s2;
+          s2 = peg$c0;
+        }
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseNonTerminator();
+          if (s3 !== peg$FAILED) {
+            peg$reportedPos = s0;
+            s1 = peg$c58(s3);
+            s0 = s1;
+          } else {
+            peg$currPos = s0;
+            s0 = peg$c0;
+          }
+        } else {
+          peg$currPos = s0;
+          s0 = peg$c0;
+        }
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
+      }
+
+      return s0;
+    }
+
+    function peg$parseNonTerminator() {
+      var s0;
+
+      if (peg$c63.test(input.charAt(peg$currPos))) {
+        s0 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c64); }
+      }
+
+      return s0;
+    }
+
+    function peg$parseSingleLineComment() {
+      var s0, s1, s2, s3, s4;
+
+      s0 = peg$currPos;
+      if (input.substr(peg$currPos, 2) === peg$c65) {
+        s1 = peg$c65;
+        peg$currPos += 2;
+      } else {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c66); }
+      }
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parse_();
+        if (s2 !== peg$FAILED) {
+          s3 = peg$parseOneLineString();
+          if (s3 !== peg$FAILED) {
+            s4 = peg$parseNewLine();
+            if (s4 !== peg$FAILED) {
+              peg$reportedPos = s0;
+              s1 = peg$c67(s3);
+              s0 = s1;
             } else {
-              var result1 = null;
-              pos = savedPos1;
+              peg$currPos = s0;
+              s0 = peg$c0;
             }
           } else {
-            var result1 = null;
-            pos = savedPos1;
+            peg$currPos = s0;
+            s0 = peg$c0;
           }
         } else {
-          var result1 = null;
-          pos = savedPos1;
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        var result2 = result1 !== null
-          ? (function(literal, comment) {
-                  var result = Object.create(null)
-                  result.comment = comment.trim();
-                  result.value = literal.trim();
-                  return result;
-              })(result1[0], result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
       }
-      
-      function parse_InlineComment() {
-        var cacheKey = 'InlineComment@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_InlineCommentOpen();
-        if (result3 !== null) {
-          if (input.substr(pos).match(/^[^*]/) !== null) {
-            var result6 = input.charAt(pos);
-            pos++;
-          } else {
-            var result6 = null;
-            if (reportMatchFailures) {
-              matchFailed("[^*]");
-            }
-          }
-          if (result6 !== null) {
-            var result4 = [];
-            while (result6 !== null) {
-              result4.push(result6);
-              if (input.substr(pos).match(/^[^*]/) !== null) {
-                var result6 = input.charAt(pos);
-                pos++;
-              } else {
-                var result6 = null;
-                if (reportMatchFailures) {
-                  matchFailed("[^*]");
-                }
-              }
-            }
-          } else {
-            var result4 = null;
-          }
-          if (result4 !== null) {
-            var result5 = parse_InlineCommentClose();
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(body) { return body.join('') })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parseOneLineString() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      s1 = [];
+      s2 = peg$parseNonLine();
+      while (s2 !== peg$FAILED) {
+        s1.push(s2);
+        s2 = peg$parseNonLine();
       }
-      
-      function parse_InlineCommentOpen() {
-        var cacheKey = 'InlineCommentOpen@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.substr(pos, 2) === "/*") {
-          var result0 = "/*";
-          pos += 2;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"/*\"");
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+      if (s1 !== peg$FAILED) {
+        peg$reportedPos = s0;
+        s1 = peg$c68(s1);
       }
-      
-      function parse_InlineCommentClose() {
-        var cacheKey = 'InlineCommentClose@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.substr(pos, 2) === "*/") {
-          var result0 = "*/";
-          pos += 2;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"*/\"");
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+      s0 = s1;
+
+      return s0;
+    }
+
+    function peg$parseDigit() {
+      var s0;
+
+      if (peg$c69.test(input.charAt(peg$currPos))) {
+        s0 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c70); }
       }
-      
-      function parse_DelimitedSection() {
-        var cacheKey = 'DelimitedSection@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_DelimitedSectionBegin();
-        if (result3 !== null) {
-          var result4 = parse__();
-          if (result4 !== null) {
-            var result9 = parse_AssignmentList();
-            if (result9 !== null) {
-              var result5 = result9;
-            } else {
-              var result8 = parse_EmptyBody();
-              if (result8 !== null) {
-                var result5 = result8;
-              } else {
-                var result5 = null;;
-              };
-            }
-            if (result5 !== null) {
-              var result6 = parse__();
-              if (result6 !== null) {
-                var result7 = parse_DelimitedSectionEnd();
-                if (result7 !== null) {
-                  var result1 = [result3, result4, result5, result6, result7];
-                } else {
-                  var result1 = null;
-                  pos = savedPos1;
-                }
-              } else {
-                var result1 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(begin, fields) {
-                  var section = Object.create(null);
-                  section[begin.name] = fields
-          
-                  return section
-              })(result1[0], result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parseAlpha() {
+      var s0;
+
+      if (peg$c71.test(input.charAt(peg$currPos))) {
+        s0 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c72); }
       }
-      
-      function parse_DelimitedSectionBegin() {
-        var cacheKey = 'DelimitedSectionBegin@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        if (input.substr(pos, 9) === "/* Begin ") {
-          var result3 = "/* Begin ";
-          pos += 9;
-        } else {
-          var result3 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"/* Begin \"");
-          }
-        }
-        if (result3 !== null) {
-          var result4 = parse_Identifier();
-          if (result4 !== null) {
-            if (input.substr(pos, 11) === " section */") {
-              var result5 = " section */";
-              pos += 11;
-            } else {
-              var result5 = null;
-              if (reportMatchFailures) {
-                matchFailed("\" section */\"");
-              }
-            }
-            if (result5 !== null) {
-              var result6 = parse_NewLine();
-              if (result6 !== null) {
-                var result1 = [result3, result4, result5, result6];
-              } else {
-                var result1 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(sectionName) { return { name: sectionName } })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parseDoubleQuote() {
+      var s0;
+
+      if (input.charCodeAt(peg$currPos) === 34) {
+        s0 = peg$c73;
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c74); }
       }
-      
-      function parse_DelimitedSectionEnd() {
-        var cacheKey = 'DelimitedSectionEnd@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        if (input.substr(pos, 7) === "/* End ") {
-          var result3 = "/* End ";
-          pos += 7;
-        } else {
-          var result3 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"/* End \"");
-          }
-        }
-        if (result3 !== null) {
-          var result4 = parse_Identifier();
-          if (result4 !== null) {
-            if (input.substr(pos, 11) === " section */") {
-              var result5 = " section */";
-              pos += 11;
-            } else {
-              var result5 = null;
-              if (reportMatchFailures) {
-                matchFailed("\" section */\"");
-              }
-            }
-            if (result5 !== null) {
-              var result6 = parse_NewLine();
-              if (result6 !== null) {
-                var result1 = [result3, result4, result5, result6];
-              } else {
-                var result1 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(sectionName) { return { name: sectionName } })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parse_() {
+      var s0, s1;
+
+      peg$silentFails++;
+      s0 = [];
+      s1 = peg$parsewhitespace();
+      while (s1 !== peg$FAILED) {
+        s0.push(s1);
+        s1 = peg$parsewhitespace();
       }
-      
-      function parse_Array() {
-        var cacheKey = 'Array@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        if (input.substr(pos, 1) === "(") {
-          var result3 = "(";
-          pos += 1;
-        } else {
-          var result3 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"(\"");
-          }
-        }
-        if (result3 !== null) {
-          var result7 = parse_ArrayBody();
-          if (result7 !== null) {
-            var result4 = result7;
-          } else {
-            var result6 = parse_EmptyArray();
-            if (result6 !== null) {
-              var result4 = result6;
-            } else {
-              var result4 = null;;
-            };
-          }
-          if (result4 !== null) {
-            if (input.substr(pos, 1) === ")") {
-              var result5 = ")";
-              pos += 1;
-            } else {
-              var result5 = null;
-              if (reportMatchFailures) {
-                matchFailed("\")\"");
-              }
-            }
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(arr) { return arr })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+      peg$silentFails--;
+      if (s0 === peg$FAILED) {
+        s1 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c75); }
       }
-      
-      function parse_EmptyArray() {
-        var cacheKey = 'EmptyArray@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var result1 = parse__();
-        var result2 = result1 !== null
-          ? (function() { return [] })()
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
+
+      return s0;
+    }
+
+    function peg$parsewhitespace() {
+      var s0;
+
+      s0 = peg$parseNewLine();
+      if (s0 === peg$FAILED) {
+        if (peg$c76.test(input.charAt(peg$currPos))) {
+          s0 = input.charAt(peg$currPos);
+          peg$currPos++;
         } else {
-          var result0 = null;
-          pos = savedPos0;
+          s0 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c77); }
         }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
       }
-      
-      function parse_ArrayBody() {
-        var cacheKey = 'ArrayBody@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse__();
-        if (result3 !== null) {
-          var result4 = parse_ArrayEntry();
-          if (result4 !== null) {
-            var result5 = parse__();
-            if (result5 !== null) {
-              var result8 = parse_ArrayBody();
-              var result6 = result8 !== null ? result8 : '';
-              if (result6 !== null) {
-                var result7 = parse__();
-                if (result7 !== null) {
-                  var result1 = [result3, result4, result5, result6, result7];
-                } else {
-                  var result1 = null;
-                  pos = savedPos1;
-                }
-              } else {
-                var result1 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(head, tail) {
-                  if (tail) {
-                      tail.unshift(head);
-                      return tail;
-                  } else {
-                      return [head];
-                  }
-              })(result1[1], result1[3])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parseNonLine() {
+      var s0, s1, s2;
+
+      s0 = peg$currPos;
+      s1 = peg$currPos;
+      peg$silentFails++;
+      s2 = peg$parseNewLine();
+      peg$silentFails--;
+      if (s2 === peg$FAILED) {
+        s1 = peg$c47;
+      } else {
+        peg$currPos = s1;
+        s1 = peg$c0;
       }
-      
-      function parse_ArrayEntry() {
-        var cacheKey = 'ArrayEntry@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result2 = parse_SimpleArrayEntry();
-        if (result2 !== null) {
-          var result0 = result2;
+      if (s1 !== peg$FAILED) {
+        s2 = peg$parseChar();
+        if (s2 !== peg$FAILED) {
+          peg$reportedPos = s0;
+          s1 = peg$c58(s2);
+          s0 = s1;
         } else {
-          var result1 = parse_CommentedArrayEntry();
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
+          peg$currPos = s0;
+          s0 = peg$c0;
         }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+      } else {
+        peg$currPos = s0;
+        s0 = peg$c0;
       }
-      
-      function parse_SimpleArrayEntry() {
-        var cacheKey = 'SimpleArrayEntry@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_Value();
-        if (result3 !== null) {
-          if (input.substr(pos, 1) === ",") {
-            var result4 = ",";
-            pos += 1;
-          } else {
-            var result4 = null;
-            if (reportMatchFailures) {
-              matchFailed("\",\"");
-            }
-          }
-          if (result4 !== null) {
-            var result1 = [result3, result4];
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
+
+      return s0;
+    }
+
+    function peg$parseLineTerminator() {
+      var s0;
+
+      s0 = peg$parseNewLine();
+      if (s0 === peg$FAILED) {
+        if (input.charCodeAt(peg$currPos) === 59) {
+          s0 = peg$c14;
+          peg$currPos++;
         } else {
-          var result1 = null;
-          pos = savedPos1;
+          s0 = peg$FAILED;
+          if (peg$silentFails === 0) { peg$fail(peg$c15); }
         }
-        var result2 = result1 !== null
-          ? (function(val) { return val })(result1[0])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
       }
-      
-      function parse_CommentedArrayEntry() {
-        var cacheKey = 'CommentedArrayEntry@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_Value();
-        if (result3 !== null) {
-          var result4 = parse__();
-          if (result4 !== null) {
-            var result5 = parse_InlineComment();
-            if (result5 !== null) {
-              if (input.substr(pos, 1) === ",") {
-                var result6 = ",";
-                pos += 1;
-              } else {
-                var result6 = null;
-                if (reportMatchFailures) {
-                  matchFailed("\",\"");
-                }
-              }
-              if (result6 !== null) {
-                var result1 = [result3, result4, result5, result6];
-              } else {
-                var result1 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(val, comment) {
-                  var result = Object.create(null);
-                  result.value = val.trim();
-                  result.comment = comment.trim();
-                  return result;
-              })(result1[0], result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parseNewLine() {
+      var s0;
+
+      if (peg$c78.test(input.charAt(peg$currPos))) {
+        s0 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c79); }
       }
-      
-      function parse_Identifier() {
-        var cacheKey = 'Identifier@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        if (input.substr(pos).match(/^[A-Za-z0-9_.]/) !== null) {
-          var result5 = input.charAt(pos);
-          pos++;
-        } else {
-          var result5 = null;
-          if (reportMatchFailures) {
-            matchFailed("[A-Za-z0-9_.]");
-          }
-        }
-        if (result5 !== null) {
-          var result3 = [];
-          while (result5 !== null) {
-            result3.push(result5);
-            if (input.substr(pos).match(/^[A-Za-z0-9_.]/) !== null) {
-              var result5 = input.charAt(pos);
-              pos++;
-            } else {
-              var result5 = null;
-              if (reportMatchFailures) {
-                matchFailed("[A-Za-z0-9_.]");
-              }
-            }
-          }
-        } else {
-          var result3 = null;
-        }
-        var result4 = result3 !== null
-          ? (function(id) { return id.join('') })(result3)
-          : null;
-        if (result4 !== null) {
-          var result2 = result4;
-        } else {
-          var result2 = null;
-          pos = savedPos0;
-        }
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result1 = parse_QuotedString();
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
+
+      return s0;
+    }
+
+    function peg$parseChar() {
+      var s0;
+
+      if (input.length > peg$currPos) {
+        s0 = input.charAt(peg$currPos);
+        peg$currPos++;
+      } else {
+        s0 = peg$FAILED;
+        if (peg$silentFails === 0) { peg$fail(peg$c57); }
       }
-      
-      function parse_Value() {
-        var cacheKey = 'Value@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result4 = parse_Object();
-        if (result4 !== null) {
-          var result0 = result4;
-        } else {
-          var result3 = parse_Array();
-          if (result3 !== null) {
-            var result0 = result3;
-          } else {
-            var result2 = parse_NumberValue();
-            if (result2 !== null) {
-              var result0 = result2;
-            } else {
-              var result1 = parse_StringValue();
-              if (result1 !== null) {
-                var result0 = result1;
-              } else {
-                var result0 = null;;
-              };
-            };
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_NumberValue() {
-        var cacheKey = 'NumberValue@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result2 = parse_DecimalValue();
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result1 = parse_IntegerValue();
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_DecimalValue() {
-        var cacheKey = 'DecimalValue@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_IntegerValue();
-        if (result3 !== null) {
-          if (input.substr(pos, 1) === ".") {
-            var result4 = ".";
-            pos += 1;
-          } else {
-            var result4 = null;
-            if (reportMatchFailures) {
-              matchFailed("\".\"");
-            }
-          }
-          if (result4 !== null) {
-            var result5 = parse_IntegerValue();
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(decimal) { 
-                  // store decimals as strings
-                  // as JS doesn't differentiate bw strings and numbers
-                  return decimal.join('')
-              })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_IntegerValue() {
-        var cacheKey = 'IntegerValue@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var savedPos3 = pos;
-        var savedReportMatchFailuresVar1 = reportMatchFailures;
-        reportMatchFailures = false;
-        var result8 = parse_Alpha();
-        reportMatchFailures = savedReportMatchFailuresVar1;
-        if (result8 === null) {
-          var result3 = '';
-        } else {
-          var result3 = null;
-          pos = savedPos3;
-        }
-        if (result3 !== null) {
-          var result7 = parse_Digit();
-          if (result7 !== null) {
-            var result4 = [];
-            while (result7 !== null) {
-              result4.push(result7);
-              var result7 = parse_Digit();
-            }
-          } else {
-            var result4 = null;
-          }
-          if (result4 !== null) {
-            var savedPos2 = pos;
-            var savedReportMatchFailuresVar0 = reportMatchFailures;
-            reportMatchFailures = false;
-            var result6 = parse_NonTerminator();
-            reportMatchFailures = savedReportMatchFailuresVar0;
-            if (result6 === null) {
-              var result5 = '';
-            } else {
-              var result5 = null;
-              pos = savedPos2;
-            }
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(number) { return parseInt(number.join(''), 10) })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_StringValue() {
-        var cacheKey = 'StringValue@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result2 = parse_QuotedString();
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result1 = parse_LiteralString();
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_QuotedString() {
-        var cacheKey = 'QuotedString@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var result3 = parse_DoubleQuote();
-        if (result3 !== null) {
-          var result4 = parse_QuotedBody();
-          if (result4 !== null) {
-            var result5 = parse_DoubleQuote();
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(str) { return '"' + str + '"' })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_QuotedBody() {
-        var cacheKey = 'QuotedBody@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var result3 = parse_NonQuote();
-        if (result3 !== null) {
-          var result1 = [];
-          while (result3 !== null) {
-            result1.push(result3);
-            var result3 = parse_NonQuote();
-          }
-        } else {
-          var result1 = null;
-        }
-        var result2 = result1 !== null
-          ? (function(str) { return str.join('') })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_NonQuote() {
-        var cacheKey = 'NonQuote@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result7 = parse_EscapedQuote();
-        if (result7 !== null) {
-          var result0 = result7;
-        } else {
-          var savedPos0 = pos;
-          var savedPos1 = pos;
-          var savedPos2 = pos;
-          var savedReportMatchFailuresVar0 = reportMatchFailures;
-          reportMatchFailures = false;
-          var result6 = parse_DoubleQuote();
-          reportMatchFailures = savedReportMatchFailuresVar0;
-          if (result6 === null) {
-            var result4 = '';
-          } else {
-            var result4 = null;
-            pos = savedPos2;
-          }
-          if (result4 !== null) {
-            if (input.length > pos) {
-              var result5 = input.charAt(pos);
-              pos++;
-            } else {
-              var result5 = null;
-              if (reportMatchFailures) {
-                matchFailed('any character');
-              }
-            }
-            if (result5 !== null) {
-              var result2 = [result4, result5];
-            } else {
-              var result2 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result2 = null;
-            pos = savedPos1;
-          }
-          var result3 = result2 !== null
-            ? (function(char) { return char })(result2[1])
-            : null;
-          if (result3 !== null) {
-            var result1 = result3;
-          } else {
-            var result1 = null;
-            pos = savedPos0;
-          }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_EscapedQuote() {
-        var cacheKey = 'EscapedQuote@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        if (input.substr(pos, 1) === "\\") {
-          var result3 = "\\";
-          pos += 1;
-        } else {
-          var result3 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"\\\\\"");
-          }
-        }
-        if (result3 !== null) {
-          var result4 = parse_DoubleQuote();
-          if (result4 !== null) {
-            var result1 = [result3, result4];
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function() { return '\\"' })()
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_LiteralString() {
-        var cacheKey = 'LiteralString@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var result3 = parse_LiteralChar();
-        if (result3 !== null) {
-          var result1 = [];
-          while (result3 !== null) {
-            result1.push(result3);
-            var result3 = parse_LiteralChar();
-          }
-        } else {
-          var result1 = null;
-        }
-        var result2 = result1 !== null
-          ? (function(literal) { return literal.join('') })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_LiteralChar() {
-        var cacheKey = 'LiteralChar@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var savedPos3 = pos;
-        var savedReportMatchFailuresVar1 = reportMatchFailures;
-        reportMatchFailures = false;
-        var result7 = parse_InlineCommentOpen();
-        reportMatchFailures = savedReportMatchFailuresVar1;
-        if (result7 === null) {
-          var result3 = '';
-        } else {
-          var result3 = null;
-          pos = savedPos3;
-        }
-        if (result3 !== null) {
-          var savedPos2 = pos;
-          var savedReportMatchFailuresVar0 = reportMatchFailures;
-          reportMatchFailures = false;
-          var result6 = parse_LineTerminator();
-          reportMatchFailures = savedReportMatchFailuresVar0;
-          if (result6 === null) {
-            var result4 = '';
-          } else {
-            var result4 = null;
-            pos = savedPos2;
-          }
-          if (result4 !== null) {
-            var result5 = parse_NonTerminator();
-            if (result5 !== null) {
-              var result1 = [result3, result4, result5];
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(char) { return char })(result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_NonTerminator() {
-        var cacheKey = 'NonTerminator@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.substr(pos).match(/^[^;,\n]/) !== null) {
-          var result0 = input.charAt(pos);
-          pos++;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("[^;,\\n]");
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_SingleLineComment() {
-        var cacheKey = 'SingleLineComment@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        if (input.substr(pos, 2) === "//") {
-          var result3 = "//";
-          pos += 2;
-        } else {
-          var result3 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"//\"");
-          }
-        }
-        if (result3 !== null) {
-          var result4 = parse__();
-          if (result4 !== null) {
-            var result5 = parse_OneLineString();
-            if (result5 !== null) {
-              var result6 = parse_NewLine();
-              if (result6 !== null) {
-                var result1 = [result3, result4, result5, result6];
-              } else {
-                var result1 = null;
-                pos = savedPos1;
-              }
-            } else {
-              var result1 = null;
-              pos = savedPos1;
-            }
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(contents) { return contents })(result1[2])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_OneLineString() {
-        var cacheKey = 'OneLineString@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var result1 = [];
-        var result3 = parse_NonLine();
-        while (result3 !== null) {
-          result1.push(result3);
-          var result3 = parse_NonLine();
-        }
-        var result2 = result1 !== null
-          ? (function(contents) { return contents.join('') })(result1)
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_Digit() {
-        var cacheKey = 'Digit@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.substr(pos).match(/^[0-9]/) !== null) {
-          var result0 = input.charAt(pos);
-          pos++;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("[0-9]");
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_Alpha() {
-        var cacheKey = 'Alpha@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.substr(pos).match(/^[A-Za-z]/) !== null) {
-          var result0 = input.charAt(pos);
-          pos++;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("[A-Za-z]");
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_DoubleQuote() {
-        var cacheKey = 'DoubleQuote@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.substr(pos, 1) === "\"") {
-          var result0 = "\"";
-          pos += 1;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("\"\\\"\"");
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse__() {
-        var cacheKey = '_@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        var savedReportMatchFailures = reportMatchFailures;
-        reportMatchFailures = false;
-        var result0 = [];
-        var result1 = parse_whitespace();
-        while (result1 !== null) {
-          result0.push(result1);
-          var result1 = parse_whitespace();
-        }
-        reportMatchFailures = savedReportMatchFailures;
-        if (reportMatchFailures && result0 === null) {
-          matchFailed("whitespace");
-        }
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_whitespace() {
-        var cacheKey = 'whitespace@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result2 = parse_NewLine();
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          if (input.substr(pos).match(/^[	 ]/) !== null) {
-            var result1 = input.charAt(pos);
-            pos++;
-          } else {
-            var result1 = null;
-            if (reportMatchFailures) {
-              matchFailed("[	 ]");
-            }
-          }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_NonLine() {
-        var cacheKey = 'NonLine@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var savedPos0 = pos;
-        var savedPos1 = pos;
-        var savedPos2 = pos;
-        var savedReportMatchFailuresVar0 = reportMatchFailures;
-        reportMatchFailures = false;
-        var result5 = parse_NewLine();
-        reportMatchFailures = savedReportMatchFailuresVar0;
-        if (result5 === null) {
-          var result3 = '';
-        } else {
-          var result3 = null;
-          pos = savedPos2;
-        }
-        if (result3 !== null) {
-          var result4 = parse_Char();
-          if (result4 !== null) {
-            var result1 = [result3, result4];
-          } else {
-            var result1 = null;
-            pos = savedPos1;
-          }
-        } else {
-          var result1 = null;
-          pos = savedPos1;
-        }
-        var result2 = result1 !== null
-          ? (function(char) { return char })(result1[1])
-          : null;
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          var result0 = null;
-          pos = savedPos0;
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_LineTerminator() {
-        var cacheKey = 'LineTerminator@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        var result2 = parse_NewLine();
-        if (result2 !== null) {
-          var result0 = result2;
-        } else {
-          if (input.substr(pos, 1) === ";") {
-            var result1 = ";";
-            pos += 1;
-          } else {
-            var result1 = null;
-            if (reportMatchFailures) {
-              matchFailed("\";\"");
-            }
-          }
-          if (result1 !== null) {
-            var result0 = result1;
-          } else {
-            var result0 = null;;
-          };
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_NewLine() {
-        var cacheKey = 'NewLine@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.substr(pos).match(/^[\n\r]/) !== null) {
-          var result0 = input.charAt(pos);
-          pos++;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed("[\\n\\r]");
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function parse_Char() {
-        var cacheKey = 'Char@' + pos;
-        var cachedResult = cache[cacheKey];
-        if (cachedResult) {
-          pos = cachedResult.nextPos;
-          return cachedResult.result;
-        }
-        
-        
-        if (input.length > pos) {
-          var result0 = input.charAt(pos);
-          pos++;
-        } else {
-          var result0 = null;
-          if (reportMatchFailures) {
-            matchFailed('any character');
-          }
-        }
-        
-        
-        
-        cache[cacheKey] = {
-          nextPos: pos,
-          result:  result0
-        };
-        return result0;
-      }
-      
-      function buildErrorMessage() {
-        function buildExpected(failuresExpected) {
-          failuresExpected.sort();
-          
-          var lastFailure = null;
-          var failuresExpectedUnique = [];
-          for (var i = 0; i < failuresExpected.length; i++) {
-            if (failuresExpected[i] !== lastFailure) {
-              failuresExpectedUnique.push(failuresExpected[i]);
-              lastFailure = failuresExpected[i];
-            }
-          }
-          
-          switch (failuresExpectedUnique.length) {
-            case 0:
-              return 'end of input';
-            case 1:
-              return failuresExpectedUnique[0];
-            default:
-              return failuresExpectedUnique.slice(0, failuresExpectedUnique.length - 1).join(', ')
-                + ' or '
-                + failuresExpectedUnique[failuresExpectedUnique.length - 1];
-          }
-        }
-        
-        var expected = buildExpected(rightmostMatchFailuresExpected);
-        var actualPos = Math.max(pos, rightmostMatchFailuresPos);
-        var actual = actualPos < input.length
-          ? quote(input.charAt(actualPos))
-          : 'end of input';
-        
-        return 'Expected ' + expected + ' but ' + actual + ' found.';
-      }
-      
-      function computeErrorPosition() {
-        /*
-         * The first idea was to use |String.split| to break the input up to the
-         * error position along newlines and derive the line and column from
-         * there. However IE's |split| implementation is so broken that it was
-         * enough to prevent it.
-         */
-        
-        var line = 1;
-        var column = 1;
-        var seenCR = false;
-        
-        for (var i = 0; i <  rightmostMatchFailuresPos; i++) {
-          var ch = input.charAt(i);
-          if (ch === '\n') {
-            if (!seenCR) { line++; }
-            column = 1;
-            seenCR = false;
-          } else if (ch === '\r' | ch === '\u2028' || ch === '\u2029') {
-            line++;
-            column = 1;
-            seenCR = true;
-          } else {
-            column++;
-            seenCR = false;
-          }
-        }
-        
-        return { line: line, column: column };
-      }
-      
-      
-      
+
+      return s0;
+    }
+
+
         function merge(hash, secondHash) {
-      
             secondHash = secondHash[0]
-      
             for(var i in secondHash) {
-      
            		hash[i] = merge_obj(hash[i], secondHash[i]);
-      
             }
-      
-    
-      
+
             return hash;
-      
         }
-      
         
-      
         function merge_obj(obj, secondObj) {
-      
         	if (!obj)
-      
         		return secondObj;
-      
-    
-      
+
             for(var i in secondObj)
-      
                 obj[i] = merge_obj(obj[i], secondObj[i]);
-      
-    
-      
+
             return obj;
-      
         }
-      
-    
-      
-      var result = parseFunctions[startRule]();
-      
-      /*
-       * The parser is now in one of the following three states:
-       *
-       * 1. The parser successfully parsed the whole input.
-       *
-       *    - |result !== null|
-       *    - |pos === input.length|
-       *    - |rightmostMatchFailuresExpected| may or may not contain something
-       *
-       * 2. The parser successfully parsed only a part of the input.
-       *
-       *    - |result !== null|
-       *    - |pos < input.length|
-       *    - |rightmostMatchFailuresExpected| may or may not contain something
-       *
-       * 3. The parser did not successfully parse any part of the input.
-       *
-       *   - |result === null|
-       *   - |pos === 0|
-       *   - |rightmostMatchFailuresExpected| contains at least one failure
-       *
-       * All code following this comment (including called functions) must
-       * handle these states.
-       */
-      if (result === null || pos !== input.length) {
-        var errorPosition = computeErrorPosition();
-        throw new this.SyntaxError(
-          buildErrorMessage(),
-          errorPosition.line,
-          errorPosition.column
-        );
+
+
+    peg$result = peg$startRuleFunction();
+
+    if (peg$result !== peg$FAILED && peg$currPos === input.length) {
+      return peg$result;
+    } else {
+      if (peg$result !== peg$FAILED && peg$currPos < input.length) {
+        peg$fail({ type: "end", description: "end of input" });
       }
-      
-      return result;
-    },
-    
-    /* Returns the parser source code. */
-    toSource: function() { return this._source; }
+
+      throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
+    }
+  }
+
+  return {
+    SyntaxError: SyntaxError,
+    parse:       parse
   };
-  
-  /* Thrown when a parser encounters a syntax error. */
-  
-  result.SyntaxError = function(message, line, column) {
-    this.name = 'SyntaxError';
-    this.message = message;
-    this.line = line;
-    this.column = column;
-  };
-  
-  result.SyntaxError.prototype = Error.prototype;
-  
-  return result;
 })();
diff --git a/lib/parser/pbxproj.pegjs b/lib/parser/pbxproj.pegjs
index 2204673..5140c05 100644
--- a/lib/parser/pbxproj.pegjs
+++ b/lib/parser/pbxproj.pegjs
@@ -166,10 +166,10 @@
   = SimpleArrayEntry / CommentedArrayEntry
 
 SimpleArrayEntry
-  = val:Value "," { return val }
+  = val:Value EndArrayEntry { return val }
 
 CommentedArrayEntry
-  = val:Value _ comment:InlineComment ","
+  = val:Value _ comment:InlineComment EndArrayEntry
     {
         var result = Object.create(null);
         result.value = val.trim();
@@ -177,6 +177,9 @@
         return result;
     }
 
+EndArrayEntry
+  = "," / _ &")"
+
 /*
  *  Identifiers and Values
  */
diff --git a/test/parser/projects/expected/with_array_expected.pbxproj b/test/parser/projects/expected/with_array_expected.pbxproj
new file mode 100644
index 0000000..efa5e47
--- /dev/null
+++ b/test/parser/projects/expected/with_array_expected.pbxproj
@@ -0,0 +1,25 @@
+// !$*UTF8*$!
+{
+    archiveVersion = 1;
+    classes = {
+    };
+    empties = (
+    );
+    ARCHS = (
+        armv6,
+        armv7,
+    );
+    files = (
+        1D60589B0D05DD56006BFB54 /* main.m in Sources */,
+        1D3623260D0F684500981E51 /* AppDelegate.m in Sources */,
+    );
+    LIBS = (
+        "$(SRCROOT)/bestgame/libs/**",
+    );
+    FRAMEWORK_SEARCH_PATHS = (
+        "$(inherited)",
+        "$(SRCROOT)/bestgame/libs/**",
+    );
+    objectVersion = 45;
+    rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/test/parser/projects/with_array.pbxproj b/test/parser/projects/with_array.pbxproj
index bdd7247..2c876f2 100644
--- a/test/parser/projects/with_array.pbxproj
+++ b/test/parser/projects/with_array.pbxproj
@@ -13,6 +13,13 @@
         1D60589B0D05DD56006BFB54 /* main.m in Sources */,
         1D3623260D0F684500981E51 /* AppDelegate.m in Sources */,
     );
+    LIBS = (
+        "$(SRCROOT)/bestgame/libs/**"
+    );
+    FRAMEWORK_SEARCH_PATHS = (
+        "$(inherited)",
+        "$(SRCROOT)/bestgame/libs/**"
+    );
     objectVersion = 45;
     rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
 }
diff --git a/test/pbxWriter.js b/test/pbxWriter.js
index 982019f..d3b49e8 100644
--- a/test/pbxWriter.js
+++ b/test/pbxWriter.js
@@ -2,10 +2,15 @@
     fs = require('fs'),
     myProj;
 
-function testProjectContents(filename, test) {
-    var myProj = new pbx(filename),
-        content = fs.readFileSync(filename, 'utf-8');
+function testProjectContents(filename, test, expectedFilename) {
+    var myProj = new pbx(filename);
 
+    var content;
+    if (expectedFilename) {
+        content = fs.readFileSync(expectedFilename, 'utf-8');
+    } else {
+        content = fs.readFileSync(filename, 'utf-8');
+    }
     // normalize tabs vs strings
     content = content.replace(/    /g, '\t');
 
@@ -46,7 +51,10 @@
         testProjectContents('test/parser/projects/hash.pbxproj', test);
     },
     'should write out the "with_array" test': function (test) {
-        testProjectContents('test/parser/projects/with_array.pbxproj', test);
+        // Special case in that the originating project does not have a trailing comma for all of its array entries.
+        // This is definitely possibly.
+        // But when we write/read it out again during testing, the trailing commas are introduced by our library.
+        testProjectContents('test/parser/projects/with_array.pbxproj', test, 'test/parser/projects/expected/with_array_expected.pbxproj');
     },
     'should write out the "section" test': function (test) {
         testProjectContents('test/parser/projects/section.pbxproj', test);