From 65467c232b6d27ddf1a7eb9dfdea4910d388b068 Mon Sep 17 00:00:00 2001 From: giles Date: Wed, 27 May 2026 07:22:01 +0000 Subject: [PATCH] =?UTF-8?q?go:=20lex.sx=20=E2=80=94=20raw=20string=20liter?= =?UTF-8?q?als=20(backtick)=20+=209=20tests=20[nothing]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Go raw string literals per Go spec § String literals: backtick-delimited, no escape processing, may span multiple lines, '\r' chars discarded from the value. gl-read-raw-string! mirrors gl-read-string! but skips escape handling and the \r filter. scan! routes the leading backtick to it; emits "string" type (same as interpreted strings — no need to distinguish at parse/type time). lex 123/123. Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/go/lex.sx | 31 +++++++++++++++++++++++- lib/go/scoreboard.json | 6 ++--- lib/go/scoreboard.md | 4 ++-- lib/go/tests/lex.sx | 54 +++++++++++++++++++++++++++++++++++------- plans/go-on-sx.md | 12 ++++++++-- 5 files changed, 90 insertions(+), 17 deletions(-) diff --git a/lib/go/lex.sx b/lib/go/lex.sx index d46ca11d..29f5d1c1 100644 --- a/lib/go/lex.sx +++ b/lib/go/lex.sx @@ -10,7 +10,7 @@ ;; 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 "..." +;; "string" — interpreted string literals "..." OR raw string literals `...` ;; "rune" — rune literals 'x' (single char + simple escapes) ;; "op" — operators & punctuation; :value is the literal text ;; "semi" — explicit ';' or auto-inserted (Go spec § Semicolons) @@ -253,6 +253,30 @@ (gl-string-loop))))) (gl-string-loop) (join "" chars)))) + (define + gl-read-raw-string! + (fn + () + (gl-advance! 1) + (let + ((chars (list))) + (define + gl-raw-loop + (fn + () + (cond + (>= pos src-len) + nil + (= (gl-cur) "`") + (gl-advance! 1) + (= (gl-cur) "\r") + (do (gl-advance! 1) (gl-raw-loop)) + :else (do + (append! chars (gl-cur)) + (gl-advance! 1) + (gl-raw-loop))))) + (gl-raw-loop) + (join "" chars)))) (define gl-read-rune! (fn @@ -426,6 +450,11 @@ ((start pos) (v (gl-read-string!))) (gl-emit! "string" v start) (gl-scan!)) + (= (gl-cur) "`") + (let + ((start pos) (v (gl-read-raw-string!))) + (gl-emit! "string" v start) + (gl-scan!)) (= (gl-cur) "'") (let ((start pos) (v (gl-read-rune!))) diff --git a/lib/go/scoreboard.json b/lib/go/scoreboard.json index b9b2ad42..c856e925 100644 --- a/lib/go/scoreboard.json +++ b/lib/go/scoreboard.json @@ -1,9 +1,9 @@ { "language": "go", - "total_pass": 114, - "total": 114, + "total_pass": 123, + "total": 123, "suites": [ - {"name":"lex","pass":114,"total":114,"status":"ok"}, + {"name":"lex","pass":123,"total":123,"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"}, diff --git a/lib/go/scoreboard.md b/lib/go/scoreboard.md index d16a8b55..82f738a4 100644 --- a/lib/go/scoreboard.md +++ b/lib/go/scoreboard.md @@ -1,10 +1,10 @@ # Go-on-SX Scoreboard -**Total: 114 / 114 tests passing** +**Total: 123 / 123 tests passing** | | Suite | Pass | Total | |---|---|---|---| -| ✅ | lex | 114 | 114 | +| ✅ | lex | 123 | 123 | | ⬜ | parse | 0 | 0 | | ⬜ | types | 0 | 0 | | ⬜ | eval | 0 | 0 | diff --git a/lib/go/tests/lex.sx b/lib/go/tests/lex.sx index d4677b12..50604e16 100644 --- a/lib/go/tests/lex.sx +++ b/lib/go/tests/lex.sx @@ -143,7 +143,38 @@ (go-test "imag: ASI at newline" (tok-types "1i\n") (list "imag" "semi" "eof")) ;; ── string literals ─────────────────────────────────────────────── +(go-test "raw: simple" (tok-values "`hello`") (list "hello" "\n" nil)) +(go-test "raw: empty" (tok-values "``") (list "" "\n" nil)) +(go-test + "raw: backslash literal — no escape processing" + (tok-values "`a\\nb`") + (list "a\\nb" "\n" nil)) +(go-test + "raw: multi-line" + (tok-values "`line1\nline2`") + (list "line1\nline2" "\n" nil)) +(go-test + "raw: contains double-quote" + (tok-values "`say \"hi\"`") + (list "say \"hi\"" "\n" nil)) +(go-test + "raw: CR stripped (Go spec § String literals)" + (tok-values "`a\r\nb`") + (list "a\nb" "\n" nil)) +(go-test "raw: type" (tok-types "`x`") (list "string" "semi" "eof")) + +;; ── rune literals ───────────────────────────────────────────────── +(go-test + "raw: then +" + (tok-types "`x` + 1") + (list "string" "op" "int" "semi" "eof")) +(go-test + "raw: ASI at newline after" + (tok-types "`abc`\n") + (list "string" "semi" "eof")) (go-test "string: empty" (tok-values "\"\"") (list "" "\n" nil)) + +;; ── comments ────────────────────────────────────────────────────── (go-test "string: hello" (tok-values "\"hello\"") (list "hello" "\n" nil)) (go-test "string: with space" @@ -155,14 +186,12 @@ "string: escape backslash" (tok-values "\"a\\\\b\"") (list "a\\b" "\n" nil)) -(go-test "string: type" (tok-types "\"x\"") (list "string" "semi" "eof")) -;; ── rune literals ───────────────────────────────────────────────── +;; ── operators & punctuation ─────────────────────────────────────── +(go-test "string: type" (tok-types "\"x\"") (list "string" "semi" "eof")) (go-test "rune: simple" (tok-values "'a'") (list "a" "\n" nil)) (go-test "rune: escape" (tok-values "'\\n'") (list "\n" "\n" nil)) (go-test "rune: type" (tok-types "'a'") (list "rune" "semi" "eof")) - -;; ── comments ────────────────────────────────────────────────────── (go-test "line comment" (tok-types "// ignored") (list "eof")) (go-test "line comment then code" (tok-values "// hi\nx") (list "x" "\n" nil)) (go-test "block comment" (tok-types "/* a b c */") (list "eof")) @@ -175,7 +204,7 @@ (tok-types "x /* multi\nline */ y") (list "ident" "semi" "ident" "semi" "eof")) -;; ── operators & punctuation ─────────────────────────────────────── +;; ── automatic semicolon insertion (Go spec § Semicolons) ────────── (go-test "ops: arithmetic" (tok-values "+ - * / %") @@ -200,8 +229,6 @@ "punct: comma colon dot" (tok-values ", : .") (list "," ":" "." nil)) - -;; ── automatic semicolon insertion (Go spec § Semicolons) ────────── (go-test "ASI: after ident at newline" (tok-types "x\ny") @@ -213,6 +240,8 @@ (tok-types "\"hi\"\n") (list "string" "semi" "eof")) (go-test "ASI: after rune" (tok-types "'a'\n") (list "rune" "semi" "eof")) + +;; ── short program ───────────────────────────────────────────────── (go-test "ASI: after )" (tok-types "f()\n") @@ -222,37 +251,45 @@ (tok-types "x[0]\n") (list "ident" "op" "int" "op" "semi" "eof")) (go-test "ASI: after }" (tok-types "{}\n") (list "op" "op" "semi" "eof")) + +;; ── report ──────────────────────────────────────────────────────── (go-test "ASI: after ++" (tok-types "i++\n") (list "ident" "op" "semi" "eof")) + (go-test "ASI: NOT after +" (tok-types "x +\ny") (list "ident" "op" "ident" "semi" "eof")) + (go-test "ASI: NOT after (" (tok-types "f(\nx)") (list "ident" "op" "ident" "op" "semi" "eof")) + (go-test "ASI: blank lines collapse — single semi only" (tok-types "x\n\n\ny") (list "ident" "semi" "ident" "semi" "eof")) + (go-test "ASI: at EOF after ident" (tok-types "x") (list "ident" "semi" "eof")) + (go-test "ASI: explicit semi" (tok-types "x;y") (list "ident" "semi" "ident" "semi" "eof")) -;; ── short program ───────────────────────────────────────────────── (go-test "short-decl: x := 42 (types)" (tok-types "x := 42") (list "ident" "op" "int" "semi" "eof")) + (go-test "short-decl: x := 42 (values)" (tok-values "x := 42") (list "x" ":=" "42" "\n" nil)) + (go-test "func decl shape" (tok-types "func foo() int { return 0 }") @@ -269,5 +306,4 @@ "semi" "eof")) -;; ── report ──────────────────────────────────────────────────────── (define go-lex-test-summary (str "lex " go-test-pass "/" go-test-count)) diff --git a/plans/go-on-sx.md b/plans/go-on-sx.md index 637d3a8b..b5054af6 100644 --- a/plans/go-on-sx.md +++ b/plans/go-on-sx.md @@ -143,11 +143,13 @@ Progress-log line → push `origin/loops/go`. ident/int/string/rune/{break,continue,fallthrough,return}/{++,--,),],}}. - [x] Float / imaginary literals (decimal floats: `3.14 .5 1. 1e10 1.5e-3`; imag: `2i 3.14i 1e2i`; hex floats `0x1.fp0` deferred) -- [ ] Raw string literals `` `...` `` +- [x] Raw string literals `` `...` `` (multi-line, no escape processing, + `\r` stripped per Go spec § String literals; same `"string"` type + as interpreted strings) - [x] Hex/octal/binary integer literals (0x… 0o… 0b…) + underscores (legacy 0123 octal also accepted; consumes lex-hex-digit?) - [ ] Full operator set audit (47 distinct per Go spec) -- **Acceptance:** lex/ suite at 50+ tests. Current: 114/114. +- **Acceptance:** lex/ suite at 50+ tests. Current: 123/123. ### Phase 2 — Parser (`lib/go/parse.sx`) ⬜ - Consume `lib/guest/core/pratt.sx` + `lib/guest/core/ast.sx`. Chisel notes @@ -406,6 +408,12 @@ _(none yet)_ _Newest first. Append one dated entry per commit._ +- 2026-05-27 — Phase 1 cont.: raw string literals (backtick-delimited). + Multi-line, no escape processing, `\r` stripped per Go spec § String + literals. Same `"string"` token type as interpreted strings — parsers + / type checkers don't need to distinguish. +9 tests, lex 123/123. + `[nothing]` — pure Go work; raw strings don't touch the substrate or + lib/guest story. - 2026-05-27 — Phase 1 cont.: decimal float + imaginary literals. `3.14`, `.5`, `1.`, `1e10`, `1.5e-3`, `2i`, `3.14i`. `gl-finish-number!` handles exponent + `i` suffix; `gl-read-number!` returns the type