diff options
| -rw-r--r-- | cmd/hs/hs.ha | 73 | ||||
| -rw-r--r-- | internal/parser/parser.ha | 96 |
2 files changed, 120 insertions, 49 deletions
diff --git a/cmd/hs/hs.ha b/cmd/hs/hs.ha index c0ad72f..233c54f 100644 --- a/cmd/hs/hs.ha +++ b/cmd/hs/hs.ha @@ -12,42 +12,63 @@ export fn main() void = { state = parser::tokentype::START, unreadbuf = ['0'...], unreadcount = 0z, + currentline = 1z, + end = false, }; - let ast = parser::parse(&p); - let ast = match (ast) { - case let a: parser::ast => - yield a; - case let e: parser::error => - fmt::fatal(parser::strerror(e)); - }; - walkast(ast); + let it = interpreter::interpreter { vars = [], }; - interpreter::interpret(&it, ast); - - let ast = parser::parse(&p); - let ast = match (ast) { - case let a: parser::ast => - yield a; - case let e: parser::error => - fmt::fatal(parser::strerror(e)); + for (let ast => parser::parse(&p)) { + let ast = match (ast) { + case let a: parser::ast => + yield a; + case let e: parser::error => + fmt::println("poopies")!; + fmt::fatal(parser::strerror(e)); + }; + interpreter::interpret(&it, ast); }; - interpreter::interpret(&it, ast); - for (let var .. it.vars) { fmt::printfln("{}: {}", var.0, var.1)!; }; - let ast = parser::parse(&p); - let ast = match (ast) { - case let a: parser::ast => - yield a; - case let e: parser::error => - fmt::fatal(parser::strerror(e)); - }; - interpreter::interpret(&it, ast); +// let ast = parser::parse(&p); +// let ast = match (ast) { +// case let a: parser::ast => +// yield a; +// case let e: parser::error => +// fmt::fatal(parser::strerror(e)); +// }; +// walkast(ast); +// let it = interpreter::interpreter { +// vars = [], +// }; +// +// interpreter::interpret(&it, ast); +// +// let ast = parser::parse(&p); +// let ast = match (ast) { +// case let a: parser::ast => +// yield a; +// case let e: parser::error => +// fmt::fatal(parser::strerror(e)); +// }; +// interpreter::interpret(&it, ast); +// +// for (let var .. it.vars) { +// fmt::printfln("{}: {}", var.0, var.1)!; +// }; +// +// let ast = parser::parse(&p); +// let ast = match (ast) { +// case let a: parser::ast => +// yield a; +// case let e: parser::error => +// fmt::fatal(parser::strerror(e)); +// }; + //interpreter::interpret(&it, ast); //let tk = parsetoken(&p); //fmt::printfln("tk value: {}\ntk type: {}", tk.value, parser::strtktype(tk.tktype))!; diff --git a/internal/parser/parser.ha b/internal/parser/parser.ha index 39b9abc..55b143e 100644 --- a/internal/parser/parser.ha +++ b/internal/parser/parser.ha @@ -69,6 +69,8 @@ export type parser = struct { state: tokentype, unreadbuf: [2]rune, unreadcount: size, + currentline: size, + end: bool, }; type validrunecondfn = *fn(c: rune) bool; @@ -105,7 +107,16 @@ fn read_rune(p: *parser) (rune | io::EOF | error) = { p.unreadcount -= 1; return p.unreadbuf[p.unreadcount]; } else { - return bufio::read_rune(p.h)?; + return match (bufio::read_rune(p.h)?) { + case let r: rune => + if (r == '\n') { + p.currentline += 1; + }; + yield r; + case io::EOF => + p.end = true; + yield io::EOF; + }; }; }; @@ -124,13 +135,15 @@ fn parsetil( til: (rune | []rune), cond: (void | validrunecond), runecount: size, - linenb: size = 0, ) -(str | error) = { +(str | io::EOF | error) = { let m = memio::dynamic(); defer io::close(&m)!; return for (let r => read_rune(p)?) { + if (r == '\n') { + continue; + }; runecount += 1; const ismatch = match (til) { case let ru: rune => @@ -150,15 +163,18 @@ fn parsetil( if (c.f(r)) { memio::appendrune(&m, r)?; } else { - break (runecount, linenb, c.err): error; + break (runecount, p.currentline, c.err): error; }; }; } else { - return (runecount, linenb, "Syntax error: variable not assigned or used"): error; + if (runecount == 0) { + return io::EOF; + }; + return (runecount, p.currentline, "Syntax error: variable not assigned or used"): error; }; }; -fn parsevarname(p: *parser, runecount: size, linenb: size = 0) (varname | error) = { +fn parsevarname(p: *parser, runecount: size) (varname | error) = { let m = memio::dynamic(); defer io::close(&m)!; @@ -172,14 +188,14 @@ fn parsevarname(p: *parser, runecount: size, linenb: size = 0) (varname | error) if (ascii::isalnum(r)) { memio::appendrune(&m, r)?; } else { - break (runecount, linenb, "Character is not alphanumeric"): error; + break (runecount, p.currentline, "Character is not alphanumeric"): error; }; } else { - return (runecount, linenb, "Syntax error: variable not assigned or used"): error; + return (runecount, p.currentline, "Syntax error: variable not assigned or used"): error; }; }; -fn parsearglist(p: *parser, runecount: size, linenb: size = 0) (arglist | error) = { +fn parsearglist(p: *parser, runecount: size) (arglist | error) = { static let buf: [256]u8 = @undefined; let arglist: arglist = []; @@ -190,11 +206,23 @@ fn parsearglist(p: *parser, runecount: size, linenb: size = 0) (arglist | error) switch (r) { case '"' => let arg = parsetil(p, '"', void, 0z)?; + let arg = match (arg) { + case io::EOF => + return (runecount, p.currentline, "Unexpected EOF"): error; + case let a: str => + yield a; + }; // reread unread " read_rune(p)?; append(arglist, arg)?; case '\'' => let arg = parsetil(p, '\'', void, 0z)?; + let arg = match (arg) { + case io::EOF => + return (runecount, p.currentline, "Unexpected EOF"): error; + case let a: str => + yield a; + }; // reread unread ' read_rune(p)?; append(arglist, arg)?; @@ -203,13 +231,13 @@ fn parsearglist(p: *parser, runecount: size, linenb: size = 0) (arglist | error) case ')' => break; case => - return (runecount, linenb, "Argument literals must be wrapped with \" or '"): error; + return (runecount, p.currentline, "Argument literals must be wrapped with \" or '"): error; }; }; return arglist; }; -fn parseoperation(p: *parser, runecount: size, linenb: size = 0) (operation | error) = { +fn parseoperation(p: *parser, runecount: size) (operation | error) = { static let buf: [256]u8 = @undefined; let stack: []argument = []; @@ -258,7 +286,7 @@ fn parseoperation(p: *parser, runecount: size, linenb: size = 0) (operation | er break; case => const msg = fmt::bsprintf(buf, "Unexpected char '{}'", r)?; - return (runecount, linenb, msg): error; + return (runecount, p.currentline, msg): error; }; }; }; @@ -290,7 +318,12 @@ export type ast = struct { children: []ast, }; -export fn parse(p: *parser, linenb: size = 0) (ast | error) = { +export fn parse(p: *parser) (ast | done | error) = { + if (p.end) { + fmt::errorln("newdone")!; + return done; + }; + let stop = false; //let t = parsetoken(p, linenb); @@ -300,17 +333,28 @@ export fn parse(p: *parser, linenb: size = 0) (ast | error) = { let root: ast = @undefined; for (!stop) { - let t = parsetoken(p, linenb)?; + let t = parsetoken(p)?; match (t) { - case varname => + case io::EOF => + return done; + case let t: varname => let node: ast = ast { value = t, children = [], }; append(tree, node)?; - case (assign | finvoke) => + case let t: finvoke => + root.value = t; + case let t: assign => root.value = t; - case (operation | arglist) => + case let t: operation => + let node: ast = ast { + value = t, + children = [], + }; + append(tree, node)?; + stop = true; + case let t: arglist => let node: ast = ast { value = t, children = [], @@ -325,7 +369,7 @@ export fn parse(p: *parser, linenb: size = 0) (ast | error) = { fn isalnum(c: rune) bool = ascii::isalnum(c); -export fn parsetoken(p: *parser, linenb: size = 0) (token | error) = { +export fn parsetoken(p: *parser) (token | io::EOF | error) = { static let buf: [256]u8 = @undefined; let runecount = 0z; @@ -338,8 +382,13 @@ export fn parsetoken(p: *parser, linenb: size = 0) (token | error) = { err = "Character is not alphanumeric", }; let t = parsetil(p, ['=', '('], cond, 0z)?; - p.state = tokentype::VARNAME; - yield t; + yield match (t) { + case io::EOF => + return io::EOF; + case let t: str => + p.state = tokentype::VARNAME; + yield t; + }; case tokentype::VARNAME => // look for ASSIGN let r = read_rune(p)?; @@ -353,10 +402,10 @@ export fn parsetoken(p: *parser, linenb: size = 0) (token | error) = { yield '(': finvoke; } else { const msg = fmt::bsprintf(buf, "Missing '=' or '(', found '{}' instead", r)?; - yield (runecount, linenb, msg): error; + yield (runecount, p.currentline, msg): error; }; case io::EOF => - yield (runecount, linenb, "Unexpected EOF"): error; + yield (runecount, p.currentline, "Unexpected EOF"): error; }; case tokentype::FINVOKE => // look for FINVOKE @@ -365,11 +414,12 @@ export fn parsetoken(p: *parser, linenb: size = 0) (token | error) = { yield t; case tokentype::ASSIGN => // look for OPERATION + fmt::errorln("parseoperation")!; let t = parseoperation(p, 0z)?; p.state = tokentype::START; yield t; case => - yield (runecount, linenb, "Not implemented"): error; + yield (runecount, p.currentline, "Not implemented"): error; }; //return for (let r => read_rune(p)?) { |
