changeset 501:f3e9732973f1

Add basic integer operations to lwcc Add +, -, *, and / to lwcc parser and code generator. Multiplication and division require helper functions in a yet to be created support library. These operations are integer only for the moment.
author William Astle <lost@l-w.ca>
date Tue, 24 Sep 2019 22:07:56 -0600
parents 733fd05ca2a8
children 14a40f8bb4eb
files lwcc/cc-gencode.c lwcc/cc-parse.c lwcc/tree.c lwcc/tree.h
diffstat 4 files changed, 97 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/lwcc/cc-gencode.c	Thu Aug 29 17:00:17 2019 -0600
+++ b/lwcc/cc-gencode.c	Tue Sep 24 22:07:56 2019 -0600
@@ -43,6 +43,34 @@
         fprintf(output, "\tldd #%s\n", n->strval);
         break;
 
+    case NODE_OPER_PLUS:
+        generate_code(n->children, output);
+        fprintf(output, "\tpshs d\n");
+        generate_code(n->children->next_child, output);
+        fprintf(output, "\taddd ,s++\n");
+        break;
+    
+    case NODE_OPER_MINUS:
+        generate_code(n->children, output);
+        fprintf(output, "\tpshs d,x\n");
+        generate_code(n->children->next_child, output);
+        fprintf(output, "\tstd 2,s\n\tpuls d\n\tsubd ,s++\n");
+        break;
+
+    case NODE_OPER_TIMES:
+        generate_code(n -> children, output);
+        fprintf(output, "\tpshs d\n");
+        generate_code(n->children->next_child, output);
+        fprintf(output, "\tjsr ___mul16i\n");
+        break;
+
+    case NODE_OPER_DIVIDE:
+        generate_code(n -> children, output);
+        fprintf(output, "\tpshs d\n");
+        generate_code(n->children->next_child, output);
+        fprintf(output, "\tjsr ___div16i\n");
+        break;
+
     default:
         for (nn = n -> children; nn; nn = nn -> next_child)
             generate_code(nn, output);
--- a/lwcc/cc-parse.c	Thu Aug 29 17:00:17 2019 -0600
+++ b/lwcc/cc-parse.c	Tue Sep 24 22:07:56 2019 -0600
@@ -169,19 +169,69 @@
 
 }
 
-node_t *parse_expr(struct parser_state *ps)
+node_t *parse_term_real(struct parser_state *ps)
 {
     node_t *rv;
-    if (ps -> curtok -> ttype == TOK_CONST_INT)
+
+    switch (ps -> curtok -> ttype)
     {
+    case TOK_CONST_INT:
         rv = node_create(NODE_CONST_INT, ps -> curtok -> strval);
         parse_next(ps);
         return rv;
     }
-    parse_generr(ps, "expr");
+
+    parse_generr(ps, "term");
     return NULL;
 }
 
+node_t *parse_expr_real(struct parser_state *ps, int prec)
+{
+    static struct { int tok; int nodetype; int prec; } operlist[] = {
+        { TOK_STAR, NODE_OPER_TIMES, 150 },
+        { TOK_DIV, NODE_OPER_DIVIDE, 150 },
+        { TOK_ADD, NODE_OPER_PLUS, 100 },
+        { TOK_SUB, NODE_OPER_MINUS, 100 },
+        { 0, 0, 0 }
+    };
+    node_t *term1, *term2;
+    int i;
+    
+    term1 = parse_term_real(ps);
+    if (!term1)
+        return NULL;
+
+nextoper:
+    for (i = 0; operlist[i].tok; i++)
+        if (operlist[i].tok == ps -> curtok -> ttype)
+            break;
+    fprintf(stderr, "Matched operator: %d, %d\n", operlist[i].tok, operlist[i].prec);
+    // if we hit the end of the expression, return
+    if (operlist[i].tok == 0)
+        return term1;
+
+    // is the next operator less or same precedence?
+    if (operlist[i].prec <= prec)
+        return term1;
+
+    parse_next(ps);
+    term2 = parse_expr_real(ps, operlist[i].prec);
+    if (!term2)
+    {
+        parse_generr(ps, "expr");
+        node_destroy(term2);
+    }
+    
+    term1 = node_create(operlist[i].nodetype, term1, term2);
+    term2 = NULL;
+    goto nextoper;
+}
+
+node_t *parse_expr(struct parser_state *ps)
+{
+    return parse_expr_real(ps, 0);
+}
+
 node_t *parse_statement(struct parser_state *ps)
 {
     node_t *rv;
--- a/lwcc/tree.c	Thu Aug 29 17:00:17 2019 -0600
+++ b/lwcc/tree.c	Tue Sep 24 22:07:56 2019 -0600
@@ -53,6 +53,10 @@
 	"BLOCK",
 	"STMT_RETURN",
 	"CONST_INT",
+	"OPER_PLUS",
+	"OPER_MINUS",
+	"OPER_TIMES",
+	"OPER_DIVIDE",
 };
 
 
@@ -70,6 +74,13 @@
 	
 	switch (type)
 	{
+	case NODE_OPER_PLUS:
+	case NODE_OPER_MINUS:
+	case NODE_OPER_TIMES:
+	case NODE_OPER_DIVIDE:
+		nargs = 2;
+		break;
+
 	case NODE_DECL:
 		nargs = 2;
 		break;
--- a/lwcc/tree.h	Thu Aug 29 17:00:17 2019 -0600
+++ b/lwcc/tree.h	Tue Sep 24 22:07:56 2019 -0600
@@ -51,7 +51,11 @@
 #define NODE_BLOCK			23	// statement block
 #define NODE_STMT_RETURN    24  // return statement
 #define NODE_CONST_INT      25  // constant integer
-#define NODE_NUMTYPES		26	// the number of node types
+#define NODE_OPER_PLUS      26  // addition
+#define NODE_OPER_MINUS     27  // subtraction
+#define NODE_OPER_TIMES     28  // multiplcation
+#define NODE_OPER_DIVIDE    29  // division
+#define NODE_NUMTYPES		30	// the number of node types
 
 typedef struct node_s node_t;