Boa: Arrow Function Parsing fails

Created on 3 Jan 2021  路  7Comments  路  Source: boa-dev/boa

ECMASCript feature
ES6 Arrow functions

Example code
Give a code example that should work after the implementation of this feature.

This code should now work and give the expected result:

let a = "Hello";
let thing = (b) => a + b;
thing(" World!");

The expected output is Hello World!.

bug parser

Most helpful comment

Maybe @Lan2u wants to add some comments on this, as he worked on the lexer/parser.

I created a branch arrow_parse which allows peeking ahead 3 (rather than 2) tokens and that allows handling the case of let foo = (a) => { return a }; (the existing code had a bug where we peeked the same position (2 ahead) twice while expecting a different value without a next() in between).

All 7 comments

As an heads up, Arrow Functions are partly implemented, as an example:

let a = "Hello";
let thing = b => a + b;
thing(" World!")

Does return "Hello World!". Seems that having the parenthesis around the arguments isn't accepted by Boa.

This seems to be a bug in the parser, that we knew it's there. The issue is that it's not possible to know if we are working with an expression or not after an assignment.

This is controlled in here. The ideal situation would be to have a lever that can move to an arbitrary position. That way, we can try to parse an arrow function (or an expression), and if we fail, we go back and try to parse the other.

Some situations are covered by the current implementation, but not all.

@Razican Maybe we don't need the cursor to move to an arbitrary position. What we need is to "clone" the cursor state and we can do something like:

let next_cursor = cursor.clone();
if let Ok(...) = option1.parse(new_cursor) {
    let cursor = new_cursor;
    next_parser.parse(cursor)?;
} else {
    option2.parse(cursor)?;
}

@Razican Maybe we don't need the cursor to move to an arbitrary position. What we need is to "clone" the cursor state and we can do something like:

let next_cursor = cursor.clone();
if let Ok(...) = option1.parse(new_cursor) {
    let cursor = new_cursor;
    next_parser.parse(cursor)?;
} else {
    option2.parse(cursor)?;
}

The thing is that a cursor is just a wrapper over a Read. Maybe if we made sure that the inner buffer was Seek too, we would be able to create snapshots or something similar, with the position, goal symbol and so on, and return to the previous state.

This means that if we wanted to create a cursor over &[u8] or a &str, we would need to wrap them in an std::io::Cursor. We could create helpers for those.

Maybe @Lan2u wants to add some comments on this, as he worked on the lexer/parser.

As an heads up, Arrow Functions are partly implemented, as an example:

let a = "Hello";
let thing = b => a + b;
thing(" World!")

Does return "Hello World!". Seems that having the parenthesis around the arguments isn't accepted by Boa.

As far as I can tell the only area it isn't implemented is for a single argument with parenthesis

let foo = (a, b) => { return a + b };
foo(1,1);
// Works
let x = a => {return a * 2};
x(1)
// Works
let z = (a, b) => a + b;
z(10, 20)
// Works
let z = (a) => { return a * 3 };
// Syntax error

Maybe @Lan2u wants to add some comments on this, as he worked on the lexer/parser.

I created a branch arrow_parse which allows peeking ahead 3 (rather than 2) tokens and that allows handling the case of let foo = (a) => { return a }; (the existing code had a bug where we peeked the same position (2 ahead) twice while expecting a different value without a next() in between).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HalidOdat picture HalidOdat  路  3Comments

jasonwilliams picture jasonwilliams  路  6Comments

HalidOdat picture HalidOdat  路  5Comments

joshwd36 picture joshwd36  路  4Comments

AnirudhKonduru picture AnirudhKonduru  路  3Comments