commit 7ae2b8126ebb7af67bbaddbe852f2b6fdc5c1fbe
parent 434b0543c55064256c267256bc455f5217fee897
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 6 Apr 2021 12:15:15 -0400
hare::parse: skeleton for postfix-expression
Diffstat:
4 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha
@@ -89,6 +89,7 @@ export fn lex(lex: *lexer) ((token, location) | io::EOF | error) = {
']' => btoken::RBRACKET,
')' => btoken::RPAREN,
';' => btoken::SEMICOLON,
+ '?' => btoken::QUESTION,
};
return (tok, loc);
};
diff --git a/hare/lex/token.ha b/hare/lex/token.ha
@@ -24,6 +24,7 @@ export type btoken = enum {
CONTINUE,
DEF,
DEFER,
+ DELETE,
ELSE,
ENUM,
EXPORT,
@@ -71,6 +72,8 @@ export type btoken = enum {
BAND,
BNOT,
BOR,
+ BXOR,
+ BXOREQ,
CASE,
COLON,
COMMA,
@@ -104,6 +107,7 @@ export type btoken = enum {
PLUS,
PLUSEQ,
PLUSPLUS,
+ QUESTION,
RBRACE,
RBRACKET,
RPAREN,
@@ -113,8 +117,6 @@ export type btoken = enum {
SLICE,
TIMES,
TIMESEQ,
- BXOR,
- BXOREQ,
};
const bmap: [_]str = [
@@ -138,6 +140,7 @@ const bmap: [_]str = [
"continue",
"def",
"defer",
+ "delete",
"else",
"enum",
"export",
@@ -180,6 +183,8 @@ const bmap: [_]str = [
"void",
"&=",
"&",
+ "^",
+ "^=",
"~",
"|",
"=>",
@@ -208,6 +213,7 @@ const bmap: [_]str = [
"-",
"-=",
"--",
+ "?",
"%=",
"%",
"!=",
@@ -224,8 +230,6 @@ const bmap: [_]str = [
"..",
"*",
"*=",
- "^",
- "^=",
];
// A loop label, such as ':example'
diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha
@@ -72,16 +72,54 @@ fn objsel(lexer: *lex::lexer) (ast::expr | error) = {
abort(); // TODO
};
-fn postfix(lexer: *lex::lexer) (ast::expr | error) = {
+fn plain_expression(lexer: *lex::lexer) (ast::expr | error) = {
want_btoken(lexer, btoken::VOID)?; // TODO
return void;
};
+fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = {
+ // Built-ins (XXX: these should probably be moved in the Hare grammar)
+ match (peek_btoken(lexer,
+ btoken::ALLOC, btoken::APPEND, btoken::FREE,
+ btoken::DELETE, btoken::ABORT, btoken::ASSERT,
+ btoken::STATIC, btoken::SIZE, btoken::LEN,
+ btoken::OFFSET)?) {
+ tok: btoken => {
+ if (lvalue is ast::expr) {
+ return syntaxerr(mkloc(lexer),
+ "Unexpected {}, was expecting '(', '.', or '['",
+ lex::tokstr(tok));
+ };
+ abort(); // TODO: Delegate as appropriate
+ },
+ void => void,
+ };
+
+ let lvalue = match (lvalue) {
+ void => plain_expression(lexer)?,
+ ex: ast::expr => ex,
+ };
+
+ match (try_btoken(lexer, btoken::LPAREN, btoken::DOT, btoken::LBRACKET,
+ btoken::QUESTION)) {
+ tok: btoken => switch (tok) {
+ btoken::LPAREN => abort(), // TODO: Calls
+ btoken::DOT => abort(), // TODO: Field access
+ btoken::LBRACKET => abort(), // TODO: Indexing
+ btoken::QUESTION => abort(), // TODO: Propagation
+ * => abort(),
+ },
+ void => return lvalue,
+ };
+
+ return postfix(lexer, lvalue);
+};
+
fn unarithm(lexer: *lex::lexer) (ast::expr | error) = {
const tok = match (try_btoken(lexer,
btoken::PLUS, btoken::MINUS, btoken::BNOT,
btoken::LNOT, btoken::TIMES, btoken::BAND)) {
- void => return postfix(lexer),
+ void => return postfix(lexer, void),
tok: btoken => tok,
};
const op = switch (tok) {
diff --git a/hare/parse/util.ha b/hare/parse/util.ha
@@ -93,6 +93,32 @@ fn try_btoken(
lex::unlex(lexer, tuple);
};
+// Looks for a matching btoken from the lexer, unlexes the token, and returns
+// it; or void if it was not a btoken.
+fn peek_btoken(
+ lexer: *lex::lexer,
+ want: lex::btoken...
+) (lex::btoken | error | void) = {
+ let tok = lex::lex(lexer);
+ let tuple = match (tok?) {
+ io::EOF => return,
+ t: (lex::token, lex::location) => {
+ match (t.0) {
+ b: lex::btoken =>
+ for (let i = 0z; i < len(want); i += 1) {
+ if (b == want[i]) {
+ lex::unlex(lexer, t);
+ return b;
+ };
+ },
+ * => void,
+ };
+ t;
+ },
+ };
+ lex::unlex(lexer, tuple);
+};
+
// Identical to [lex::lex], but considers io::EOF a syntax error.
fn mustlex(lexer: *lex::lexer) ((lex::token, lex::location) | error) = {
return match (lex::lex(lexer)) {