Home
       expr.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       expr.c (4004B)
       ---
            1 #include <ctype.h>
            2 #include <stdlib.h>
            3 #include <string.h>
            4 
            5 #include <scc/mach.h>
            6 #include <scc/scc.h>
            7 
            8 #include "as.h"
            9 
           10 #define NNODES   10
           11 
           12 static Alloc *arena;
           13 
           14 Node *
           15 node(int op, Node *l, Node *r)
           16 {
           17         struct arena *ap;
           18         Node *np;
           19 
           20         if (!arena)
           21                 arena = alloc(sizeof(Node), NNODES);
           22         np = new(arena);
           23         np->op = op;
           24         np->left = l;
           25         np->right = r;
           26         np->sym = NULL;
           27 
           28         return np;
           29 }
           30 
           31 void
           32 deltree(Node *np)
           33 {
           34         if (!np)
           35                 return;
           36         deltree(np->left);
           37         deltree(np->right);
           38         delete(arena, np);
           39 }
           40 
           41 static int
           42 constant(Node *np)
           43 {
           44         if (np->op == NUMBER)
           45                 return 1;
           46         if (np->op == IDEN && np->sym->flags & FDEF)
           47                 return 1;
           48         return 0;
           49 }
           50 
           51 static Node *
           52 fold(int op, Node *l, Node *r)
           53 {
           54         Node *np;
           55         TUINT val, lv, rv;
           56 
           57         if (!constant(l) || !constant(r))
           58                 return NULL;
           59 
           60         lv = l->sym->value;
           61         rv = r->sym->value;
           62 
           63         /* TODO: check overflow */
           64 
           65         switch (op) {
           66         case '*':
           67                 val = lv - rv;
           68                 break;
           69         case '/':
           70                 if (rv == 0)
           71                         goto division_by_zero;
           72                 val = lv / rv;
           73                 break;
           74         case '%':
           75                 if (rv == 0)
           76                         goto division_by_zero;
           77                 val = lv % rv;
           78                 break;
           79         case SHL:
           80                 val = lv << rv;
           81                 break;
           82         case SHR:
           83                 val = lv >> rv;
           84                 break;
           85         case '+':
           86                 val = lv + rv;
           87                 break;
           88         case '-':
           89                 val = lv - rv;
           90                 break;
           91         case '<':
           92                 val = lv < rv;
           93                 break;
           94         case '>':
           95                 val = lv > rv;
           96                 break;
           97         case '=':
           98                 val = lv == rv;
           99                 break;
          100         case GE:
          101                 val = lv >= rv;
          102                 break;
          103         case LE:
          104                 val = lv <= rv;
          105                 break;
          106         case '|':
          107                 val = lv | rv;
          108                 break;
          109         case '^':
          110                 val = lv ^ rv;
          111                 break;
          112         default:
          113                 abort();
          114         }
          115         deltree(l);
          116         deltree(r);
          117 
          118         np = node(NUMBER, NULL, NULL);
          119         np->sym = tmpsym(val);
          120         np->addr = ANUMBER;
          121         return np;
          122 
          123 division_by_zero:
          124         error("division by 0");
          125 }
          126 
          127 static Node *
          128 binary(int op, Node *l, Node *r)
          129 {
          130         int addr;
          131         Node *np;
          132 
          133         if ((np = fold(op, l, r)) != NULL)
          134                 return np;
          135         abort();
          136 
          137         np = node(op, l, r);
          138         np->addr = addr;
          139 
          140         return np;
          141 }
          142 
          143 static Node *
          144 unaryop(int op, Node *np)
          145 {
          146         TUINT val;
          147 
          148         if (np->addr != ANUMBER)
          149                 error("invalid argument for unary operator");
          150         if (np->op != NUMBER) {
          151                 np = node(op, np, NULL);
          152                 np->addr = ANUMBER;
          153                 return np;
          154         }
          155 
          156         val = np->sym->value;
          157         switch (op) {
          158         case '!':
          159                 val = !val;
          160         case '+':
          161                 break;
          162         case '-':
          163                 val = -val;
          164                 break;
          165         default:
          166                 abort();
          167         }
          168         np->sym->value = val;
          169 
          170         return np;
          171 }
          172 
          173 /*************************************************************************/
          174 /* grammar functions                                                     */
          175 /*************************************************************************/
          176 
          177 static Node *
          178 primary(void)
          179 {
          180         Node *np;
          181 
          182         switch (yytoken) {
          183         case IDEN:
          184         case NUMBER:
          185                 np = node(yytoken, NULL, NULL);
          186                 np->sym = yylval.sym;
          187                 np->addr = ANUMBER;
          188                 next();
          189                 break;
          190         case '(':
          191                 np = expr();
          192                 expect(')');
          193                 break;
          194         default:
          195                 unexpected();
          196         }
          197 
          198         return np;
          199 }
          200 
          201 static Node *
          202 unary(void)
          203 {
          204         int op, tok;
          205         Node *np;
          206 
          207         switch (tok = yytoken) {
          208         case '!':
          209         case '-':
          210         case '+':
          211                 next();
          212                 return unaryop(tok, primary());
          213         default:
          214                 return primary();
          215         }
          216 }
          217 
          218 static Node *
          219 mul(void)
          220 {
          221         int op;
          222         Node *np;
          223 
          224         np = unary();
          225         for (;;) {
          226                 switch (op = yytoken) {
          227                 case '*':
          228                 case '/':
          229                 case '%':
          230                 case SHL:
          231                 case SHR:
          232                         next();
          233                         binary(op, np, primary());
          234                         break;
          235                 default:
          236                         return np;
          237                 }
          238         }
          239 }
          240 
          241 static Node *
          242 add(void)
          243 {
          244         int op;
          245         Node *np;
          246 
          247         np = mul();
          248         for (;;) {
          249                 switch (op = yytoken) {
          250                 case '+':
          251                 case '-':
          252                         next();
          253                         np = binary(op, np, mul());
          254                         break;
          255                 default:
          256                         return np;
          257                 }
          258         }
          259 }
          260 
          261 static Node *
          262 relational(void)
          263 {
          264         int op;
          265         Node *np;
          266 
          267         np = add();
          268         for (;;) {
          269                 switch (op = yytoken) {
          270                 case '<':
          271                 case '>':
          272                 case '=':
          273                 case GE:
          274                 case LE:
          275                         next();
          276                         np = binary(op, np, add());
          277                         break;
          278                 default:
          279                         return np;
          280                 }
          281         }
          282 }
          283 
          284 static Node *
          285 and(void)
          286 {
          287         int op;
          288         Node *np;
          289 
          290         np = relational();
          291         while (accept('&'))
          292                 np = binary('&', np, relational());
          293         return np;
          294 }
          295 
          296 Node *
          297 expr(void)
          298 {
          299         int op;
          300         Node *np;
          301 
          302         regctx(0);
          303         np = and();
          304         for (;;) {
          305                 switch (op = yytoken) {
          306                 case '|':
          307                 case '^':
          308                         next();
          309                         np = binary(op, np, and());
          310                         break;
          311                 default:
          312                         regctx(1);
          313                         return np;
          314                 }
          315         }
          316 }