简体   繁体   中英

Unable to parse function with Esprima/Acorn: unexpected token '('

I am able to parse arrow functions using Esprima and Acorn, but using normal functions gives an error:

const esprima = require('esprima');
const acorn = require('acorn');

console.log(esprima.parseScript(` () => { console.log('Test')}`)); //works
console.log(acorn.parse(` () => { console.log('Test') }`); //works

console.log(esprima.parseScript(`function () { console.log('Test')}`)); // Unexpected token
console.log(acorn.parse(`function () { console.log('Test') }`); //Unexpected token

Any suggestions?

tl;dr

If the line begins with the token function , it is a FunctionDeclaration , not a FunctionExpression . And a function declaration requires an identifier (in a FunctionExpression it is optional ).

--------

The way that function () { console.log('Test') } code is written, makes it a function declaration ( FunctionDeclaration ) , not a function expression. And a function declaration expects an identifier (in a function expression it is optional ).

Try it in Chrome console, you'll get the same error.

To understand, you'll have to look into the grammar os ES6 (more below).

The () => {} ( ArrowFunction ) is always an expression (specifically, believe it or not, an AssignmentExpression ).


A JavaScript, in ES6, Script is roughly a sequence of statements ( StatementList , which is a sequence of StatementListItem s).

A StatementListItem is a Statement or a Declaration .

Between Statement or a Declaration , the only possible expression is ExpressionStatement .

ExpressionStatement is nothing more than an Expression .

And in Expression you find the FunctionExpression .

Because they start with the same token, I believe the FunctionDeclaration takes precedence over the FunctionExpression (the former is "less deep" down the grammar). So the parser consumes the token function an expects the FunctionDeclaration to continue, throwing the error.


Getting rid of the error

You can add an identifier, fulfilling the FunctionDeclaration 's requirements:

console.log(esprima.parseScript(`function test() { console.log('Test')}`));
console.log(acorn.parse(`function test() { console.log('Test') }`);

But, again, that makes it a FunctionDeclaration. To make your code a function expression alone, as pointed by @JaredSmith in comments , wrap it into ( / ) s:

console.log(esprima.parseScript(`(function () { console.log('Test')} )`));
console.log(acorn.parse(`(function () { console.log('Test') } )`);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM