URI:
       expr.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       expr.c (4020B)
       ---
            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         unsigned long long 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 
          136         np = node(op, l, r);
          137         np->addr = addr;
          138 
          139         return np;
          140 }
          141 
          142 static Node *
          143 unaryop(int op, Node *np)
          144 {
          145         unsigned long long val;
          146 
          147         if (np->addr != ANUMBER)
          148                 error("invalid argument for unary operator");
          149         if (np->op != NUMBER) {
          150                 np = node(op, np, NULL);
          151                 np->addr = ANUMBER;
          152                 return np;
          153         }
          154 
          155         val = np->sym->value;
          156         switch (op) {
          157         case '!':
          158                 val = !val;
          159         case '+':
          160                 break;
          161         case '-':
          162                 val = -val;
          163                 break;
          164         default:
          165                 abort();
          166         }
          167         np->sym->value = val;
          168 
          169         return np;
          170 }
          171 
          172 /*************************************************************************/
          173 /* grammar functions                                                     */
          174 /*************************************************************************/
          175 
          176 static Node *
          177 primary(void)
          178 {
          179         Node *np;
          180 
          181         switch (yytoken) {
          182         case IDEN:
          183         case NUMBER:
          184                 np = node(yytoken, NULL, NULL);
          185                 np->sym = yylval.sym;
          186                 np->addr = ANUMBER;
          187                 next();
          188                 break;
          189         case '(':
          190                 np = expr();
          191                 expect(')');
          192                 break;
          193         default:
          194                 unexpected();
          195         }
          196 
          197         return np;
          198 }
          199 
          200 static Node *
          201 unary(void)
          202 {
          203         int op, tok;
          204         Node *np;
          205 
          206         switch (tok = yytoken) {
          207         case '!':
          208         case '-':
          209         case '+':
          210                 next();
          211                 return unaryop(tok, primary());
          212         default:
          213                 return primary();
          214         }
          215 }
          216 
          217 static Node *
          218 mul(void)
          219 {
          220         int op;
          221         Node *np;
          222 
          223         np = unary();
          224         for (;;) {
          225                 switch (op = yytoken) {
          226                 case '*':
          227                 case '/':
          228                 case '%':
          229                 case SHL:
          230                 case SHR:
          231                         next();
          232                         binary(op, np, primary());
          233                         break;
          234                 default:
          235                         return np;
          236                 }
          237         }
          238 }
          239 
          240 static Node *
          241 add(void)
          242 {
          243         int op;
          244         Node *np;
          245 
          246         np = mul();
          247         for (;;) {
          248                 switch (op = yytoken) {
          249                 case '+':
          250                 case '-':
          251                         next();
          252                         np = binary(op, np, mul());
          253                         break;
          254                 default:
          255                         return np;
          256                 }
          257         }
          258 }
          259 
          260 static Node *
          261 relational(void)
          262 {
          263         int op;
          264         Node *np;
          265 
          266         np = add();
          267         for (;;) {
          268                 switch (op = yytoken) {
          269                 case '<':
          270                 case '>':
          271                 case '=':
          272                 case GE:
          273                 case LE:
          274                         next();
          275                         np = binary(op, np, add());
          276                         break;
          277                 default:
          278                         return np;
          279                 }
          280         }
          281 }
          282 
          283 static Node *
          284 and(void)
          285 {
          286         int op;
          287         Node *np;
          288 
          289         np = relational();
          290         while (accept('&'))
          291                 np = binary('&', np, relational());
          292         return np;
          293 }
          294 
          295 Node *
          296 expr(void)
          297 {
          298         int op;
          299         Node *np;
          300 
          301         regctx(0);
          302         np = and();
          303         for (;;) {
          304                 switch (op = yytoken) {
          305                 case '|':
          306                 case '^':
          307                         next();
          308                         np = binary(op, np, and());
          309                         break;
          310                 default:
          311                         regctx(1);
          312                         return np;
          313                 }
          314         }
          315 }