fix(lang): a template inside another's hole, and integer literals past 2^31 - 1

A template literal nested in a {...} hole crashed the parser: the outer
literal ended at the inner backtick. The lexer (and ludic-fmt's) now
reads a hole as code, taking strings, chars and templates in it whole.
A decimal literal past 2147483647, or a hex one of more than eight
digits, was wrapped into a negative int; it is a long with its value
now, and giving one to an int is refused. Reseed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 08:10:46 +03:00
parent b401f7acc1
commit afa4d23a4f
17 changed files with 47107 additions and 46056 deletions

View file

@ -136,6 +136,38 @@ program LudicFmt {
return c == '&' or c == '|' or c == '^' or c == '~' # & | ^ ~
}
# the backtick that closes the template opening at s[i0] (or the end): a `{...}` hole is code, so
# a string, a char or another template inside it is skipped whole - as the compiler reads it
function fmt_tmpl_end(s: pointer, i0: int) -> int {
var i = i0 + 1
while s[i] != 0 and s[i] != '`' {
if s[i] == '\\' and s[i + 1] != 0 { i += 2; continue }
if s[i] == '{' and s[i + 1] == '{' { i += 2; continue }
if s[i] == '{' { i = fmt_hole_end(s, i + 1) }
if s[i] != 0 { i += 1 }
}
return i
}
function fmt_hole_end(s: pointer, i0: int) -> int {
var i = i0
var depth = 1
while s[i] != 0 {
let d = s[i]
if d == '"' or d == '\'' {
i += 1
while s[i] != 0 and s[i] != d { if s[i] == '\\' and s[i + 1] != 0 { i += 1 }; i += 1 }
}
else if d == '`' { i = fmt_tmpl_end(s, i) }
else if d == '{' { depth += 1 }
else if d == '}' {
depth -= 1
if depth == 0 { return i }
}
if s[i] != 0 { i += 1 }
}
return i
}
function lex(s: pointer) -> void {
src = s
tk_kind = new []int; tk_start = new []int; tk_end = new []int; tk_line = new []int
@ -155,9 +187,9 @@ program LudicFmt {
if s[i] == '"' { i += 1 }
push_tok(LT_STR, st, i, line); continue
}
if c == '`' { # `interpolated`
let st = i; i += 1
while s[i] != 0 and s[i] != '`' { if s[i] == '\\' and s[i + 1] != 0 { i += 2 } else { i += 1 } }
if c == '`' { # `interpolated`, holes and all
let st = i
i = fmt_tmpl_end(s, i)
if s[i] == '`' { i += 1 }
push_tok(LT_STR, st, i, line); continue
}