diff --git a/compiler/lexer/lexer.go b/compiler/lexer/lexer.go index b795b84..7bbceb4 100644 --- a/compiler/lexer/lexer.go +++ b/compiler/lexer/lexer.go @@ -11,6 +11,7 @@ const ( IDENTIFIER lexType = iota KEYWORD NUMBER + HEX STRING BYTE OPERATOR @@ -238,9 +239,30 @@ func Lex(inputFullSource string) []Item { // NUMBER // 0-9 lexNumber := func() bool { + isHex := false + if i + 1 < len(input) { + if input[i] == '0' && input[i+1] == 'x' { + isHex = true + i += 2 + } + } if i >= len(input) { return false } + if isHex { + if (input[i] >= '0' && input[i] <= '9') || (input[i] >= 'a' && input[i] <= 'f') || (input[i] >= 'A' && input[i] <= 'F') { + val := "" + for (input[i] >= '0' && input[i] <= '9') || (input[i] >= 'a' && input[i] <= 'f') || (input[i] >= 'A' && input[i] <= 'F') { + val += string(input[i]) + i++ + if i >= len(input) { + break + } + } + res = append(res, Item{Type: HEX, Val: val, Line: line}) + return true + } + } if input[i] >= '0' && input[i] <= '9' { val := "" for i < len(input) && input[i] >= '0' && input[i] <= '9' { diff --git a/compiler/parser/parser.go b/compiler/parser/parser.go index ae37d15..cfaf010 100644 --- a/compiler/parser/parser.go +++ b/compiler/parser/parser.go @@ -63,6 +63,33 @@ func (p *parser) parseOne(withAheadParse bool) (res Node) { return p.parseOneWithOptions(withAheadParse, withAheadParse, withAheadParse) } +func (p *parser) parseNumberSuffix() (ty TypeNode) { + next := p.lookAhead(1) + if next.Type == lexer.IDENTIFIER { + switch next.Val { + case "u8": + ty = &SingleTypeNode{SourceName: "uint8", TypeName: "uint8"} + p.i++ + case "u16": + ty = &SingleTypeNode{SourceName: "uint16", TypeName: "uint16"} + p.i++ + case "u32": + ty = &SingleTypeNode{SourceName: "uint32", TypeName: "uint32"} + p.i++ + case "u64": + ty = &SingleTypeNode{SourceName: "uint64", TypeName: "uint64"} + p.i++ + case "u128": + ty = &SingleTypeNode{SourceName: "uint128", TypeName: "uint128"} + p.i++ + case "u256": + ty = &SingleTypeNode{SourceName: "uint256", TypeName: "uint256"} + p.i++ + } + } + return +} + func (p *parser) parseOneWithOptions(withAheadParse, withArithAhead, withIdentifierAhead bool) (res Node) { current := p.input[p.i] @@ -91,6 +118,24 @@ func (p *parser) parseOneWithOptions(withAheadParse, withArithAhead, withIdentif } return + + // HEX always returns a ConstantNode + // Convert string hex representation to int64 + case lexer.HEX: + val, err := strconv.ParseInt(current.Val, 16, 64) + if err != nil { + panic(err) + } + res = &ConstantNode{ + Type: NUMBER, + TargetType: p.parseNumberSuffix(), + Value: val, + } + if withAheadParse { + res = p.aheadParse(res) + } + return + // NUMBER always returns a ConstantNode // Convert string representation to int64 case lexer.NUMBER: @@ -98,34 +143,10 @@ func (p *parser) parseOneWithOptions(withAheadParse, withArithAhead, withIdentif if err != nil { panic(err) } - next := p.lookAhead(1) - var ty TypeNode - if next.Type == lexer.IDENTIFIER { - switch next.Val { - case "u8": - ty = &SingleTypeNode{SourceName: "uint8", TypeName: "uint8"} - p.i++ - case "u16": - ty = &SingleTypeNode{SourceName: "uint16", TypeName: "uint16"} - p.i++ - case "u32": - ty = &SingleTypeNode{SourceName: "uint32", TypeName: "uint32"} - p.i++ - case "u64": - ty = &SingleTypeNode{SourceName: "uint64", TypeName: "uint64"} - p.i++ - case "u128": - ty = &SingleTypeNode{SourceName: "uint128", TypeName: "uint128"} - p.i++ - case "u256": - ty = &SingleTypeNode{SourceName: "uint256", TypeName: "uint256"} - p.i++ - } - } res = &ConstantNode{ Type: NUMBER, - TargetType: ty, + TargetType: p.parseNumberSuffix(), Value: val, } if withAheadParse { diff --git a/tests/examples/number-literal.cell b/tests/examples/number-literal.cell index 4e87c89..934a0ea 100644 --- a/tests/examples/number-literal.cell +++ b/tests/examples/number-literal.cell @@ -27,5 +27,10 @@ func main() { if f != uint256(600) { return 6 } + + aa := 0xffffu32 + if aa != uint32(65535) { + return 11 + } return 0 } \ No newline at end of file