From: Johnny Richard <johnny@johnnyrichard.com>
To: ~johnnyrichard/olang-devel@lists.sr.ht
Cc: Johnny Richard <johnny@johnnyrichard.com>
Subject: [PATCH olang v1 2/2] parser: spec: allow nested unary expressions
Date: Mon, 14 Oct 2024 13:29:48 +0200 [thread overview]
Message-ID: <20241014113011.108922-3-johnny@johnnyrichard.com> (raw)
In-Reply-To: <20241014113011.108922-1-johnny@johnnyrichard.com>
Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
---
docs/info/olang.ebnf | 13 ++++----
src/parser.c | 58 ++++++++++++++++++++++++----------
tests/olc/0035_unary_nested.ol | 36 +++++++++++++++++++++
3 files changed, 84 insertions(+), 23 deletions(-)
create mode 100644 tests/olc/0035_unary_nested.ol
diff --git a/docs/info/olang.ebnf b/docs/info/olang.ebnf
index 76a5c2f..791c6f0 100644
--- a/docs/info/olang.ebnf
+++ b/docs/info/olang.ebnf
@@ -52,19 +52,18 @@
<cmp-relational-expression> ::= <bitwise-shift-expression> (<ows> ('<' | '>' | '<=' | '>=') <ows> <bitwise-shift-expression>)*
<bitwise-shift-expression> ::= <additive-expression> (<ows> ('<<' | '>>') <ows> <additive-expression>)*
<additive-expression> ::= <multiplicative-expression> (<ows> ('+' | '-') <ows> <multiplicative-expression>)*
-<multiplicative-expression> ::= <primary-expression> (<ows> ('*' | '/' | '%') <ows> <primary-expression>)*
-<primary-expression> ::= <integer-literal>
- | <variable-name>
- | <function-call>
- | <unary-expression>
- | '(' <ows> <expression> <ows> ')'
-<unary-expression> ::= <unary-operator> <ows> <primary-expression>
+<multiplicative-expression> ::= <unary-expression> (<ows> ('*' | '/' | '%') <ows> <unary-expression>)*
+<unary-expression> ::= (<unary-operator> <ows>)* <primary-expression>
<unary-operator> ::= '&'
| '*'
| '+'
| '-'
| '~'
| '!'
+<primary-expression> ::= <integer-literal>
+ | <variable-name>
+ | <function-call>
+ | '(' <ows> <expression> <ows> ')'
(* Identifiers *)
<type> ::= ('u8' | 'u16' | 'u32' | 'u64') (<ows> '*')*
diff --git a/src/parser.c b/src/parser.c
index 8b103df..35cf017 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -28,6 +28,9 @@
static bool
skip_expected_token(parser_t *parser, token_kind_t expected_kind);
+static void
+skip_next_token(parser_t *parser);
+
static bool
expected_next_token(parser_t *parser, token_t *token, token_kind_t kind);
@@ -64,6 +67,9 @@ parser_parse_fn_params(parser_t *parser);
static ast_node_t *
parser_parse_expr(parser_t *parser);
+static ast_node_t *
+parser_parse_unary_expr(parser_t *parser);
+
static ast_node_t *
parser_parse_primary_expr(parser_t *parser);
@@ -247,7 +253,7 @@ parser_parse_expr_1(parser_t *parser, ast_node_t *lhs, size_t prev_precedence)
token_t token_op;
lexer_next_token(parser->lexer, &token_op);
- ast_node_t *rhs = parser_parse_primary_expr(parser);
+ ast_node_t *rhs = parser_parse_unary_expr(parser);
if (rhs == NULL) {
return NULL;
}
@@ -278,7 +284,7 @@ parser_parse_expr_1(parser_t *parser, ast_node_t *lhs, size_t prev_precedence)
static ast_node_t *
parser_parse_expr(parser_t *parser)
{
- ast_node_t *lhs = parser_parse_primary_expr(parser);
+ ast_node_t *lhs = parser_parse_unary_expr(parser);
if (lhs == NULL) {
return NULL;
}
@@ -286,6 +292,33 @@ parser_parse_expr(parser_t *parser)
return parser_parse_expr_1(parser, lhs, BINOP_MIN_PREC);
}
+static ast_node_t *
+parser_parse_unary_expr(parser_t *parser)
+{
+ token_t token;
+ lexer_peek_next(parser->lexer, &token);
+ switch (token.kind) {
+ case TOKEN_AND:
+ case TOKEN_STAR:
+ case TOKEN_PLUS:
+ case TOKEN_DASH:
+ case TOKEN_TILDE:
+ case TOKEN_BANG: {
+ skip_next_token(parser);
+ ast_node_t *expr = parser_parse_unary_expr(parser);
+ if (expr == NULL) {
+ return NULL;
+ }
+
+ ast_unary_op_kind_t kind = token_kind_to_unary_op_kind(token.kind);
+ return ast_new_node_unary_op(parser->arena, token.loc, kind, expr);
+ }
+ default: {
+ return parser_parse_primary_expr(parser);
+ }
+ }
+}
+
static ast_node_t *
parser_parse_primary_expr(parser_t *parser)
{
@@ -310,20 +343,6 @@ parser_parse_primary_expr(parser_t *parser)
return ast_new_node_ref(
parser->arena, token_id.loc, token_id.value);
}
- case TOKEN_AND:
- case TOKEN_STAR:
- case TOKEN_PLUS:
- case TOKEN_DASH:
- case TOKEN_TILDE:
- case TOKEN_BANG: {
- ast_node_t *expr = parser_parse_primary_expr(parser);
- if (expr == NULL) {
- return NULL;
- }
-
- ast_unary_op_kind_t kind = token_kind_to_unary_op_kind(token.kind);
- return ast_new_node_unary_op(parser->arena, token.loc, kind, expr);
- }
case TOKEN_OPAREN: {
ast_node_t *expr = parser_parse_expr(parser);
@@ -740,6 +759,13 @@ skip_expected_token(parser_t *parser, token_kind_t expected_kind)
return expected_next_token(parser, &token, expected_kind);
}
+static void
+skip_next_token(parser_t *parser)
+{
+ token_t token;
+ lexer_next_token(parser->lexer, &token);
+}
+
static bool
expected_next_token(parser_t *parser,
token_t *token,
diff --git a/tests/olc/0035_unary_nested.ol b/tests/olc/0035_unary_nested.ol
new file mode 100644
index 0000000..ef4e936
--- /dev/null
+++ b/tests/olc/0035_unary_nested.ol
@@ -0,0 +1,36 @@
+# Copyright (C) 2024 olang mantainers
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+fn main(): u32 {
+ var e: u32 = 0
+ return ~~e
+}
+
+# TEST test_compile(exit_code=0)
+#
+# TEST test_run_binary(exit_code=0)
+#
+# TEST test_ast WITH
+# Translation_Unit
+# `-Function_Definition <name:main> <return:u32>
+# `-Block
+# |-Var_Definition <name:e> <kind:u32>
+# | `-Literal <kind:u32> <value:0>
+# `-Return_Statement
+# `-Unary_Operation (~)
+# `-Unary_Operation (~)
+# `-Reference <name:e>
+# END
+
--
2.46.0
next prev parent reply other threads:[~2024-10-14 9:31 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-14 11:29 [PATCH olang v1 0/2] parser: spec: allow nested expresssion Johnny Richard
2024-10-14 9:39 ` Carlos Maniero
2024-10-14 11:29 ` [PATCH olang v1 1/2] parser: rename factor to primary_expr Johnny Richard
2024-10-14 11:29 ` Johnny Richard [this message]
2024-10-14 9:31 ` [olang/patches/.build.yml] build success builds.sr.ht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241014113011.108922-3-johnny@johnnyrichard.com \
--to=johnny@johnnyrichard.com \
--cc=~johnnyrichard/olang-devel@lists.sr.ht \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.johnnyrichard.com/olang.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox