[Pkg-javascript-commits] [node-acorn-jsx] 436/484: Add JSX support to loose parser.

Bastien Roucariès rouca at moszumanska.debian.org
Sat Aug 19 14:21:07 UTC 2017


This is an automated email from the git hooks/post-receive script.

rouca pushed a commit to branch master
in repository node-acorn-jsx.

commit e0bcfca03f8b044de2f23306c18f431d3d578c9a
Author: Ingvar Stepanyan <me at rreverser.com>
Date:   Tue Jan 27 18:25:49 2015 +0200

    Add JSX support to loose parser.
---
 acorn.js          |  10 +---
 acorn_loose.js    | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 test/tests-jsx.js |   3 +-
 3 files changed, 175 insertions(+), 13 deletions(-)

diff --git a/acorn.js b/acorn.js
index 2447814..3cc5fa0 100644
--- a/acorn.js
+++ b/acorn.js
@@ -463,7 +463,8 @@
                       dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq,
                       name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string,
                       arrow: _arrow, template: _template, star: _star, assign: _assign,
-                      backQuote: _backQuote, dollarBraceL: _dollarBraceL};
+                      backQuote: _backQuote, dollarBraceL: _dollarBraceL, jsxName: _jsxName,
+                      jsxText: _jsxText, jsxTagStart: _jsxTagStart, jsxTagEnd: _jsxTagEnd};
   for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];
 
   // This is a trick taken from Esprima. It turns out that, on
@@ -3321,9 +3322,6 @@
         return node;
 
       case _jsxTagStart:
-        return parseJSXElement();
-
-      case _jsxText:
       case _string:
         return parseExprAtom();
 
@@ -3337,10 +3335,6 @@
   // at the beginning of the next one (right brace).
 
   function parseJSXEmptyExpression() {
-    if (tokType !== _braceR) {
-      unexpected();
-    }
-
     var tmp;
 
     tmp = tokStart;
diff --git a/acorn_loose.js b/acorn_loose.js
index 0f52fcc..fa7631b 100644
--- a/acorn_loose.js
+++ b/acorn_loose.js
@@ -256,11 +256,27 @@
     return node;
   }
 
+  function finishNodeAt(node, type, pos) {
+    if (options.locations) { node.loc.end = pos[1]; pos = pos[0]; }
+    node.type = type;
+    node.end = pos;
+    if (options.ranges)
+      node.range[1] = pos;
+    return node;
+  }
+
+  function emptyNode(type) {
+    var dummy = startNodeAt(options.locations ? [lastEnd, lastEndLoc] : lastEnd);
+    dummy.name = "✖";
+    return finishNodeAt(dummy, type, storeCurrentPos());
+  }
+
   function dummyIdent() {
-    var dummy = startNode();
+    var dummy = emptyNode("Identifier");
     dummy.name = "✖";
-    return finishNode(dummy, "Identifier");
+    return dummy;
   }
+
   function isDummy(node) { return node.name == "✖"; }
 
   function eat(type) {
@@ -724,7 +740,7 @@
       next();
       return finishNode(node, "Literal");
 
-    case tt.num: case tt.string:
+    case tt.num: case tt.string: case tt.jsxText:
       var node = startNode();
       node.value = token.value;
       node.raw = input.slice(token.start, token.end);
@@ -788,6 +804,9 @@
     case tt.backQuote:
       return parseTemplate();
 
+    case tt.jsxTagStart:
+      return parseJSXElement();
+
     default:
       return dummyIdent();
     }
@@ -1161,4 +1180,154 @@
     }
     return elts;
   }
+
+  // Parse next token as JSX identifier
+
+  function parseJSXIdentifier() {
+    var node = startNode();
+    node.name = token.type === tt.jsxName ? token.value : token.type.keyword;
+    next();
+    return finishNode(node, "JSXIdentifier");
+  }
+
+  // Parse namespaced identifier.
+
+  function parseJSXNamespacedName() {
+    var start = storeCurrentPos();
+    var name = parseJSXIdentifier();
+    if (!eat(tt.colon)) return name;
+    var node = startNodeAt(start);
+    node.namespace = name;
+    node.name = parseJSXIdentifier();
+    return finishNode(node, "JSXNamespacedName");
+  }
+
+  // Parses element name in any form - namespaced, member
+  // or single identifier.
+
+  function parseJSXElementName() {
+    var start = storeCurrentPos();
+    var node = parseJSXNamespacedName();
+    while (eat(tt.dot)) {
+      var newNode = startNodeAt(start);
+      newNode.object = node;
+      newNode.property = parseJSXIdentifier();
+      node = finishNode(newNode, "JSXMemberExpression");
+    }
+    return node;
+  }
+
+  // Parses any type of JSX attribute value.
+
+  function parseJSXAttributeValue() {
+    return token.type === tt.braceL ? parseJSXExpressionContainer() : parseExprAtom();
+  }
+
+  // Parses JSX expression enclosed into curly brackets.
+
+  function parseJSXExpressionContainer(allowEmpty) {
+    var node = startNode();
+    pushCx();
+    next();
+    node.expression = allowEmpty && token.type === tt.braceR ? emptyNode("JSXEmptyExpression") : parseExpression();
+    popCx();
+    expect(tt.braceR);
+    return finishNode(node, "JSXExpressionContainer");
+  }
+
+  // Parses following JSX attribute name-value pair.
+
+  function parseJSXAttribute() {
+    var node = startNode();
+    if (token.type === tt.braceL) {
+      if (lookAhead(1).type === tt.ellipsis) {
+        next();
+        next();
+        node.argument = parseMaybeAssign();
+        expect(tt.braceR);
+        return finishNode(node, "JSXSpreadAttribute");
+      } else {
+        node.name = dummyIdent();
+        node.value = parseJSXAttributeValue();
+      }
+    } else {
+      node.name = parseJSXNamespacedName();
+      node.value = eat(tt.eq) ? parseJSXAttributeValue() : null;
+    }
+    return finishNode(node, "JSXAttribute");
+  }
+
+  // Parses JSX opening tag starting after '<'.
+
+  function parseJSXOpeningElementAt(start) {
+    var node = startNodeAt(start);
+    node.attributes = [];
+    node.name = parseJSXElementName();
+    while (token.type !== tt.slash && token.type !== tt.jsxTagEnd && token.type !== tt.eof) {
+      node.attributes.push(parseJSXAttribute());
+    }
+    node.selfClosing = eat(tt.slash);
+    expect(tt.jsxTagEnd);
+    if (token.type === tt.eof) node.selfClosing = true;
+    return finishNode(node, "JSXOpeningElement");
+  }
+
+  // Parses JSX closing tag starting after '</'.
+
+  function parseJSXClosingElementAt(start) {
+    var node = startNodeAt(start);
+    node.name = parseJSXElementName();
+    expect(tt.jsxTagEnd);
+    return finishNode(node, "JSXClosingElement");
+  }
+
+  // Parses entire JSX element, including it's opening tag
+  // (starting after '<'), attributes, contents and closing tag.
+
+  function parseJSXElementAt(start) {
+    var node = startNodeAt(start);
+    var children = [];
+    var openingElement = parseJSXOpeningElementAt(start);
+    var closingElement = null;
+
+    if (!openingElement.selfClosing) {
+      contents:for (;;) {
+        switch (token.type) {
+          case tt.jsxTagStart:
+            start = storeCurrentPos();
+            next();
+            if (eat(tt.slash)) {
+              closingElement = parseJSXClosingElementAt(start);
+              break contents;
+            }
+            children.push(parseJSXElementAt(start));
+            break;
+
+          case tt.braceL:
+            children.push(parseJSXExpressionContainer(true));
+            break;
+
+          case tt.eof:
+            break contents;
+
+          default:
+            children.push(parseExprAtom());
+            break;
+        }
+      }
+    }
+
+    node.openingElement = openingElement;
+    node.closingElement = closingElement;
+    node.children = children;
+    return finishNode(node, "JSXElement");
+  }
+
+  // Parses entire JSX element from current position.
+
+  function parseJSXElement() {
+    var start = storeCurrentPos();
+    next();
+    return parseJSXElementAt(start);
+  }
 });
diff --git a/test/tests-jsx.js b/test/tests-jsx.js
index e5d2999..a7dd79e 100644
--- a/test/tests-jsx.js
+++ b/test/tests-jsx.js
@@ -3604,8 +3604,7 @@ for (var ns in fbTestFixture) {
     }, {
       ecmaVersion: 6,
       locations: true,
-      ranges: true,
-      loose: false
+      ranges: true
     });
   }
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-acorn-jsx.git



More information about the Pkg-javascript-commits mailing list