mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 16:54:25 +00:00
const, if as a value, """ text over several lines, min/max/abs/clamp, import a/b and import x as y, the fs module
- const NAME = value (numbers, text, other constants; typed: const f32 G = 9.8), also module.NAME
- x := if c { a } else { b }
- """ ... """: the closing quotes' indentation goes from every line
- min, max, abs, clamp for any numbers, unless your own function has the name
- import ui/button (a module in a folder), import path as p
- fs: read_bytes, write_bytes, exists, is_dir, mkdir (with parents), list, remove_dir, data_dir(app)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016GzNP6r8dg6WDxUVZy8wjL
This commit is contained in:
parent
d0666cf788
commit
f2d6480749
21 changed files with 688 additions and 17 deletions
|
|
@ -24,7 +24,7 @@ fn isHex(char c) -> bool {
|
|||
|
||||
fn isKeyword(str w) -> bool {
|
||||
keywords := ["fn", "return", "if", "else", "while", "for", "in", "break", "continue", "true", "false",
|
||||
"null", "import", "link", "struct", "defer", "or", "try", "enum", "match", "export"]
|
||||
"null", "import", "link", "struct", "defer", "or", "try", "enum", "match", "export", "const"]
|
||||
return keywords.contains(w)
|
||||
}
|
||||
|
||||
|
|
@ -78,6 +78,57 @@ fn operator(ptr[Lexer] lx) -> str {
|
|||
return ""
|
||||
}
|
||||
|
||||
// """ text over several lines """: the line break after the opening quotes is dropped, and so is
|
||||
// the indentation of the closing quotes, from every line (the text can be indented with the code).
|
||||
fn longString(ptr[Lexer] lx, Token t) -> str {
|
||||
for k in 0..3 {
|
||||
advance(lx)
|
||||
}
|
||||
[]str parts
|
||||
while !(peek(lx, 0) == '"' && peek(lx, 1) == '"' && peek(lx, 2) == '"') {
|
||||
if lx.i >= lx.src.len {
|
||||
fail(lx, t.line, t.col, "text is never closed (missing \"\"\")")
|
||||
}
|
||||
ch := peek(lx, 0)
|
||||
advance(lx)
|
||||
if ch == '\\' {
|
||||
e := peek(lx, 0)
|
||||
advance(lx)
|
||||
ch = escape(lx, e)
|
||||
} else if ch == '\r' {
|
||||
continue
|
||||
}
|
||||
parts.push(str(ch))
|
||||
}
|
||||
for k in 0..3 {
|
||||
advance(lx)
|
||||
}
|
||||
lx.nl = false // the line breaks inside were text, not the end of a statement
|
||||
body := parts.join("")
|
||||
if body.starts_with("\n") {
|
||||
body = body.sub(1, body.len)
|
||||
}
|
||||
last := body.split("\n")
|
||||
indent := last[last.len - 1]
|
||||
if last.len > 1 && indent.trim().len == 0 {
|
||||
// the closing quotes are on their own line: their indentation goes from every line
|
||||
[]str lines
|
||||
for i in 0..last.len - 1 {
|
||||
line := last[i]
|
||||
if line.starts_with(indent) {
|
||||
line = line.sub(indent.len, line.len)
|
||||
} else if line.trim().len > 0 {
|
||||
fail(lx, t.line, t.col, "a line of this text is indented less than the closing \"\"\"")
|
||||
} else {
|
||||
line = ""
|
||||
}
|
||||
lines.push(line)
|
||||
}
|
||||
return lines.join("\n")
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
fn escape(ptr[Lexer] lx, char e) -> char {
|
||||
if e == 'n' {
|
||||
return '\n'
|
||||
|
|
@ -185,6 +236,9 @@ fn lex(str src, str path) -> []Token {
|
|||
if mant.len > 0 {
|
||||
t.text = (mant + lx.src.sub(expStart, lx.i)).replace("_", "") // LLVM wants the '.'
|
||||
}
|
||||
} else if c == '"' && peek(lx, 1) == '"' && peek(lx, 2) == '"' {
|
||||
t.kind = "string"
|
||||
t.text = longString(lx, t)
|
||||
} else if c == '"' || c == '\'' {
|
||||
quote := c
|
||||
t.kind = "string"
|
||||
|
|
|
|||
Loading…
Reference in a new issue