unary minus
This commit is contained in:
@@ -4,8 +4,8 @@ import "../ast"
|
||||
import "../source"
|
||||
import "../symbol"
|
||||
import "../token"
|
||||
import "base:intrinsics"
|
||||
import "core:fmt"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
|
||||
Parser :: struct {
|
||||
@@ -168,14 +168,32 @@ parse_call :: proc(parser: ^Parser, qualifier: symbol.Id, first, name: token.Tok
|
||||
})
|
||||
}
|
||||
|
||||
parse_integer_magnitude :: proc(text: string) -> (u64, bool) {
|
||||
value: u64
|
||||
for byte in transmute([]byte)text {
|
||||
if byte < '0' || byte > '9' {
|
||||
return 0, false
|
||||
}
|
||||
next, overflow := intrinsics.overflow_mul(value, u64(10))
|
||||
if overflow {
|
||||
return 0, false
|
||||
}
|
||||
value, overflow = intrinsics.overflow_add(next, u64(byte-'0'))
|
||||
if overflow {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
return value, len(text) > 0
|
||||
}
|
||||
|
||||
parse_primary :: proc(parser: ^Parser, nesting: int) -> ast.Expr_Id {
|
||||
tok := current(parser)
|
||||
#partial switch tok.kind {
|
||||
case .Integer:
|
||||
advance(parser)
|
||||
value, ok := strconv.parse_i64(token_text(parser, tok))
|
||||
value, ok := parse_integer_magnitude(token_text(parser, tok))
|
||||
if !ok {
|
||||
return invalid_expr(parser, tok.span, "integer literal does not fit in i64")
|
||||
return invalid_expr(parser, tok.span, "integer literal magnitude does not fit in u64")
|
||||
}
|
||||
return add_expr(parser, ast.Expr{
|
||||
kind=.Integer,
|
||||
@@ -250,6 +268,14 @@ infix_binding_power :: proc(kind: token.Kind) -> (left, right: int, ok: bool) {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
prefix_binding_power :: proc(kind: token.Kind) -> (right: int, ok: bool) {
|
||||
#partial switch kind {
|
||||
case .Minus:
|
||||
return 20, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
parse_expression_bp :: proc(parser: ^Parser, minimum_binding_power, nesting: int) -> ast.Expr_Id {
|
||||
if nesting > MAX_EXPRESSION_NESTING {
|
||||
tok := current(parser)
|
||||
@@ -258,7 +284,24 @@ parse_expression_bp :: proc(parser: ^Parser, minimum_binding_power, nesting: int
|
||||
}
|
||||
return invalid_expr(parser, tok.span, "expression nesting exceeds 256 levels")
|
||||
}
|
||||
left := parse_primary(parser, nesting)
|
||||
left := ast.INVALID_EXPR
|
||||
if right_power, ok := prefix_binding_power(current(parser).kind); ok {
|
||||
operator := advance(parser)
|
||||
if parser.delimiter_depth > 0 {
|
||||
skip_newlines(parser)
|
||||
}
|
||||
operand := parse_expression_bp(parser, right_power, nesting+1)
|
||||
operand_expr := parser.module.exprs[operand]
|
||||
left = add_expr(parser, ast.Expr{
|
||||
kind=.Negate,
|
||||
span=span_from(operator.span, operand_expr.span),
|
||||
left=operand,
|
||||
right=ast.INVALID_EXPR,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
left = parse_primary(parser, nesting)
|
||||
}
|
||||
if parser.delimiter_depth > 0 {
|
||||
skip_newlines(parser)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user