changeset 506:7e8298f7bc0a

Add basic syntax for typecasting Add parser support for type casts. This current scheme handles only integer types. Also include parenthesis grouping in expressions.
author William Astle <lost@l-w.ca>
date Sun, 27 Oct 2019 12:06:01 -0600
parents 59b8c8b15bd4
children dd9c5cef2e80
files lwcc/cc-parse.c lwcc/tree.c lwcc/tree.h
diffstat 3 files changed, 127 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/lwcc/cc-parse.c	Sat Oct 26 22:01:55 2019 -0600
+++ b/lwcc/cc-parse.c	Sun Oct 27 12:06:01 2019 -0600
@@ -171,9 +171,94 @@
 
 node_t *parse_expr_real(struct parser_state *ps, int prec);
 
+// parse an elementary type (int, etc.)
+node_t *parse_elem_type(struct parser_state *ps)
+{
+    int sgn = -1;
+    int nt = -1;
+    int nn = 1;
+
+    if (ps -> curtok -> ttype == TOK_KW_SIGNED)
+    {
+        sgn = 1;
+        parse_next(ps);
+    }
+    else if (ps -> curtok -> ttype == TOK_KW_UNSIGNED)
+    {
+        sgn = 0;
+        parse_next(ps);
+    }
+    
+    switch (ps -> curtok -> ttype)
+    {
+    // NOTE: char is unsigned by default
+    case TOK_KW_CHAR:
+        if (sgn == -1 || sgn == 0)
+            nt = NODE_TYPE_UCHAR;
+        else
+            nt = NODE_TYPE_CHAR;
+        break;
+    
+    case TOK_KW_SHORT:
+        nt = sgn ? NODE_TYPE_SHORT : NODE_TYPE_USHORT;
+        break;
+    
+    case TOK_KW_INT:
+        nt = sgn ? NODE_TYPE_INT : NODE_TYPE_UINT;
+        break;
+    
+    case TOK_KW_LONG:
+        parse_next(ps);
+        if (ps -> curtok -> ttype == TOK_KW_LONG)
+        {
+            nt = sgn ? NODE_TYPE_LONGLONG : NODE_TYPE_ULONGLONG;
+            break;
+        }
+        nn = 0;
+        nt = sgn ? NODE_TYPE_LONG : NODE_TYPE_ULONG;
+        break;
+    
+    }
+    if (nt == -1)
+    {
+        if (sgn == -1)
+        {
+            return NULL;
+        }
+        else
+        {
+            nt = sgn ? NODE_TYPE_INT : NODE_TYPE_UINT;
+        }
+    }
+    else if (nn)
+    {
+        parse_next(ps);
+    }
+    return node_create(nt);
+}
+
+// if ident is non-zero, accept an identifier as part of the type; otherwise
+// do not accept an identifier; currently a stub
+node_t *parse_type(struct parser_state *ps, int ident)
+{
+    node_t *rv;
+
+    // see if we have an elementary type
+    rv = parse_elem_type(ps);
+
+    // look for "struct", etc.
+
+    // look for pointer indicator(s)
+
+    // look for identifier if wanted/allowed
+
+    // look for array indicator or function parameter list
+    return rv;
+}
+
 node_t *parse_term_real(struct parser_state *ps)
 {
-    node_t *rv;
+    node_t *rv, *rv2;
 
     switch (ps -> curtok -> ttype)
     {
@@ -181,6 +266,40 @@
         rv = node_create(NODE_CONST_INT, ps -> curtok -> strval);
         parse_next(ps);
         return rv;
+     
+    // opening paren: either grouping or type cast
+    case TOK_OPAREN:
+        parse_next(ps);
+        // parse a type without an identifier
+        rv2 = parse_type(ps, 0);
+        if (rv2)
+        {
+            if (ps -> curtok -> ttype != TOK_CPAREN)
+            {   
+                node_destroy(rv2);
+                parse_generr(ps, "missing ) on type cast");
+                return NULL;
+            }
+            parse_next(ps);
+            // detect C99 compound literal here
+            rv = parse_expr_real(ps, 175);
+            if (!rv)
+            {
+                node_destroy(rv);
+                return NULL;
+            }
+            return node_create(NODE_TYPECAST, rv2, rv);
+        }
+        // grouping
+        rv = parse_expr_real(ps, 0);
+        if (ps -> curtok -> ttype != TOK_CPAREN)
+        {
+            node_destroy(rv);
+            parse_generr(ps, "missing ) on expression grouping");
+            return NULL;
+        }
+        parse_next(ps);
+        return rv;
     }
 
     parse_generr(ps, "term");
--- a/lwcc/tree.c	Sat Oct 26 22:01:55 2019 -0600
+++ b/lwcc/tree.c	Sun Oct 27 12:06:01 2019 -0600
@@ -90,6 +90,7 @@
 	"OPER_BWXORASS",
 	"OPER_BWORASS",
 	"OPER_COMMA",
+	"TYPECAST",
 };
 
 
@@ -151,6 +152,10 @@
 		nargs = 2;
 		break;
 
+	case NODE_TYPECAST:
+		nargs = 2;
+		break;
+
 	case NODE_OPER_POSTINC:
 	case NODE_OPER_POSTDEC:
 		nargs = 1;
--- a/lwcc/tree.h	Sat Oct 26 22:01:55 2019 -0600
+++ b/lwcc/tree.h	Sun Oct 27 12:06:01 2019 -0600
@@ -88,7 +88,8 @@
 #define NODE_OPER_BWXORASS  60  // bitwise xor/assign combo
 #define NODE_OPER_BWORASS   61  // bitwise or/assign combo
 #define NODE_OPER_COMMA     62  // comma sequential evaluation operator
-#define NODE_NUMTYPES		63	// the number of node types
+#define NODE_TYPECAST       63  // type cast to unsigned long long
+#define NODE_NUMTYPES		64	// the number of node types
 
 typedef struct node_s node_t;