Skip to content

Commit

Permalink
fix: positions of expressions (#505)
Browse files Browse the repository at this point in the history
Fix Idx1 of ConditionalExpression so that it points to the next character after alternate expression.
Fix Idx1 of SequenceExpression to return Idx1 of the last sequence element, not first.
Fix Idx0 of unary expression to point to the start of operand in case of a postfix operator.
Fix Idx1 of VariableExpression so that it points to the character right after the name literal if the
expression does not have an initializer.
  • Loading branch information
tyamagu2 committed Jul 21, 2023
1 parent d2ed0a7 commit 589611c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
9 changes: 6 additions & 3 deletions ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (ce *ConditionalExpression) Idx0() file.Idx {

// Idx1 implements Node.
func (ce *ConditionalExpression) Idx1() file.Idx {
return ce.Test.Idx1()
return ce.Alternate.Idx1()
}

// expression implements Expression.
Expand Down Expand Up @@ -397,7 +397,7 @@ func (se *SequenceExpression) Idx0() file.Idx {

// Idx1 implements Node.
func (se *SequenceExpression) Idx1() file.Idx {
return se.Sequence[0].Idx1()
return se.Sequence[len(se.Sequence)-1].Idx1()
}

// expression implements Expression.
Expand Down Expand Up @@ -451,6 +451,9 @@ type UnaryExpression struct {

// Idx0 implements Node.
func (ue *UnaryExpression) Idx0() file.Idx {
if ue.Postfix {
return ue.Operand.Idx0()
}
return ue.Idx
}

Expand Down Expand Up @@ -480,7 +483,7 @@ func (ve *VariableExpression) Idx0() file.Idx {
// Idx1 implements Node.
func (ve *VariableExpression) Idx1() file.Idx {
if ve.Initializer == nil {
return file.Idx(int(ve.Idx) + len(ve.Name) + 1)
return file.Idx(int(ve.Idx) + len(ve.Name))
}
return ve.Initializer.Idx1()
}
Expand Down
4 changes: 2 additions & 2 deletions parser/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ func (p *parser) parseLogicalOrExpression() ast.Expression {
return left
}

func (p *parser) parseConditionlExpression() ast.Expression {
func (p *parser) parseConditionalExpression() ast.Expression {
left := p.parseLogicalOrExpression()

if p.token == token.QUESTION_MARK {
Expand All @@ -911,7 +911,7 @@ func (p *parser) parseConditionlExpression() ast.Expression {
}

func (p *parser) parseAssignmentExpression() ast.Expression {
left := p.parseConditionlExpression()
left := p.parseConditionalExpression()
var operator token.Token
switch p.token {
case token.ASSIGN:
Expand Down
44 changes: 44 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,50 @@ func TestPosition(t *testing.T) {
node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ArrayLiteral)
is(node.Idx0(), 5)
is(parser.slice(node.Idx0(), node.Idx1()), "[1, 2]")

parser = newParser("", "x = true ? 1 : 2", 1, nil)
program, err = parser.parse()
is(err, nil)
node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ConditionalExpression)
is(node.Idx0(), 5)
is(parser.slice(node.Idx0(), node.Idx1()), "true ? 1 : 2")

parser = newParser("", "(function(){ x = 1, y = 2; })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.ExpressionStatement).Expression.(*ast.SequenceExpression)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "x = 1, y = 2")

parser = newParser("", "x = ~x", 1, nil)
program, err = parser.parse()
is(err, nil)
node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.UnaryExpression)
is(node.Idx0(), 5)
is(parser.slice(node.Idx0(), node.Idx1()), "~x")

parser = newParser("", "(function(){ xyz++; })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "xyz++")

parser = newParser("", "(function(){ var abc, xyz = 1; })", 1, nil)
program, err = parser.parse()
is(err, nil)
block = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)
node = block.List[0].(*ast.VariableStatement)
is(node.Idx0(), 14)
is(parser.slice(node.Idx0(), node.Idx1()), "var abc, xyz = 1")
node = block.List[0].(*ast.VariableStatement).List[0].(*ast.VariableExpression)
is(node.Idx0(), 18)
is(parser.slice(node.Idx0(), node.Idx1()), "abc")
node = block.List[0].(*ast.VariableStatement).List[1].(*ast.VariableExpression)
is(node.Idx0(), 23)
is(parser.slice(node.Idx0(), node.Idx1()), "xyz = 1")
})
}

Expand Down

0 comments on commit 589611c

Please sign in to comment.