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:
| M | compiler.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;