Skip to content
Permalink
Browse files

Add support for ** under ecmaVersion 7

This adds support for the exponentiation operator, which is currently
Stage 4 for ES7. The supported operators are ** and **=.

Fixes #381
  • Loading branch information
nzakas authored and marijnh committed Jan 29, 2016
1 parent bed0042 commit a8ce3a12394a454484edb8c66ac697532ffcb5f7
Showing with 318 additions and 8 deletions.
  1. +2 −2 README.md
  2. +2 −1 src/bin/acorn.js
  3. +8 −0 src/expression.js
  4. +14 −4 src/tokenize.js
  5. +2 −1 src/tokentype.js
  6. +1 −0 test/run.js
  7. +289 −0 test/tests-es7.js
@@ -62,7 +62,7 @@ object referring to that same position.
[estree]: https://github.com/estree/estree

- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be
either 3, 5, or 6. This influences support for strict mode, the set
either 3, 5, 6, or 7. This influences support for strict mode, the set
of reserved words, and support for new syntax features. Default is 5.

- **sourceType**: Indicate the mode the code should be parsed in. Can be
@@ -304,7 +304,7 @@ The `bin/acorn` utility can be used to parse a file from the command
line. It accepts as arguments its input file and the following
options:

- `--ecma3|--ecma5|--ecma6`: Sets the ECMAScript version to parse. Default is
- `--ecma3|--ecma5|--ecma6|--ecma7`: Sets the ECMAScript version to parse. Default is
version 5.

- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise.
@@ -9,7 +9,7 @@ const options = {}

function help(status) {
const print = (status == 0) ? console.log : console.error
print("usage: " + basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6]")
print("usage: " + basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6|--ecma7]")
print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]")
process.exit(status)
}
@@ -21,6 +21,7 @@ for (let i = 2; i < process.argv.length; ++i) {
else if (arg == "--ecma3") options.ecmaVersion = 3
else if (arg == "--ecma5") options.ecmaVersion = 5
else if (arg == "--ecma6") options.ecmaVersion = 6
else if (arg == "--ecma7") options.ecmaVersion = 7
else if (arg == "--locations") options.locations = true
else if (arg == "--allow-hash-bang") options.allowHashBang = true
else if (arg == "--silent") silent = true
@@ -17,6 +17,7 @@
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser

import {types as tt} from "./tokentype"
import {types as tc} from "./tokencontext"
import {Parser} from "./state"

const pp = Parser.prototype
@@ -162,12 +163,19 @@ pp.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
let startPos = this.start, startLoc = this.startLoc
node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, prec, noIn)
this.finishNode(node, (op === tt.logicalOR || op === tt.logicalAND) ? "LogicalExpression" : "BinaryExpression")
if (this.options.ecmaVersion >= 7 && op === tt.starstar)
this.checkExponentiationOperand(node.left)
return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
}
}
return left
}

pp.checkExponentiationOperand = function(node) {
if (node.type === "UnaryExpression" && node.operator !== "++" && node.operator !== "--")
this.raiseRecoverable(node.start, "Base operand of ** cannot use a unary expression")
}

// Parse unary operators, both prefix and postfix.

pp.parseMaybeUnary = function(refDestructuringErrors) {
@@ -228,10 +228,20 @@ pp.readToken_slash = function() { // '/'
return this.finishOp(tt.slash, 1)
}

pp.readToken_mult_modulo = function(code) { // '%*'
pp.readToken_mult_modulo_exp = function(code) { // '%*'
let next = this.input.charCodeAt(this.pos + 1)
if (next === 61) return this.finishOp(tt.assign, 2)
return this.finishOp(code === 42 ? tt.star : tt.modulo, 1)
let size = 1
let tokentype = code === 42 ? tt.star : tt.modulo

// exponentiation operator ** and **=
if (this.options.ecmaVersion >= 7 && next === 42) {
++size
tokentype = tt.starstar
next = this.input.charCodeAt(this.pos + 2)
}

if (next === 61) return this.finishOp(tt.assign, size + 1)
return this.finishOp(tokentype, size)
}

pp.readToken_pipe_amp = function(code) { // '|&'
@@ -343,7 +353,7 @@ pp.getTokenFromCode = function(code) {
return this.readToken_slash()

case 37: case 42: // '%*'
return this.readToken_mult_modulo(code)
return this.readToken_mult_modulo_exp(code)

case 124: case 38: // '|&'
return this.readToken_pipe_amp(code)
@@ -95,7 +95,8 @@ export const types = {
plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
modulo: binop("%", 10),
star: binop("*", 10),
slash: binop("/", 10)
slash: binop("/", 10),
starstar: binop("**", 11)
}

// Map keyword names to token types.
@@ -5,6 +5,7 @@
driver = require("./driver.js");
require("./tests.js");
require("./tests-harmony.js");
require("./tests-es7.js");
require("babel-core/register")
acorn = require("../src")
require("../src/loose")

0 comments on commit a8ce3a1

Please sign in to comment.
You can’t perform that action at this time.