Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser add var decl #55

Merged
merged 15 commits into from
Aug 7, 2018
Merged

Parser add var decl #55

merged 15 commits into from
Aug 7, 2018

Conversation

katcipis
Copy link
Collaborator

@katcipis katcipis commented Aug 3, 2018

Closes #53

@katcipis katcipis self-assigned this Aug 3, 2018
@katcipis katcipis requested review from i4ki and ryukinix August 3, 2018 03:16
@codecov-io
Copy link

codecov-io commented Aug 3, 2018

Codecov Report

Merging #55 into master will increase coverage by 1.48%.
The diff coverage is 96.82%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master     #55      +/-   ##
=========================================
+ Coverage   63.61%   65.1%   +1.48%     
=========================================
  Files          19      19              
  Lines        1528    1576      +48     
=========================================
+ Hits          972    1026      +54     
+ Misses        507     502       -5     
+ Partials       49      48       -1
Impacted Files Coverage Δ
parser/parser.go 87.86% <96.82%> (+6.19%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0a2715b...aa035bc. Read the comment docs.

parser/parser.go Outdated
)

func init() {
unaryParsers = map[token.Type]parserfn{
token.Minus: parseUnary,
token.Plus: parseUnary,
}
literalParsers = map[token.Type]parserfn{
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tiago4orion I moved everything to init for the sake of consistency and also because I wrote a bug before because a variable that could be initialized outside init used the unaryParsers variable but the variable was an empty map at the time since the initialization was not on the order that the variables appeared on the code. If everything was able to be initialized outside init it would be good, but if one needs to be inside init it seems better to all the other ones to be there as well.

@katcipis katcipis changed the title WIP: Parser add var decl Parser add var decl Aug 6, 2018
Value Node
}

VarDecls []VarDecl
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

ast/node.go Outdated
@@ -76,6 +83,8 @@ const (
NodeUnaryExpr
NodeMemberExpr
NodeCallExpr
NodeVarDecl
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if(var a = 1) { console.log("hello"); }
VM99:1 Uncaught SyntaxError: Unexpected token var

simple var decl is not permitted.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get the point

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exprBegin

You defined the NodeVarDecl and NodeVarDecls beetwen exprBegin and exprEnd.
Take a look:
func IsExpr(node Node) bool {

Just need to move it out of this section.

ast/node.go Outdated
@@ -76,6 +83,8 @@ const (
NodeUnaryExpr
NodeMemberExpr
NodeCallExpr
NodeVarDecl
NodeVarDecls
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if(var a = 1, b = 2, c =3) console.log("ok")
VM85:1 Uncaught SyntaxError: Unexpected token var

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't tried to use var statements as expressions, they are being accepted right now as a bug ? I just added the var parser on the node parser, I did not realized that the parseNode function is the expression parser (it is the main entrypoint no ?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my other comment. Sorry for not being clear.

parser/parser.go Outdated
@@ -126,10 +125,10 @@ func (p *Parser) parseNode() (n ast.Node, eof bool, err error) {
// parsers should not leave tokens not processed
// in the lookahead buffer.
if len(p.lookahead) != 0 {
panic(fmt.Sprintf(
return nil, false, fmt.Errorf(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not panic? (just asking for the motivation)

Copy link
Collaborator Author

@katcipis katcipis Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the error the a test was giving was a lot harder to understand with panic, after using a error return the error was much easier to track. Since this is a bug inside the parser panic may be better but I forgot the code like this.

parser/parser.go Outdated
return _parseVarDecls(p)
}

func _parseVarDecls(p *Parser) (ast.VarDecls, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

o.o

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because I wanted to recursively build the vardecls from other vardecls but to use the function on the parserfn maps it needs to return an ast.Node. If I allow VarDecls to be built from ast.Node I would allow all sort of odd stuff to happen like var decls with other things inside (function declarations for example).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm complaining mostly about the name hehe

parser/parser.go Outdated

func _parseVarDecls(p *Parser) (ast.VarDecls, error) {

if !p.scry(2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why lookahead of 2?

var a; // no lookahead
var a = 1; // no lookahead

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point I had just "var". I dropped it since it is not necessary anymore. Now I need at least two tokens to see if it is:

  • identifier + semicolon
  • identifier + assignment (=)

How could this be written differently ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ident := p.next()
if ident.Type() != token.Ident {
	return nil, p.errorf(ident, "expected IDENT")
}

tok := p.next()
if tok.Type() == token.Semicolon {
	return ast.NewVarDecls(ast.NewVarDecl(ident.Value, ast.NewUndefined())), nil
}

if tok.Type != token.Assign {
	return nil, fmt.Errorf("parser: var decl: expected assignment token [=] got [%s]", tok)
}

// parse assignment ...

fail: true,
},
{
name: "InvalidMemberAccess",
Copy link
Contributor

@i4ki i4ki Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this test be together with memberexpr tests?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, they are just as about member expression as they are about variable initialization. Actually the objective of these tests is to check that if the parser of the member access (the one that already has been tested isolated) fails the parser for variable statements checks that error and handles it properly, so it seemed like here would be the best place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you are saying that this just test if errors are being checked ?

Copy link
Collaborator Author

@katcipis katcipis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did not understood some things =/

ast/node.go Outdated
@@ -76,6 +83,8 @@ const (
NodeUnaryExpr
NodeMemberExpr
NodeCallExpr
NodeVarDecl
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get the point

ast/node.go Outdated
@@ -76,6 +83,8 @@ const (
NodeUnaryExpr
NodeMemberExpr
NodeCallExpr
NodeVarDecl
NodeVarDecls
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't tried to use var statements as expressions, they are being accepted right now as a bug ? I just added the var parser on the node parser, I did not realized that the parseNode function is the expression parser (it is the main entrypoint no ?)

parser/parser.go Outdated
@@ -126,10 +125,10 @@ func (p *Parser) parseNode() (n ast.Node, eof bool, err error) {
// parsers should not leave tokens not processed
// in the lookahead buffer.
if len(p.lookahead) != 0 {
panic(fmt.Sprintf(
return nil, false, fmt.Errorf(
Copy link
Collaborator Author

@katcipis katcipis Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the error the a test was giving was a lot harder to understand with panic, after using a error return the error was much easier to track. Since this is a bug inside the parser panic may be better but I forgot the code like this.

parser/parser.go Outdated
return _parseVarDecls(p)
}

func _parseVarDecls(p *Parser) (ast.VarDecls, error) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because I wanted to recursively build the vardecls from other vardecls but to use the function on the parserfn maps it needs to return an ast.Node. If I allow VarDecls to be built from ast.Node I would allow all sort of odd stuff to happen like var decls with other things inside (function declarations for example).

parser/parser.go Outdated

func _parseVarDecls(p *Parser) (ast.VarDecls, error) {

if !p.scry(2) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point I had just "var". I dropped it since it is not necessary anymore. Now I need at least two tokens to see if it is:

  • identifier + semicolon
  • identifier + assignment (=)

How could this be written differently ?

fail: true,
},
{
name: "InvalidMemberAccess",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, they are just as about member expression as they are about variable initialization. Actually the objective of these tests is to check that if the parser of the member access (the one that already has been tested isolated) fails the parser for variable statements checks that error and handles it properly, so it seemed like here would be the best place.

parser/parser.go Outdated
return nil, fmt.Errorf("parser: var decl: invalid token[%s] expected comma", possibleSemiColon)
}

vars, err := _parseVarDecls(p)
Copy link
Collaborator Author

@katcipis katcipis Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to be able to do this recursion, it does not expect a "var" token and it can't return an ast.Node (not exactly can't but it don't seem like a good idea to me). The name is kinda lame but I was unable to think on something better until now. I thought about varAssigment since it parsers "a = value" not expecting the "var", but I imagine that the kind of node produced must be different since there is a difference on Javascript between declaring multiple variables starting with "var" and without (reference errors if the variable does not exist and it is not initialized).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http://es5.github.io/#x12.2

Spec call this section of declaration as VariableDeclarationList. What about parseDeclList ?

@katcipis katcipis merged commit f029e0d into master Aug 7, 2018
@katcipis katcipis deleted the parserAddVarDecl branch August 7, 2018 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants