go: lex.sx — decimal float + imaginary literals + 22 tests [consumes-lex]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
Adds Go float and imaginary literal forms per Go spec § Floating-point literals and § Imaginary literals: 3.14 .5 1. 1e10 1.5e-3 2.0e+2 1E5 (floats) 2i 3.14i 1e2i (imag) gl-read-number! returns one of "int" / "float" / "imag"; gl-finish-number! factors out the post-mantissa exponent + 'i' suffix logic so the int / float / leading-dot-float paths all share it. scan! adds a .<digit> branch ahead of the operator matcher so '.5' tokenises as float. ASI trigger list extended to include float + imag (Go spec § Semicolons: all literal types trigger). Greedy-grammar pin (a single test '1.method' lexes as float ident), since the Go spec says the '.' after a digit always belongs to the number, never to a following identifier. Hex floats (0x1.fp0) deferred — not commonly used. lex 114/114. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
;; "keyword" — one of the 25 Go keywords
|
||||
;; "int" — integer literals (decimal, 0x.. hex, 0b.. binary, 0o.. octal,
|
||||
;; legacy 0123 octal; underscores between digits allowed)
|
||||
;; "float" — decimal float literals (3.14, .5, 1., 1e10, 1.5e-3, 1E5)
|
||||
;; "imag" — imaginary literals (2i, 3.14i, 1e2i)
|
||||
;; "string" — interpreted string literals "..."
|
||||
;; "rune" — rune literals 'x' (single char + simple escapes)
|
||||
;; "op" — operators & punctuation; :value is the literal text
|
||||
@@ -16,7 +18,7 @@
|
||||
;;
|
||||
;; ASI (Go spec § Semicolons): a newline (or EOF, or a block comment
|
||||
;; containing a newline) emits a ";semi" if the previous emitted token's
|
||||
;; type is ident/int/string/rune, or its value is one of
|
||||
;; type is ident/int/float/imag/string/rune, or its value is one of
|
||||
;; {break, continue, fallthrough, return, ++, --, ), ], }}.
|
||||
;;
|
||||
;; All scanner locals are gl- prefixed: SX host primitives (peek/emit/etc.)
|
||||
@@ -57,6 +59,8 @@
|
||||
|
||||
(define go-asi-ops (list "++" "--" ")" "]" "}"))
|
||||
|
||||
(define go-asi-lit-types (list "ident" "int" "float" "imag" "string" "rune"))
|
||||
|
||||
(define
|
||||
go-asi-trigger?
|
||||
(fn
|
||||
@@ -67,10 +71,7 @@
|
||||
(let
|
||||
((ty (get tok :type)) (v (get tok :value)))
|
||||
(or
|
||||
(= ty "ident")
|
||||
(= ty "int")
|
||||
(= ty "string")
|
||||
(= ty "rune")
|
||||
(some (fn (lt) (= lt ty)) go-asi-lit-types)
|
||||
(and (= ty "keyword") (some (fn (k) (= k v)) go-asi-keywords))
|
||||
(and (= ty "op") (some (fn (o) (= o v)) go-asi-ops)))))))
|
||||
|
||||
@@ -143,30 +144,70 @@
|
||||
(and (< pos src-len) (or (digit? (gl-cur)) (= (gl-cur) "_")))
|
||||
(gl-advance! 1)
|
||||
(gl-read-digit-run! digit?))))
|
||||
(define
|
||||
gl-finish-number!
|
||||
(fn
|
||||
(has-fraction?)
|
||||
(let
|
||||
((typ (if has-fraction? "float" "int")))
|
||||
(when
|
||||
(or (= (gl-cur) "e") (= (gl-cur) "E"))
|
||||
(gl-advance! 1)
|
||||
(when
|
||||
(or (= (gl-cur) "+") (= (gl-cur) "-"))
|
||||
(gl-advance! 1))
|
||||
(gl-read-digit-run! lex-digit?)
|
||||
(set! typ "float"))
|
||||
(cond
|
||||
(= (gl-cur) "i")
|
||||
(do (gl-advance! 1) "imag")
|
||||
:else typ))))
|
||||
(define
|
||||
gl-read-number!
|
||||
(fn
|
||||
()
|
||||
(cond
|
||||
(and (= (gl-cur) ".") (lex-digit? (gl-peek 1)))
|
||||
(do
|
||||
(gl-advance! 1)
|
||||
(gl-read-digit-run! lex-digit?)
|
||||
(gl-finish-number! true))
|
||||
(and
|
||||
(= (gl-cur) "0")
|
||||
(or
|
||||
(= (gl-peek 1) "x")
|
||||
(= (gl-peek 1) "X")))
|
||||
(do (gl-advance! 2) (gl-read-digit-run! lex-hex-digit?))
|
||||
(do
|
||||
(gl-advance! 2)
|
||||
(gl-read-digit-run! lex-hex-digit?)
|
||||
"int")
|
||||
(and
|
||||
(= (gl-cur) "0")
|
||||
(or
|
||||
(= (gl-peek 1) "b")
|
||||
(= (gl-peek 1) "B")))
|
||||
(do (gl-advance! 2) (gl-read-digit-run! gl-bin-digit?))
|
||||
(do
|
||||
(gl-advance! 2)
|
||||
(gl-read-digit-run! gl-bin-digit?)
|
||||
"int")
|
||||
(and
|
||||
(= (gl-cur) "0")
|
||||
(or
|
||||
(= (gl-peek 1) "o")
|
||||
(= (gl-peek 1) "O")))
|
||||
(do (gl-advance! 2) (gl-read-digit-run! gl-oct-digit?))
|
||||
:else (gl-read-digit-run! lex-digit?))))
|
||||
(do
|
||||
(gl-advance! 2)
|
||||
(gl-read-digit-run! gl-oct-digit?)
|
||||
"int")
|
||||
:else (do
|
||||
(gl-read-digit-run! lex-digit?)
|
||||
(cond
|
||||
(and (= (gl-cur) ".") (not (= (gl-peek 1) ".")))
|
||||
(do
|
||||
(gl-advance! 1)
|
||||
(gl-read-digit-run! lex-digit?)
|
||||
(gl-finish-number! true))
|
||||
:else (gl-finish-number! false))))))
|
||||
(define
|
||||
gl-read-string!
|
||||
(fn
|
||||
@@ -371,9 +412,14 @@
|
||||
(lex-digit? (gl-cur))
|
||||
(do
|
||||
(let
|
||||
((start pos))
|
||||
(gl-read-number!)
|
||||
(gl-emit! "int" (slice src start pos) start))
|
||||
((start pos) (typ (gl-read-number!)))
|
||||
(gl-emit! typ (slice src start pos) start))
|
||||
(gl-scan!))
|
||||
(and (= (gl-cur) ".") (lex-digit? (gl-peek 1)))
|
||||
(do
|
||||
(let
|
||||
((start pos) (typ (gl-read-number!)))
|
||||
(gl-emit! typ (slice src start pos) start))
|
||||
(gl-scan!))
|
||||
(= (gl-cur) "\"")
|
||||
(let
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"language": "go",
|
||||
"total_pass": 92,
|
||||
"total": 92,
|
||||
"total_pass": 114,
|
||||
"total": 114,
|
||||
"suites": [
|
||||
{"name":"lex","pass":92,"total":92,"status":"ok"},
|
||||
{"name":"lex","pass":114,"total":114,"status":"ok"},
|
||||
{"name":"parse","pass":0,"total":0,"status":"pending"},
|
||||
{"name":"types","pass":0,"total":0,"status":"pending"},
|
||||
{"name":"eval","pass":0,"total":0,"status":"pending"},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Go-on-SX Scoreboard
|
||||
|
||||
**Total: 92 / 92 tests passing**
|
||||
**Total: 114 / 114 tests passing**
|
||||
|
||||
| | Suite | Pass | Total |
|
||||
|---|---|---|---|
|
||||
| ✅ | lex | 92 | 92 |
|
||||
| ✅ | lex | 114 | 114 |
|
||||
| ⬜ | parse | 0 | 0 |
|
||||
| ⬜ | types | 0 | 0 |
|
||||
| ⬜ | eval | 0 | 0 |
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
(go-test "int: bigger" (tok-values "123456") (list "123456" "\n" nil))
|
||||
(go-test "int: type" (tok-types "42") (list "int" "semi" "eof"))
|
||||
|
||||
;; ── integer literals — prefixed + underscores (Go spec § Integer literals)
|
||||
;; ── integer literals — prefixed + underscores ─────────────────────
|
||||
(go-test "int: hex lower" (tok-values "0x1f") (list "0x1f" "\n" nil))
|
||||
(go-test "int: hex upper-x" (tok-values "0X1F") (list "0X1F" "\n" nil))
|
||||
(go-test
|
||||
@@ -105,6 +105,43 @@
|
||||
(tok-types "0xFF + 1")
|
||||
(list "int" "op" "int" "semi" "eof"))
|
||||
|
||||
;; ── float literals (Go spec § Floating-point literals) ────────────
|
||||
(go-test "float: simple" (tok-values "3.14") (list "3.14" "\n" nil))
|
||||
(go-test "float: trailing dot" (tok-values "1.") (list "1." "\n" nil))
|
||||
(go-test "float: leading dot" (tok-values ".5") (list ".5" "\n" nil))
|
||||
(go-test "float: exp lower" (tok-values "1e10") (list "1e10" "\n" nil))
|
||||
(go-test "float: exp upper" (tok-values "1E5") (list "1E5" "\n" nil))
|
||||
(go-test "float: exp negative" (tok-values "1.5e-3") (list "1.5e-3" "\n" nil))
|
||||
(go-test "float: exp positive" (tok-values "2.0e+2") (list "2.0e+2" "\n" nil))
|
||||
(go-test "float: zero" (tok-values "0.0") (list "0.0" "\n" nil))
|
||||
(go-test "float: dot-only-exp" (tok-values ".5e2") (list ".5e2" "\n" nil))
|
||||
(go-test "float: underscore" (tok-values "1_000.5") (list "1_000.5" "\n" nil))
|
||||
(go-test "float: type" (tok-types "3.14") (list "float" "semi" "eof"))
|
||||
(go-test
|
||||
"float: trailing dot type"
|
||||
(tok-types "1.")
|
||||
(list "float" "semi" "eof"))
|
||||
(go-test
|
||||
"float: exp-only type"
|
||||
(tok-types "1e10")
|
||||
(list "float" "semi" "eof"))
|
||||
(go-test
|
||||
"float: then +"
|
||||
(tok-types "3.14 + 0.1")
|
||||
(list "float" "op" "float" "semi" "eof"))
|
||||
(go-test
|
||||
"float: greedy 1.method"
|
||||
(tok-types "1.method")
|
||||
(list "float" "ident" "semi" "eof"))
|
||||
|
||||
;; ── imaginary literals (Go spec § Imaginary literals) ─────────────
|
||||
(go-test "imag: int i" (tok-values "2i") (list "2i" "\n" nil))
|
||||
(go-test "imag: float i" (tok-values "3.14i") (list "3.14i" "\n" nil))
|
||||
(go-test "imag: exp i" (tok-values "1e2i") (list "1e2i" "\n" nil))
|
||||
(go-test "imag: int-i type" (tok-types "2i") (list "imag" "semi" "eof"))
|
||||
(go-test "imag: float-i type" (tok-types "3.14i") (list "imag" "semi" "eof"))
|
||||
(go-test "imag: ASI at newline" (tok-types "1i\n") (list "imag" "semi" "eof"))
|
||||
|
||||
;; ── string literals ───────────────────────────────────────────────
|
||||
(go-test "string: empty" (tok-values "\"\"") (list "" "\n" nil))
|
||||
(go-test "string: hello" (tok-values "\"hello\"") (list "hello" "\n" nil))
|
||||
@@ -170,6 +207,7 @@
|
||||
(tok-types "x\ny")
|
||||
(list "ident" "semi" "ident" "semi" "eof"))
|
||||
(go-test "ASI: after int" (tok-types "42\n") (list "int" "semi" "eof"))
|
||||
(go-test "ASI: after float" (tok-types "3.14\n") (list "float" "semi" "eof"))
|
||||
(go-test
|
||||
"ASI: after string"
|
||||
(tok-types "\"hi\"\n")
|
||||
|
||||
Reference in New Issue
Block a user