Aria

A low-level systems programming language
git clone git://git.m21c.me/Aria.git
Log | Files | Refs | LICENSE

commit d7d718c343f3a1f835a80dd66cf86a21ffb2638a
parent f98725c44ba9e0107206fe692d57cc8d6ca4f454
Author: m21c  <ho*******@gmail.com>
Date:   Thu,  2 Feb 2023 05:09:06 +0100

added token pushnack + fixed clause parsing

Diffstat:
Mcompiler.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 77 insertions(+), 14 deletions(-)

diff --git a/compiler.c b/compiler.c @@ -528,7 +528,7 @@ struct Source { char stringbuf[1024]; int lastindent, lastkind; - Node tok; + Node tok, savedtok; /* environment */ @@ -1351,6 +1351,12 @@ gettok(Source *source) source->lastkind = source->tok.kind; + if (source->savedtok.kind) { + source->tok = source->savedtok; + source->savedtok.kind = 0; + return source->tok.kind; + } + skipwhite: if (hasnewline) { if (!mygetline(source)) { @@ -1507,6 +1513,15 @@ skipwhite: #undef select } +static void +pushbacktok(Source *source, Node *tok) +{ + assert(source->savedtok.kind == 0); + + source->savedtok = source->tok; + source->tok = *tok; +} + #define skipnewline(source) \ ((source)->tok.kind == LINEDELIM ? (void) gettok(source) : (void) 0) @@ -2080,34 +2095,56 @@ static bool checkend(Source *source, bool hastail, int needindent, const char *expecterrmsg) { + Node savedtok = {0}; + if (getkind(source) == LINEDELIM) { + savedtok = source->tok; + gettok(source); if (getkind(source) == SEMIDELIM) { error(getloc(source), expecterrmsg); gettok(source); + + pushbacktok(source, &savedtok); return true; } } - if (source->lastkind == LINEDELIM && source->lastindent < needindent) + if (source->lastkind == LINEDELIM && source->lastindent < needindent) { + /* NOTE(m21c): Is that correct? Maybe we should always pushback + * a made-up new-line, instead of asserting that we + * have saved one. Since it might be the case, that + * we already have read a new-line prior the call + * to this function. But I'll leave it this way, + * for now. */ + /* assert(savedtok.kind == LINEDELIM); */ + + if (savedtok.kind == LINEDELIM) + pushbacktok(source, &savedtok); return true; + } if (getkind(source) == SEMIDELIM) { + savedtok = source->tok; gettok(source); /* NOTE(m21c): used for REPL. it allows having * semicolons on line-endings and nultiple * adjacent semecolons in REPL-mode. */ - if (getkind(source) == SEMIDELIM || getkind(source) == LINEDELIM) { - /* TODO(m21c): output an error-message if not in REPL-mode */ - } + if ((getkind(source) == SEMIDELIM || + getkind(source) == LINEDELIM) && + source->filein != stdin) + /* NOTE(m21c): output an error-message if not in REPL-mode */ + error(&savedtok.loc, "trailing semicolon."); } if (isdelimiter(source->tok.kind)) return true; - if (hastail && source->lastkind != LINEDELIM && source->lastkind != SEMIDELIM) + if (hastail && + source->lastkind != LINEDELIM && + source->lastkind != SEMIDELIM) error(getloc(source), "expected line delimiter"); return false; @@ -2532,6 +2569,27 @@ readrecord(Source *source, bool isunion) return recordnode; } +static bool +skipnewlineontok(Source *source, Kind kind, int neededindent) +{ + Node savedtok; + + if (getkind(source) == kind) + return source->lastindent >= neededindent; + + if (getkind(source) == LINEDELIM) { + savedtok = source->tok; + + if (gettok(source) == kind && + source->lastindent >= neededindent) + return true; + + pushbacktok(source, &savedtok); + } + + return false; +} + static Node * readatom(Source *source, int flags) { @@ -2661,7 +2719,8 @@ readatom(Source *source, int flags) case KVAR: gettok(source); lhs = declaration(source, primitive(TINFER), false); - break; + /* skip postfix-operators */ + return lhs; case KFALSE: case KTRUE: @@ -2683,7 +2742,8 @@ readatom(Source *source, int flags) case KSTRUCT: case KUNION: lhs = readrecord(source, source->tok.kind == KUNION); - break; + /* skip postfix-operators */ + return lhs; case KNOT: lhs = tokennode(source, NULL); @@ -2761,7 +2821,8 @@ readatom(Source *source, int flags) lhs = tokennode(source, NULL); gettok(source); lhs->lhs = stmtlist(source, indent, SDO, NULL, false); - break; + /* skip postfix-operators */ + return lhs; case KLOOP: indent = source->lastindent; @@ -2769,7 +2830,7 @@ readatom(Source *source, int flags) gettok(source); lhs->lhs = stmtlist(source, indent, SLOOP, NULL, false); - if (getkind(source) == KUNTIL && source->lastindent >= indent) { + if (skipnewlineontok(source, KUNTIL, indent)) { lhs->kind = ALOOPUNTIL; gettok(source); lhs->u.payload = readexpr(source, POR); @@ -2778,7 +2839,8 @@ readatom(Source *source, int flags) if (lhs->kind != KLOOP) goto joinelse; else - break; + /* skip postfix-operators */ + return lhs; case KWHILE: indent = source->lastindent; @@ -2800,15 +2862,16 @@ readatom(Source *source, int flags) lhs->lhs = stmtlist(source, indent, SIF, NULL, false); joinelse: - if (getkind(source) == KELSE && source->lastindent >= indent) { + if (skipnewlineontok(source, KELSE, indent)) { gettok(source); lhs->rhs = stmtlist(source, indent, SELSE, NULL, false); } - break; + /* skip postfix-operators */ + return lhs; default: - joinerror: + /* joinerror: */ error(getloc(source), "expected expression"); lhs = tokennode(source, NULL); lhs->kind = NUMBER;