<head>
  <title>jsparse Docs</title>
</head>

<body>
  <div id="page">
    {{> page}}
  </div>
</body>

<template name="page">

<div class="topnotes">
  <p>This is the spec for the JavaScript syntax tree returned by <code>jsparse</code>.</p>

   <p>It's notable that <em>every token</em> from the source code appears in order in this syntax tree, which
   is a Concrete Syntax Tree (CST) rather than an abstract AST.</p>
  
  {{spacer}}

  <p>The tree consists of <strong>nodes</strong>
    and <strong>tokens</strong>.  A node consists of a name followed
    by zero or more child nodes or tokens.  A token consists of
    one or more characters from the source code.</p>
  <p>For example, the following tree, which might have come from parsing <code>1 + 2</code>,
    contains nodes named <span class="str">"binary"</span>,
    <span class="str">"number"</span>, and <span class="str">"number"</span>
    and the tokens <span class="token">1</span>, <span class="token">+</span>,
    and <span class="token">2</span>:</p>
  
    <p>{{#nodespec}}["binary", ["number", `1`], `+`, ["number", `2`]]{{/nodespec}}</p>

  {{spacer}}
    
    <p>The following notation is used throughout this document to give schematic definitions of
      the different types of nodes.</p>
    
    <p>An <span class="ref">italicized</span> word refers to a list of one or more possible
      nodes or tokens that could fill a certain spot.  For example, the following is the
      definition of the <span class="str">"binary"</span> node:</p>

    <p>{{#nodespec}}["binary", expression, binaryOp, expression]{{/nodespec}}</p>

    <p>The <span class="ref">expression</span> spot could be filled by one of over 20 types
      of expression nodes, and if you look up <span class="ref">binaryOp</span> you'll see
      it refers to any of a list of binary operator tokens.</p>

    <p>A vertical bar (<span class="punc or">|</span>) separates alternatives, of which exactly
      one must be present in the tree.  An ellipsis (<span class="punc">...</span>) stands
      for a sequence of <em>zero or more</em> of the preceding item.  For example:</p>

    {{#nodespec}}["program", (statement | functionDecl), ...]{{/nodespec}}

    <p>This definition says that a program node contains zero or more items, each of which may be either a
      <span class="ref">statement</span> or a <span class="ref">functionDecl</span>.</p>

    <p>A question mark (<span class="punct">?</span>) indicates that the previous item
      (or items enclosed in parentheses) may or may not present.</p>

    <p>Token classes like <span class="tokentype">IDENTIFIER</span> match any token in the class.  The <span class="tokentype">BOOLEAN</span>, <span class="tokentype">NUMBER</span>, <span class="tokentype">STRING</span>, and <span class="tokentype">REGEX</span> classes are all literals.  An example <span class="tokentype">STRING</span> would be <span class="token">"hello"</span>.

      {{spacer}}

     <p>Some definitions with ellipses may seem strangely permissive, such as:</p>

  {{#nodespec}}["varStmnt", `var`, (varDecl | `,`), ..., semi]{{/nodespec}}

     <p>This seems to say that <code>var;</code> and <code>var,,x,</code> are valid statements.
       The reason for this style of definition is to discourage reliance on exact comma
       positions, which may occasionally vary between JavaScript implementations and versions.
       For example, the 5th edition of ECMAScript allows a trailing comma in object literals whereas
       the 3rd edition doesn't.</p>

     <p>For most applications, the commas aren't that important, and you can read all the varDecls
       by just skipping any commas you encounter.</p>
      
</div>

{{#nodespec}}program:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["program", (statement | functionDecl), ...]{{/nodespec}}
</div>

{{#nodespec}}statement:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["expressionStmnt", expression, semi]{{/nodespec}}
  <div class="explan">
    <p>Function calls and assignments are expressions.</p>
  </div>
  {{#nodespec}}["emptyStmnt", `;`]{{/nodespec}}
  <div class="explan">
    <p>Only an actual <span class="token">;</span> token can create an empty statement.</p>
  </div>
  {{#nodespec}}["blockStmnt", `{`, statement, ..., `}`]{{/nodespec}}
  {{#nodespec}}["varStmnt", `var`, (varDecl | `,`), ..., semi]{{/nodespec}}
  <div class="explan">
    <p>You can assume at least one varDecl is present.</p>
  </div>
  {{#nodespec}}["ifStmnt", `if`, `(`, expression, `)`, statement, (`else`, statement)?]{{/nodespec}}
  {{#nodespec}}["whileStmnt", `while`, `(`, expression, `)`, statement]{{/nodespec}}
  {{#nodespec}}["doStmnt", `do`, statement, `while`, `(`, expression, `)`, semi]{{/nodespec}}
  {{#nodespec}}["forStmnt", `for`, `(`, forSpec, `)`, statement]{{/nodespec}}
  {{#nodespec}}["returnStmnt", `return`, (expression | nil), semi]{{/nodespec}}
  {{#nodespec}}["continueStmnt", `continue`, (IDENTIFIER | nil), semi]{{/nodespec}}
  {{#nodespec}}["breakStmnt", `break`, (IDENTIFIER | nil), semi]{{/nodespec}}
  {{#nodespec}}["throwStmnt", `throw`, expression, semi]{{/nodespec}}
  {{#nodespec}}["withStmnt", `with`, `(`, expression, `)`, statement]{{/nodespec}}
  {{#nodespec}}["switchStmnt", `switch`, `(`, expression, `)`, `{`, (case | default), ..., `}`]{{/nodespec}}
  <div class="explan">
    <p>There's at most one default clause, but it can be anywhere in the list of cases and defaults.</p>
  </div>
  {{#nodespec}}["tryStmnt", `try`, statement, (catch | nil), (finally | nil)]{{/nodespec}}
  <div class="explan">
    <p>The statement is always a blockStmnt.</p>
  </div>
  {{#nodespec}}["labelStmnt", IDENTIFIER, `:`, statement]{{/nodespec}}
  {{#nodespec}}["debuggerStmnt", `debugger`, semi]{{/nodespec}}
</div>

{{#nodespec}}functionDecl:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["functionDecl", `function`, IDENTIFIER, `(`, (IDENTIFIER | `,`), ..., `)`, `{`, (statement | functionDecl), ..., `}`]{{/nodespec}}
  <div class="explan">
    <p>Different from a functionExpr only in that the function name is required and not optional.</p>
  </div>
</div>

{{#nodespec}}expression:{{/nodespec}}
<div class="indent">
{{#nodespec}}["this", `this`]{{/nodespec}}
{{#nodespec}}["null", `null`]{{/nodespec}}
{{#nodespec}}["number", NUMBER]{{/nodespec}}
{{#nodespec}}["boolean", BOOLEAN]{{/nodespec}}
{{#nodespec}}["regex", REGEX]{{/nodespec}}
{{#nodespec}}["string", STRING]{{/nodespec}}
{{#nodespec}}["identifier", IDENTIFIER]{{/nodespec}}
{{#nodespec}}["parens", `(`, expression, `)`]{{/nodespec}}
{{#nodespec}}["array", `[`, (expression | `,`), ..., `]`]{{/nodespec}}
  <div class="explan">
    <p>All commas are significant because of element elision, and any
      combination of commas and expressions is possible.
    The array <code>[,,,7,,8,,]</code> has 7 and 8 as
    its 3rd and 5th elements.</p>
  </div>
{{#nodespec}}["object", `{`, (prop | `,`), ..., `}`]{{/nodespec}}
{{#nodespec}}["functionExpr", `function`, (IDENTIFIER | nil), `(`, (IDENTIFIER | `,`), ..., `)`, `{`, (statement | functionDecl), ..., `}`]{{/nodespec}}
{{#nodespec}}["dot", expression, `.`, identifierName]{{/nodespec}}
{{#nodespec}}["bracket", expression, `[`, expression, `]`]{{/nodespec}}
{{#nodespec}}["call", expression, `(`, (expression | `,`), ...,  `)`]{{/nodespec}}
{{#nodespec}}["new", `new`, expression]{{/nodespec}}
{{#nodespec}}["newcall", `new`, expression, `(`, (expression | `,`), ...,  `)`]{{/nodespec}}
{{#nodespec}}["unary", unaryOp, expression]{{/nodespec}}
{{#nodespec}}["binary", expression, binaryOp, expression]{{/nodespec}}
{{#nodespec}}["postfix", expression, postfixOp]{{/nodespec}}
{{#nodespec}}["ternary", expression, `?`, expression, `:`, expression]{{/nodespec}}
{{#nodespec}}["assignment", expression, assignmentOp, expression]{{/nodespec}}
<div class="explan">
<p>There is no simple constraint on what the first expression can be.
  A left-hand-side expression could be a simple identifier like <code>foo</code>,
or it could be any expression ending in a property access, such as <code>foo().bar[baz]</code>.
Parentheses are also allowed around the left-hand side, so surprisingly <code>((x)) = 3</code>
is completely legal and equivalent to <code>x = 3</code>.  This is because
JavaScript evaluates the left-hand side all the way down to the final variable reference.</p>
</div>
{{#nodespec}}["comma", (expression | `,`), ...]{{/nodespec}}
<div class="explan"><p>You can assume there are at least two expressions, since there would have been no comma otherwise.</p></div>
</div>

{{#nodespec}}nil:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["nil"]{{/nodespec}}
  <div class="explan"><p>Serves as a placeholder for optional parts of nodes.</p></div>
</div>

{{#nodespec}}semi:{{/nodespec}}
<div class="indent">
  {{#nodespec}}[";"] | `;`{{/nodespec}}
  <div class="explan">
    <p>An optional semicolon at the end of a statement.  Most semicolons in JavaScript can legally
    be omitted if a line break follows.  If the semicolon was omitted, a <span class="str">";"</span>
    node takes its place.</p>
  </div>
</div>

{{#nodespec}}prop:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["prop", propertyName, `:`, expression]{{/nodespec}}
</div>

{{#nodespec}}propertyName:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["idPropName", identifierName]{{/nodespec}}
  {{#nodespec}}["strPropName", STRING]{{/nodespec}}
  {{#nodespec}}["numPropName", NUMBER]{{/nodespec}}
  <div class="explan">
    <p>A property name in an object literal can be given as a bare identifier, a quoted string literal,
    or a number literal.  These nodes indicate which it is.</p>
  </div>
</div>

{{#nodespec}}varDecl:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["varDecl", IDENTIFIER, (`=`, expression)?]{{/nodespec}}
</div>

{{#nodespec}}forSpec:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["forSpec", (expression | nil), `;`, (expression | nil), `;`, (expression | nil)]{{/nodespec}}
  {{#nodespec}}["forVarSpec", `var`, (varDecl | `,`), ..., `;`, (expression | nil), `;`, (expression | nil)]{{/nodespec}}
  {{#nodespec}}["forInSpec", expression, `in`, expression]{{/nodespec}}
  {{#nodespec}}["forVarInSpec", `var`, varDecl, `in`, expression]{{/nodespec}}
  <div class="explan">
    <p>There are technically four types of for-loops in JavaScript.</p>
      <p>These definitions suggest some
      odd possibilities, and interestingly, they work.  The form <code>for (x.foo in y)</code> will actually
      set <code>x.foo</code> each time through the loop, and <code>for (var x = bar() in y)</code> will call
      <code>bar()</code> and assign it first thing,
      even if <code>x</code> is immediately overwritten before the first iteration of the loop.</p>
    <p>The semicolons are mandatory, even at a line break.</p>
  </div>
</div>

{{#nodespec}}case:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["case", `case`, expression, `:`, statement, ...]{{/nodespec}}
</div>

{{#nodespec}}default:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["default", `default`, `:`, statement, ...]{{/nodespec}}
</div>

{{#nodespec}}catch:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["catch", `catch`, `(`, IDENTIFIER, `)`, statement]{{/nodespec}}
  <div class="explan">
    <p>The statement is always a blockStmnt.</p>
  </div>
</div>

{{#nodespec}}finally:{{/nodespec}}
<div class="indent">
  {{#nodespec}}["finally", `finally`, statement]{{/nodespec}}
  <div class="explan">
    <p>The statement is always a blockStmnt.</p>
  </div>
</div>

{{#nodespec}}identifierName:{{/nodespec}}
<div class="indent">
  {{#nodespec}}(IDENTIFIER | KEYWORD | BOOLEAN | `null`){{/nodespec}}
  <div class="explan">
    <p>As of ECMAScript 5th edition, keywords and reserved words can be used in some places
      where an identifier is expected.  For example, <code>x.return()</code> or
      <code>{true: 'yes'}</code>.</p>
  </div>
</div>

{{#nodespec}}unaryOp:{{/nodespec}}
<div class="indent">
  {{#nodespec}}(`delete` | `void` | `typeof` | `++` | `--` | `+` | `-` | `~` | `!`){{/nodespec}}
</div>

{{#nodespec}}binaryOp:{{/nodespec}}
<div class="indent">
  {{#nodespec}}(`*` | `/` | `%` | `+` | `-` | `<<` | `>>` | `>>>` | `<` | `>` | `<=` | `>=` | `instanceof` | `in` | `==` | `!=` | `===` | `!==` | `&` | `^` | `|` | `&&` | `||`){{/nodespec}}
</div>

{{#nodespec}}postfixOp:{{/nodespec}}
<div class="indent">
  {{#nodespec}}(`++` | `--`){{/nodespec}}
</div>

{{#nodespec}}assignmentOp:{{/nodespec}}
<div class="indent">
  {{#nodespec}}(`=` | `*=` | `/=` | `%=` | `+=` | `-=` | `<<=` | `>>=` | `>>>=` | `&=` | `^=` | `|=`){{/nodespec}}
</div>

</template>
