mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-07 11:04:17 +00:00
fix nil exceptions with incomplete code parse
This makes the parser more fault tolerant because the different parse_foo procs return nil when in an invalid state, which is fine most of the time but when creating a node it would crash accessing its position.
This commit is contained in:
@@ -7,7 +7,7 @@ import "core:reflect"
|
|||||||
import "core:odin/tokenizer"
|
import "core:odin/tokenizer"
|
||||||
_ :: intrinsics
|
_ :: intrinsics
|
||||||
|
|
||||||
new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T {
|
new_from_positions :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T {
|
||||||
n, _ := mem.new(T)
|
n, _ := mem.new(T)
|
||||||
n.pos = pos
|
n.pos = pos
|
||||||
n.end = end
|
n.end = end
|
||||||
@@ -23,6 +23,15 @@ new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_from_pos_and_end_node :: proc($T: typeid, pos: tokenizer.Pos, end: ^Node) -> ^T {
|
||||||
|
return new(T, pos, end != nil ? end.end : {})
|
||||||
|
}
|
||||||
|
|
||||||
|
new :: proc {
|
||||||
|
new_from_positions,
|
||||||
|
new_from_pos_and_end_node,
|
||||||
|
}
|
||||||
|
|
||||||
clone :: proc{
|
clone :: proc{
|
||||||
clone_node,
|
clone_node,
|
||||||
clone_expr,
|
clone_expr,
|
||||||
|
|||||||
@@ -787,7 +787,10 @@ parse_if_stmt :: proc(p: ^Parser) -> ^ast.If_Stmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end := body.end
|
end: tokenizer.Pos
|
||||||
|
if body != nil {
|
||||||
|
end = body.end
|
||||||
|
}
|
||||||
if else_stmt != nil {
|
if else_stmt != nil {
|
||||||
end = else_stmt.end
|
end = else_stmt.end
|
||||||
}
|
}
|
||||||
@@ -850,7 +853,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
body = parse_body(p)
|
body = parse_body(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end)
|
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body)
|
||||||
range_stmt.for_pos = tok.pos
|
range_stmt.for_pos = tok.pos
|
||||||
range_stmt.in_pos = in_tok.pos
|
range_stmt.in_pos = in_tok.pos
|
||||||
range_stmt.expr = rhs
|
range_stmt.expr = rhs
|
||||||
@@ -910,7 +913,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
rhs = assign_stmt.rhs[0]
|
rhs = assign_stmt.rhs[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end)
|
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body)
|
||||||
range_stmt.for_pos = tok.pos
|
range_stmt.for_pos = tok.pos
|
||||||
range_stmt.vals = vals
|
range_stmt.vals = vals
|
||||||
range_stmt.in_pos = assign_stmt.op.pos
|
range_stmt.in_pos = assign_stmt.op.pos
|
||||||
@@ -920,7 +923,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cond_expr := convert_stmt_to_expr(p, cond, "boolean expression")
|
cond_expr := convert_stmt_to_expr(p, cond, "boolean expression")
|
||||||
for_stmt := ast.new(ast.For_Stmt, tok.pos, body.end)
|
for_stmt := ast.new(ast.For_Stmt, tok.pos, body)
|
||||||
for_stmt.for_pos = tok.pos
|
for_stmt.for_pos = tok.pos
|
||||||
for_stmt.init = init
|
for_stmt.init = init
|
||||||
for_stmt.cond = cond_expr
|
for_stmt.cond = cond_expr
|
||||||
@@ -976,7 +979,7 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
lhs[0] = new_blank_ident(p, tok.pos)
|
lhs[0] = new_blank_ident(p, tok.pos)
|
||||||
rhs[0] = parse_expr(p, true)
|
rhs[0] = parse_expr(p, true)
|
||||||
|
|
||||||
as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0].end)
|
as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0])
|
||||||
as.lhs = lhs
|
as.lhs = lhs
|
||||||
as.op = in_tok
|
as.op = in_tok
|
||||||
as.rhs = rhs
|
as.rhs = rhs
|
||||||
@@ -1010,14 +1013,14 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
body.stmts = clauses[:]
|
body.stmts = clauses[:]
|
||||||
|
|
||||||
if is_type_switch {
|
if is_type_switch {
|
||||||
ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body.end)
|
ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body)
|
||||||
ts.tag = tag
|
ts.tag = tag
|
||||||
ts.body = body
|
ts.body = body
|
||||||
ts.switch_pos = tok.pos
|
ts.switch_pos = tok.pos
|
||||||
return ts
|
return ts
|
||||||
} else {
|
} else {
|
||||||
cond := convert_stmt_to_expr(p, tag, "switch expression")
|
cond := convert_stmt_to_expr(p, tag, "switch expression")
|
||||||
ts := ast.new(ast.Switch_Stmt, tok.pos, body.end)
|
ts := ast.new(ast.Switch_Stmt, tok.pos, body)
|
||||||
ts.init = init
|
ts.init = init
|
||||||
ts.cond = cond
|
ts.cond = cond
|
||||||
ts.body = body
|
ts.body = body
|
||||||
@@ -1044,7 +1047,7 @@ parse_attribute :: proc(p: ^Parser, tok: tokenizer.Token, open_kind, close_kind:
|
|||||||
if p.curr_tok.kind == .Eq {
|
if p.curr_tok.kind == .Eq {
|
||||||
eq := expect_token(p, .Eq)
|
eq := expect_token(p, .Eq)
|
||||||
value := parse_value(p)
|
value := parse_value(p)
|
||||||
fv := ast.new(ast.Field_Value, elem.pos, value.end)
|
fv := ast.new(ast.Field_Value, elem.pos, value)
|
||||||
fv.field = elem
|
fv.field = elem
|
||||||
fv.sep = eq.pos
|
fv.sep = eq.pos
|
||||||
fv.value = value
|
fv.value = value
|
||||||
@@ -1137,7 +1140,7 @@ parse_foreign_block :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Foreign_Bl
|
|||||||
body.stmts = decls[:]
|
body.stmts = decls[:]
|
||||||
body.close = close.pos
|
body.close = close.pos
|
||||||
|
|
||||||
decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body.end)
|
decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body)
|
||||||
decl.docs = docs
|
decl.docs = docs
|
||||||
decl.tok = tok
|
decl.tok = tok
|
||||||
decl.foreign_library = foreign_library
|
decl.foreign_library = foreign_library
|
||||||
@@ -1248,7 +1251,7 @@ parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast
|
|||||||
return ast.new(ast.Bad_Stmt, inline_tok.pos, end_pos(p.prev_tok))
|
return ast.new(ast.Bad_Stmt, inline_tok.pos, end_pos(p.prev_tok))
|
||||||
}
|
}
|
||||||
|
|
||||||
range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body.end)
|
range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body)
|
||||||
range_stmt.inline_pos = inline_tok.pos
|
range_stmt.inline_pos = inline_tok.pos
|
||||||
range_stmt.for_pos = for_tok.pos
|
range_stmt.for_pos = for_tok.pos
|
||||||
range_stmt.val0 = val0
|
range_stmt.val0 = val0
|
||||||
@@ -1304,7 +1307,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
case ^ast.Return_Stmt:
|
case ^ast.Return_Stmt:
|
||||||
error(p, s.pos, "you cannot defer a return statement")
|
error(p, s.pos, "you cannot defer a return statement")
|
||||||
}
|
}
|
||||||
ds := ast.new(ast.Defer_Stmt, tok.pos, stmt.end)
|
ds := ast.new(ast.Defer_Stmt, tok.pos, stmt)
|
||||||
ds.stmt = stmt
|
ds.stmt = stmt
|
||||||
return ds
|
return ds
|
||||||
|
|
||||||
@@ -1341,8 +1344,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
if tok.kind != .Fallthrough && p.curr_tok.kind == .Ident {
|
if tok.kind != .Fallthrough && p.curr_tok.kind == .Ident {
|
||||||
label = parse_ident(p)
|
label = parse_ident(p)
|
||||||
}
|
}
|
||||||
end := label.end if label != nil else end_pos(tok)
|
s := ast.new(ast.Branch_Stmt, tok.pos, label)
|
||||||
s := ast.new(ast.Branch_Stmt, tok.pos, end)
|
|
||||||
s.tok = tok
|
s.tok = tok
|
||||||
s.label = label
|
s.label = label
|
||||||
expect_semicolon(p, s)
|
expect_semicolon(p, s)
|
||||||
@@ -1366,7 +1368,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
if p.curr_tok.kind != .Colon {
|
if p.curr_tok.kind != .Colon {
|
||||||
end := list[len(list)-1]
|
end := list[len(list)-1]
|
||||||
expect_semicolon(p, end)
|
expect_semicolon(p, end)
|
||||||
us := ast.new(ast.Using_Stmt, tok.pos, end.end)
|
us := ast.new(ast.Using_Stmt, tok.pos, end)
|
||||||
us.list = list
|
us.list = list
|
||||||
return us
|
return us
|
||||||
}
|
}
|
||||||
@@ -1416,13 +1418,13 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
bd.tok = tok
|
bd.tok = tok
|
||||||
bd.name = name
|
bd.name = name
|
||||||
ce := parse_call_expr(p, bd)
|
ce := parse_call_expr(p, bd)
|
||||||
es := ast.new(ast.Expr_Stmt, ce.pos, ce.end)
|
es := ast.new(ast.Expr_Stmt, ce.pos, ce)
|
||||||
es.expr = ce
|
es.expr = ce
|
||||||
return es
|
return es
|
||||||
|
|
||||||
case "force_inline", "force_no_inline":
|
case "force_inline", "force_no_inline":
|
||||||
expr := parse_inlining_operand(p, true, tag)
|
expr := parse_inlining_operand(p, true, tag)
|
||||||
es := ast.new(ast.Expr_Stmt, expr.pos, expr.end)
|
es := ast.new(ast.Expr_Stmt, expr.pos, expr)
|
||||||
es.expr = expr
|
es.expr = expr
|
||||||
return es
|
return es
|
||||||
case "unroll":
|
case "unroll":
|
||||||
@@ -1444,7 +1446,8 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
return ast.new(ast.Bad_Stmt, tok.pos, end_pos(tag))
|
return ast.new(ast.Bad_Stmt, tok.pos, end_pos(tag))
|
||||||
case:
|
case:
|
||||||
stmt := parse_stmt(p)
|
stmt := parse_stmt(p)
|
||||||
te := ast.new(ast.Tag_Stmt, tok.pos, stmt.pos)
|
end := stmt.pos if stmt != nil else end_pos(tok)
|
||||||
|
te := ast.new(ast.Tag_Stmt, tok.pos, end)
|
||||||
te.op = tok
|
te.op = tok
|
||||||
te.name = name
|
te.name = name
|
||||||
te.stmt = stmt
|
te.stmt = stmt
|
||||||
@@ -1572,7 +1575,7 @@ convert_stmt_to_body :: proc(p: ^Parser, stmt: ^ast.Stmt) -> ^ast.Stmt {
|
|||||||
error(p, stmt.pos, "expected a non-empty statement")
|
error(p, stmt.pos, "expected a non-empty statement")
|
||||||
}
|
}
|
||||||
|
|
||||||
bs := ast.new(ast.Block_Stmt, stmt.pos, stmt.end)
|
bs := ast.new(ast.Block_Stmt, stmt.pos, stmt)
|
||||||
bs.open = stmt.pos
|
bs.open = stmt.pos
|
||||||
bs.stmts = make([]^ast.Stmt, 1)
|
bs.stmts = make([]^ast.Stmt, 1)
|
||||||
bs.stmts[0] = stmt
|
bs.stmts[0] = stmt
|
||||||
@@ -1741,7 +1744,7 @@ parse_var_type :: proc(p: ^Parser, flags: ast.Field_Flags) -> ^ast.Expr {
|
|||||||
error(p, tok.pos, "variadic field missing type after '..'")
|
error(p, tok.pos, "variadic field missing type after '..'")
|
||||||
type = ast.new(ast.Bad_Expr, tok.pos, end_pos(tok))
|
type = ast.new(ast.Bad_Expr, tok.pos, end_pos(tok))
|
||||||
}
|
}
|
||||||
e := ast.new(ast.Ellipsis, type.pos, type.end)
|
e := ast.new(ast.Ellipsis, type.pos, type)
|
||||||
e.expr = type
|
e.expr = type
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
@@ -1808,7 +1811,7 @@ parse_ident_list :: proc(p: ^Parser, allow_poly_names: bool) -> []^ast.Expr {
|
|||||||
if is_blank_ident(ident) {
|
if is_blank_ident(ident) {
|
||||||
error(p, ident.pos, "invalid polymorphic type definition with a blank identifier")
|
error(p, ident.pos, "invalid polymorphic type definition with a blank identifier")
|
||||||
}
|
}
|
||||||
poly_name := ast.new(ast.Poly_Type, tok.pos, ident.end)
|
poly_name := ast.new(ast.Poly_Type, tok.pos, ident)
|
||||||
poly_name.type = ident
|
poly_name.type = ident
|
||||||
append(&list, poly_name)
|
append(&list, poly_name)
|
||||||
} else {
|
} else {
|
||||||
@@ -2154,7 +2157,7 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^
|
|||||||
e.inlining = pi
|
e.inlining = pi
|
||||||
case:
|
case:
|
||||||
error(p, tok.pos, "'%s' must be followed by a procedure literal or call", tok.text)
|
error(p, tok.pos, "'%s' must be followed by a procedure literal or call", tok.text)
|
||||||
return ast.new(ast.Bad_Expr, tok.pos, expr.end)
|
return ast.new(ast.Bad_Expr, tok.pos, expr)
|
||||||
}
|
}
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
@@ -2204,7 +2207,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
case .Distinct:
|
case .Distinct:
|
||||||
tok := advance_token(p)
|
tok := advance_token(p)
|
||||||
type := parse_type(p)
|
type := parse_type(p)
|
||||||
dt := ast.new(ast.Distinct_Type, tok.pos, type.end)
|
dt := ast.new(ast.Distinct_Type, tok.pos, type)
|
||||||
dt.tok = tok.kind
|
dt.tok = tok.kind
|
||||||
dt.type = type
|
dt.type = type
|
||||||
return dt
|
return dt
|
||||||
@@ -2215,7 +2218,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
switch name.text {
|
switch name.text {
|
||||||
case "type":
|
case "type":
|
||||||
type := parse_type(p)
|
type := parse_type(p)
|
||||||
hp := ast.new(ast.Helper_Type, tok.pos, type.end)
|
hp := ast.new(ast.Helper_Type, tok.pos, type)
|
||||||
hp.tok = tok.kind
|
hp.tok = tok.kind
|
||||||
hp.type = type
|
hp.type = type
|
||||||
return hp
|
return hp
|
||||||
@@ -2319,7 +2322,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
tag_call := parse_call_expr(p, tag)
|
tag_call := parse_call_expr(p, tag)
|
||||||
type := parse_type(p)
|
type := parse_type(p)
|
||||||
|
|
||||||
rt := ast.new(ast.Relative_Type, tok.pos, type.end)
|
rt := ast.new(ast.Relative_Type, tok.pos, type)
|
||||||
rt.tag = tag_call
|
rt.tag = tag_call
|
||||||
rt.type = type
|
rt.type = type
|
||||||
return rt
|
return rt
|
||||||
@@ -2328,7 +2331,8 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
return parse_inlining_operand(p, lhs, name)
|
return parse_inlining_operand(p, lhs, name)
|
||||||
case:
|
case:
|
||||||
expr := parse_expr(p, lhs)
|
expr := parse_expr(p, lhs)
|
||||||
te := ast.new(ast.Tag_Expr, tok.pos, expr.pos)
|
end := expr.pos if expr != nil else end_pos(tok)
|
||||||
|
te := ast.new(ast.Tag_Expr, tok.pos, end)
|
||||||
te.op = tok
|
te.op = tok
|
||||||
te.name = name.text
|
te.name = name.text
|
||||||
te.expr = expr
|
te.expr = expr
|
||||||
@@ -2456,7 +2460,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
case .Pointer:
|
case .Pointer:
|
||||||
tok := expect_token(p, .Pointer)
|
tok := expect_token(p, .Pointer)
|
||||||
elem := parse_type(p)
|
elem := parse_type(p)
|
||||||
ptr := ast.new(ast.Pointer_Type, tok.pos, elem.end)
|
ptr := ast.new(ast.Pointer_Type, tok.pos, elem)
|
||||||
ptr.pointer = tok.pos
|
ptr.pointer = tok.pos
|
||||||
ptr.elem = elem
|
ptr.elem = elem
|
||||||
return ptr
|
return ptr
|
||||||
@@ -2470,7 +2474,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
tok := expect_token(p, .Pointer)
|
tok := expect_token(p, .Pointer)
|
||||||
close := expect_token(p, .Close_Bracket)
|
close := expect_token(p, .Close_Bracket)
|
||||||
elem := parse_type(p)
|
elem := parse_type(p)
|
||||||
t := ast.new(ast.Multi_Pointer_Type, open.pos, elem.end)
|
t := ast.new(ast.Multi_Pointer_Type, open.pos, elem)
|
||||||
t.open = open.pos
|
t.open = open.pos
|
||||||
t.pointer = tok.pos
|
t.pointer = tok.pos
|
||||||
t.close = close.pos
|
t.close = close.pos
|
||||||
@@ -2480,7 +2484,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
tok := expect_token(p, .Dynamic)
|
tok := expect_token(p, .Dynamic)
|
||||||
close := expect_token(p, .Close_Bracket)
|
close := expect_token(p, .Close_Bracket)
|
||||||
elem := parse_type(p)
|
elem := parse_type(p)
|
||||||
da := ast.new(ast.Dynamic_Array_Type, open.pos, elem.end)
|
da := ast.new(ast.Dynamic_Array_Type, open.pos, elem)
|
||||||
da.open = open.pos
|
da.open = open.pos
|
||||||
da.dynamic_pos = tok.pos
|
da.dynamic_pos = tok.pos
|
||||||
da.close = close.pos
|
da.close = close.pos
|
||||||
@@ -2500,7 +2504,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
}
|
}
|
||||||
close := expect_token(p, .Close_Bracket)
|
close := expect_token(p, .Close_Bracket)
|
||||||
elem := parse_type(p)
|
elem := parse_type(p)
|
||||||
at := ast.new(ast.Array_Type, open.pos, elem.end)
|
at := ast.new(ast.Array_Type, open.pos, elem)
|
||||||
at.open = open.pos
|
at.open = open.pos
|
||||||
at.len = count
|
at.len = count
|
||||||
at.close = close.pos
|
at.close = close.pos
|
||||||
@@ -2514,7 +2518,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
expect_token(p, .Close_Bracket)
|
expect_token(p, .Close_Bracket)
|
||||||
value := parse_type(p)
|
value := parse_type(p)
|
||||||
|
|
||||||
mt := ast.new(ast.Map_Type, tok.pos, value.end)
|
mt := ast.new(ast.Map_Type, tok.pos, value)
|
||||||
mt.tok_pos = tok.pos
|
mt.tok_pos = tok.pos
|
||||||
mt.key = key
|
mt.key = key
|
||||||
mt.value = value
|
mt.value = value
|
||||||
@@ -2755,7 +2759,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
expect_token(p, .Close_Bracket)
|
expect_token(p, .Close_Bracket)
|
||||||
elem := parse_type(p)
|
elem := parse_type(p)
|
||||||
|
|
||||||
mt := ast.new(ast.Matrix_Type, tok.pos, elem.end)
|
mt := ast.new(ast.Matrix_Type, tok.pos, elem)
|
||||||
mt.tok_pos = tok.pos
|
mt.tok_pos = tok.pos
|
||||||
mt.row_count = row_count
|
mt.row_count = row_count
|
||||||
mt.column_count = column_count
|
mt.column_count = column_count
|
||||||
@@ -2893,7 +2897,7 @@ parse_elem_list :: proc(p: ^Parser) -> []^ast.Expr {
|
|||||||
eq := expect_token(p, .Eq)
|
eq := expect_token(p, .Eq)
|
||||||
value := parse_value(p)
|
value := parse_value(p)
|
||||||
|
|
||||||
fv := ast.new(ast.Field_Value, elem.pos, value.end)
|
fv := ast.new(ast.Field_Value, elem.pos, value)
|
||||||
fv.field = elem
|
fv.field = elem
|
||||||
fv.sep = eq.pos
|
fv.sep = eq.pos
|
||||||
fv.value = value
|
fv.value = value
|
||||||
@@ -2962,7 +2966,7 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
value := parse_value(p)
|
value := parse_value(p)
|
||||||
fv := ast.new(ast.Field_Value, arg.pos, value.end)
|
fv := ast.new(ast.Field_Value, arg.pos, value)
|
||||||
fv.field = arg
|
fv.field = arg
|
||||||
fv.sep = eq.pos
|
fv.sep = eq.pos
|
||||||
fv.value = value
|
fv.value = value
|
||||||
@@ -2993,7 +2997,7 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
|
|||||||
|
|
||||||
o := ast.unparen_expr(operand)
|
o := ast.unparen_expr(operand)
|
||||||
if se, ok := o.derived.(^ast.Selector_Expr); ok && se.op.kind == .Arrow_Right {
|
if se, ok := o.derived.(^ast.Selector_Expr); ok && se.op.kind == .Arrow_Right {
|
||||||
sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce.end)
|
sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce)
|
||||||
sce.expr = o
|
sce.expr = o
|
||||||
sce.call = ce
|
sce.call = ce
|
||||||
return sce
|
return sce
|
||||||
@@ -3101,7 +3105,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
|
|||||||
case .Ident:
|
case .Ident:
|
||||||
field := parse_ident(p)
|
field := parse_ident(p)
|
||||||
|
|
||||||
sel := ast.new(ast.Selector_Expr, operand.pos, field.end)
|
sel := ast.new(ast.Selector_Expr, operand.pos, field)
|
||||||
sel.expr = operand
|
sel.expr = operand
|
||||||
sel.op = tok
|
sel.op = tok
|
||||||
sel.field = field
|
sel.field = field
|
||||||
@@ -3127,7 +3131,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
|
|||||||
type.op = question
|
type.op = question
|
||||||
type.expr = nil
|
type.expr = nil
|
||||||
|
|
||||||
ta := ast.new(ast.Type_Assertion, operand.pos, type.end)
|
ta := ast.new(ast.Type_Assertion, operand.pos, type)
|
||||||
ta.expr = operand
|
ta.expr = operand
|
||||||
ta.type = type
|
ta.type = type
|
||||||
|
|
||||||
@@ -3145,7 +3149,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
|
|||||||
case .Ident:
|
case .Ident:
|
||||||
field := parse_ident(p)
|
field := parse_ident(p)
|
||||||
|
|
||||||
sel := ast.new(ast.Selector_Expr, operand.pos, field.end)
|
sel := ast.new(ast.Selector_Expr, operand.pos, field)
|
||||||
sel.expr = operand
|
sel.expr = operand
|
||||||
sel.op = tok
|
sel.op = tok
|
||||||
sel.field = field
|
sel.field = field
|
||||||
@@ -3225,7 +3229,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
close := expect_token(p, .Close_Paren)
|
close := expect_token(p, .Close_Paren)
|
||||||
expr := parse_unary_expr(p, lhs)
|
expr := parse_unary_expr(p, lhs)
|
||||||
|
|
||||||
tc := ast.new(ast.Type_Cast, tok.pos, expr.end)
|
tc := ast.new(ast.Type_Cast, tok.pos, expr)
|
||||||
tc.tok = tok
|
tc.tok = tok
|
||||||
tc.open = open.pos
|
tc.open = open.pos
|
||||||
tc.type = type
|
tc.type = type
|
||||||
@@ -3237,7 +3241,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
op := advance_token(p)
|
op := advance_token(p)
|
||||||
expr := parse_unary_expr(p, lhs)
|
expr := parse_unary_expr(p, lhs)
|
||||||
|
|
||||||
ac := ast.new(ast.Auto_Cast, op.pos, expr.end)
|
ac := ast.new(ast.Auto_Cast, op.pos, expr)
|
||||||
ac.op = op
|
ac.op = op
|
||||||
ac.expr = expr
|
ac.expr = expr
|
||||||
return ac
|
return ac
|
||||||
@@ -3248,7 +3252,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
op := advance_token(p)
|
op := advance_token(p)
|
||||||
expr := parse_unary_expr(p, lhs)
|
expr := parse_unary_expr(p, lhs)
|
||||||
|
|
||||||
ue := ast.new(ast.Unary_Expr, op.pos, expr.end)
|
ue := ast.new(ast.Unary_Expr, op.pos, expr)
|
||||||
ue.op = op
|
ue.op = op
|
||||||
ue.expr = expr
|
ue.expr = expr
|
||||||
return ue
|
return ue
|
||||||
@@ -3258,7 +3262,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
error(p, op.pos, "unary '%s' operator is not supported", op.text)
|
error(p, op.pos, "unary '%s' operator is not supported", op.text)
|
||||||
expr := parse_unary_expr(p, lhs)
|
expr := parse_unary_expr(p, lhs)
|
||||||
|
|
||||||
ue := ast.new(ast.Unary_Expr, op.pos, expr.end)
|
ue := ast.new(ast.Unary_Expr, op.pos, expr)
|
||||||
ue.op = op
|
ue.op = op
|
||||||
ue.expr = expr
|
ue.expr = expr
|
||||||
return ue
|
return ue
|
||||||
@@ -3266,7 +3270,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
case .Period:
|
case .Period:
|
||||||
op := advance_token(p)
|
op := advance_token(p)
|
||||||
field := parse_ident(p)
|
field := parse_ident(p)
|
||||||
ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field.end)
|
ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field)
|
||||||
ise.field = field
|
ise.field = field
|
||||||
return ise
|
return ise
|
||||||
|
|
||||||
@@ -3407,7 +3411,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
|
|||||||
error(p, p.curr_tok.pos, "no right-hand side in assignment statement")
|
error(p, p.curr_tok.pos, "no right-hand side in assignment statement")
|
||||||
return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok))
|
return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok))
|
||||||
}
|
}
|
||||||
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end)
|
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1])
|
||||||
stmt.lhs = lhs
|
stmt.lhs = lhs
|
||||||
stmt.op = op
|
stmt.op = op
|
||||||
stmt.rhs = rhs
|
stmt.rhs = rhs
|
||||||
@@ -3424,7 +3428,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
|
|||||||
rhs := make([]^ast.Expr, 1)
|
rhs := make([]^ast.Expr, 1)
|
||||||
rhs[0] = expr
|
rhs[0] = expr
|
||||||
|
|
||||||
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end)
|
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1])
|
||||||
stmt.lhs = lhs
|
stmt.lhs = lhs
|
||||||
stmt.op = op
|
stmt.op = op
|
||||||
stmt.rhs = rhs
|
stmt.rhs = rhs
|
||||||
@@ -3466,7 +3470,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
|
|||||||
error(p, op.pos, "postfix '%s' statement is not supported", op.text)
|
error(p, op.pos, "postfix '%s' statement is not supported", op.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0].end)
|
es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0])
|
||||||
es.expr = lhs[0]
|
es.expr = lhs[0]
|
||||||
return es
|
return es
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user