1 #include "exprast.h"
2 #include <ctype.h>
3 
4 #define arglist_sizeof(l) (sizeof(RSArgList) + ((l) * sizeof(RSExpr *)))
5 
RS_NewArgList(RSExpr * e)6 RSArgList *RS_NewArgList(RSExpr *e) {
7   RSArgList *ret = rm_malloc(arglist_sizeof(e ? 1 : 0));
8   ret->len = e ? 1 : 0;
9   if (e) ret->args[0] = e;
10   return ret;
11 }
12 
RSArgList_Append(RSArgList * l,RSExpr * e)13 RSArgList *RSArgList_Append(RSArgList *l, RSExpr *e) {
14   l = rm_realloc(l, arglist_sizeof(l->len + 1));
15   l->args[l->len++] = e;
16   return l;
17 }
18 
newExpr(RSExprType t)19 static RSExpr *newExpr(RSExprType t) {
20   RSExpr *e = rm_calloc(1, sizeof(*e));
21   e->t = t;
22   return e;
23 }
24 
25 // unquote and unescape a stirng literal, and return a cleaned copy of it
unescpeStringDup(const char * s,size_t sz)26 char *unescpeStringDup(const char *s, size_t sz) {
27 
28   char *dst = rm_malloc(sz);
29   char *dstStart = dst;
30   char *src = (char *)s + 1;       // we start after the first quote
31   char *end = (char *)s + sz - 1;  // we end at the last quote
32   while (src < end) {
33     // unescape
34     if (*src == '\\' && src + 1 < end && (ispunct(*(src + 1)) || isspace(*(src + 1)))) {
35       ++src;
36       continue;
37     }
38     *dst++ = *src++;
39   }
40   *dst = '\0';
41   return dstStart;
42 }
RS_NewStringLiteral(const char * str,size_t len)43 RSExpr *RS_NewStringLiteral(const char *str, size_t len) {
44   RSExpr *e = newExpr(RSExpr_Literal);
45   e->literal = RS_StaticValue(RSValue_String);
46   e->literal.strval.str = unescpeStringDup(str, len);
47   e->literal.strval.len = strlen(e->literal.strval.str);
48   e->literal.strval.stype = RSString_Malloc;
49   return e;
50 }
51 
RS_NewNullLiteral()52 RSExpr *RS_NewNullLiteral() {
53   RSExpr *e = newExpr(RSExpr_Literal);
54   RSValue_MakeReference(&e->literal, RS_NullVal());
55   return e;
56 }
57 
RS_NewNumberLiteral(double n)58 RSExpr *RS_NewNumberLiteral(double n) {
59   RSExpr *e = newExpr(RSExpr_Literal);
60 
61   e->literal = RS_StaticValue(RSValue_Number);
62   e->literal.numval = n;
63   return e;
64 }
65 
RS_NewOp(unsigned char op,RSExpr * left,RSExpr * right)66 RSExpr *RS_NewOp(unsigned char op, RSExpr *left, RSExpr *right) {
67   RSExpr *e = newExpr(RSExpr_Op);
68   e->op.op = op;
69   e->op.left = left;
70   e->op.right = right;
71   return e;
72 }
73 
RS_NewPredicate(RSCondition cond,RSExpr * left,RSExpr * right)74 RSExpr *RS_NewPredicate(RSCondition cond, RSExpr *left, RSExpr *right) {
75   RSExpr *e = newExpr(RSExpr_Predicate);
76   e->pred.cond = cond;
77   e->pred.left = left;
78   e->pred.right = right;
79   // e->pred = (RSPredicate){
80   //     .cond = cond,
81   //     .left = left,
82   //     .right = right,
83   // };
84   return e;
85 }
86 
RS_NewFunc(const char * str,size_t len,RSArgList * args,RSFunction cb)87 RSExpr *RS_NewFunc(const char *str, size_t len, RSArgList *args, RSFunction cb) {
88   RSExpr *e = newExpr(RSExpr_Function);
89   e->func.args = args;
90   e->func.name = rm_strndup(str, len);
91   e->func.Call = cb;
92   return e;
93 }
94 
RS_NewProp(const char * str,size_t len)95 RSExpr *RS_NewProp(const char *str, size_t len) {
96   RSExpr *e = newExpr(RSExpr_Property);
97   e->property.key = rm_strndup(str, len);
98   e->property.lookupObj = NULL;
99   return e;
100 }
101 
RS_NewInverted(RSExpr * child)102 RSExpr *RS_NewInverted(RSExpr *child) {
103   RSExpr *e = newExpr(RSExpr_Inverted);
104   e->inverted.child = child;
105   return e;
106 }
107 
RSArgList_Free(RSArgList * l)108 void RSArgList_Free(RSArgList *l) {
109   if (!l) return;
110   for (size_t i = 0; i < l->len; i++) {
111     RSExpr_Free(l->args[i]);
112   }
113   rm_free(l);
114 }
RSExpr_Free(RSExpr * e)115 void RSExpr_Free(RSExpr *e) {
116   if (!e) return;
117   switch (e->t) {
118     case RSExpr_Literal:
119       RSValue_Clear(&e->literal);
120       break;
121     case RSExpr_Function:
122       rm_free((char *)e->func.name);
123       RSArgList_Free(e->func.args);
124       break;
125     case RSExpr_Op:
126       RSExpr_Free(e->op.left);
127       RSExpr_Free(e->op.right);
128       break;
129     case RSExpr_Predicate:
130       RSExpr_Free(e->pred.left);
131       RSExpr_Free(e->pred.right);
132       break;
133     case RSExpr_Property:
134       rm_free((char *)e->property.key);
135       break;
136     case RSExpr_Inverted:
137       RSExpr_Free(e->inverted.child);
138   }
139   rm_free(e);
140 }
141 
RSExpr_Print(const RSExpr * e)142 void RSExpr_Print(const RSExpr *e) {
143   if (!e) {
144     printf("NULL");
145     return;
146   }
147   switch (e->t) {
148     case RSExpr_Literal:
149       RSValue_Print(&e->literal);
150       break;
151     case RSExpr_Function:
152       printf("%s(", e->func.name);
153       for (size_t i = 0; e->func.args != NULL && i < e->func.args->len; i++) {
154         RSExpr_Print(e->func.args->args[i]);
155         if (i < e->func.args->len - 1) printf(", ");
156       }
157       printf(")");
158       break;
159     case RSExpr_Op:
160       printf("(");
161       RSExpr_Print(e->op.left);
162       printf(" %c ", e->op.op);
163       RSExpr_Print(e->op.right);
164       printf(")");
165       break;
166 
167     case RSExpr_Predicate:
168       printf("(");
169       RSExpr_Print(e->pred.left);
170       printf(" %s ", getRSConditionStrings(e->pred.cond));
171       RSExpr_Print(e->pred.right);
172       printf(")");
173 
174       break;
175     case RSExpr_Property:
176       printf("@%s", e->property.key);
177       break;
178     case RSExpr_Inverted:
179       printf("!");
180       RSExpr_Print(e->inverted.child);
181       break;
182   }
183 }
184 
ExprAST_Free(RSExpr * e)185 void ExprAST_Free(RSExpr *e) {
186   RSExpr_Free(e);
187 }
188 
ExprAST_Print(const RSExpr * e)189 void ExprAST_Print(const RSExpr *e) {
190   RSExpr_Print(e);
191 }
192 
ExprAST_Parse(const char * e,size_t n,QueryError * status)193 RSExpr *ExprAST_Parse(const char *e, size_t n, QueryError *status) {
194   char *errtmp = NULL;
195   RS_LOG_ASSERT(!QueryError_HasError(status), "Query has error")
196 
197   RSExpr *ret = RSExpr_Parse(e, n, &errtmp);
198   if (!ret) {
199     QueryError_SetError(status, QUERY_EEXPR, errtmp);
200   }
201   rm_free(errtmp);
202   return ret;
203 }
204