Browse Source

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.
Laytan Laats 1 year ago
parent
commit
bd19081543
2 changed files with 61 additions and 48 deletions
  1. 10 1
      core/odin/ast/clone.odin
  2. 51 47
      core/odin/parser/parser.odin

+ 10 - 1
core/odin/ast/clone.odin

@@ -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,

+ 51 - 47
core/odin/parser/parser.odin

@@ -786,8 +786,11 @@ parse_if_stmt :: proc(p: ^Parser) -> ^ast.If_Stmt {
 			else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok))
 			else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok))
 		}
 		}
 	}
 	}
-
-	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, end)
+		s := ast.new(ast.Branch_Stmt, tok.pos, label)
 		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
@@ -3247,8 +3251,8 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
 	     .And:
 	     .And:
 		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
 }
 }