public inbox for ~johnnyrichard/olang-devel@lists.sr.ht
 help / color / mirror / code / Atom feed
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


  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