diff options
Diffstat (limited to 'internal/parser/parser.ha')
| -rw-r--r-- | internal/parser/parser.ha | 96 |
1 files changed, 73 insertions, 23 deletions
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)?) { |
