00001
00002
00003
00004 #include <stdlib.h>
00005 #include "utils.h"
00006 #include "parser.h"
00007 #include "rules.h"
00008 #include "functions.h"
00009 #include "configuration.h"
00010 #include "filesystem.h"
00011
00012 Op new_ops[num_ops] = {
00013 {"-",1,10},
00014 {"++",2,6},
00015 {"+",2,6},
00016 {"-",2,6},
00017 {"*",2,7},
00018 {"/",2,7},
00019 {"&&",2,3},
00020 {"%%",2,2},
00021 {"||",2,2},
00022 {"%",2,7},
00023 {"<=",2,5},
00024 {">=",2,5},
00025 {"<",2,5},
00026 {">",2,5},
00027 {"==",2,4},
00028 {"!=",2,4},
00029 {"!",1,10},
00030 {"like regex",2,4},
00031 {"not like regex",2,4},
00032 {"like",2,4},
00033 {"not like",2,4},
00034 {"^^",2,8},
00035 {"^",2,8},
00036 {"floor",1,10},
00037 {"ceiling",1,10},
00038 {"log",1,10},
00039 {"exp",1,10},
00040 {"abs",1,10},
00041 {"=",2,1},
00042 {"@@",2,20}
00043 };
00044 PARSER_FUNC_PROTO2(Term, int rulegen, int prec);
00045 PARSER_FUNC_PROTO2(Actions, int rulegen, int backwardCompatible);
00046 PARSER_FUNC_PROTO1(T, int rulegen);
00047 PARSER_FUNC_PROTO1(Value, int rulegen);
00048 PARSER_FUNC_PROTO1(StringExpression, Token *tk);
00049 PARSER_FUNC_PROTO(RuleName);
00050 PARSER_FUNC_PROTO(TermBackwardCompatible);
00051 PARSER_FUNC_PROTO1(ExprBackwardCompatible, int level);
00052 PARSER_FUNC_PROTO1(TermSystemBackwardCompatible, int lev);
00053 PARSER_FUNC_PROTO(ActionArgumentBackwardCompatible);
00054 PARSER_FUNC_PROTO(FuncExpr);
00055 PARSER_FUNC_PROTO(Type);
00056 PARSER_FUNC_PROTO2(_Type, int prec, int lifted);
00057 PARSER_FUNC_PROTO(TypeSet);
00058 PARSER_FUNC_PROTO(Column);
00059 PARSER_FUNC_PROTO(QueryCond);
00060 PARSER_FUNC_PROTO(FuncType);
00061 PARSER_FUNC_PROTO(_FuncType);
00062 PARSER_FUNC_PROTO(TypingConstraints);
00063 PARSER_FUNC_PROTO(_TypingConstraints);
00064 PARSER_FUNC_PROTO(Metadata);
00065
00066
00067 ParserContext *newParserContext(rError_t *errmsg, Region *r) {
00068 ParserContext *pc = (ParserContext *)malloc(sizeof(ParserContext));
00069 pc->stackTopStackTop = 0;
00070 pc->nodeStackTop = 0;
00071 pc->error = 0;
00072 pc->errloc.exprloc = -1;
00073 pc->region = r;
00074 pc->errmsg = errmsg;
00075 pc->errnode = NULL;
00076 pc->symtable = newHashTable2(100, r);
00077 pc->errmsgbuf[0] = '\0';
00078 pc->tqp = pc->tqtop = pc->tqbot = 0;
00079 return pc;
00080 }
00081
00082 void deleteParserContext(ParserContext *t) {
00083 free(t);
00084 }
00085 int isLocalVariableNode(Node *node) {
00086 return
00087 getNodeType(node)==TK_VAR &&
00088 node->text[0] == '*';
00089 }
00090 int isSessionVariableNode(Node *node) {
00091 return
00092 getNodeType(node)==TK_VAR &&
00093 node->text[0] == '$';
00094 }
00095 int isVariableNode(Node *node) {
00096 return
00097 isLocalVariableNode(node) ||
00098 isSessionVariableNode(node);
00099 }
00100 #define nKeywords 19
00101 char *keywords[nKeywords] = { "in", "let", "match", "with", "for", "forExec", "while", "whileExec", "foreach", "forEachExec", "if", "ifExec", "then", "else", "data", "constructor", "on", "or", "oron"};
00102 int isKeyword(char *text) {
00103 int i;
00104 for(i=0;i<nKeywords;i++) {
00105 if(strcmp(keywords[i], text) == 0) {
00106 return 1;
00107 }
00108 }
00109 return 0;
00110 }
00111
00112 void skipWhitespace(Pointer *expr) {
00113 int ch;
00114 ch = lookAhead(expr, 0);
00115 while (ch!=-1 && (ch==' ' || ch=='\t' || ch=='\r' || ch=='\n')) {
00116 ch = nextChar(expr);
00117 }
00118 }
00119 void skipComments(Pointer *e) {
00120 int ch = lookAhead(e, 0);
00121 while(ch!='\n' && ch!=-1) {
00122 ch = nextChar(e);
00123 }
00124 }
00125 char *findLineCont(char *expr) {
00126 char *e = expr + strlen(expr);
00127 while (e!=expr) {
00128 e--;
00129 if(*e==' ' || *e=='\t' || *e=='\r' || *e=='\n') continue;
00130 if(*e=='\\' || *e==',' || *e==';' || *e=='|' || *e=='#') return e;
00131 break;
00132 }
00133 return NULL;
00134 }
00135
00136
00137
00138
00139
00140 int skip(Pointer *e, char *text, Token **token, ParserContext *pc, int rulegen) {
00141 *token = nextTokenRuleGen(e, pc, rulegen);
00142 if(((*token)->type!=TK_TEXT && (*token)->type!=TK_OP && (*token)->type!=TK_MISC_OP) || strcmp((*token)->text,text)!=0) {
00143 (*token)->type = N_ERROR;
00144 return 0;
00145 }
00146 return 1;
00147 }
00148
00149
00150
00151
00152
00153 Token* nextTokenRuleGen(Pointer* e, ParserContext *context, int rulegen) {
00154 if(context->tqp != context->tqtop) {
00155 Token *token = &(context->tokenQueue[context->tqp]);
00156 INC_MOD(context->tqp, 1024);
00157 return token;
00158 }
00159
00160 Token* token = &(context->tokenQueue[context->tqp]);
00161 INC_MOD(context->tqtop, 1024);
00162 if(context->tqbot == context->tqtop)
00163 INC_MOD(context->tqbot, 1024);
00164 context->tqp = context->tqtop;
00165
00166 while (1) {
00167 skipWhitespace(e);
00168 Label start;
00169 Label pos;
00170 getFPos(&start, e, context);
00171 token->exprloc = start.exprloc;
00172 int ch = lookAhead(e, 0);
00173 if (ch == -1) {
00174 token->type = TK_EOS;
00175 strcpy(token->text, "EOS");
00176 break;
00177 } else {
00178 int i;
00179 if (ch == '{' || ch == '}' || ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == ',' || ch == '@' || (ch == '|' && (!rulegen || lookAhead(e, 1) != '|')) || ch == ';' || ch == '?') {
00180 *(token->text) = ch;
00181 (token->text)[1] = '\0';
00182 token->type = TK_MISC_OP;
00183 nextChar(e);
00184 break;
00185 } else if (ch == '#') {
00186 if (!rulegen && lookAhead(e, 1) == '#') {
00187 token->text[0] = ch;
00188 token->text[1] = lookAhead(e, 1);
00189 token->text[2] = '\0';
00190 token->type = TK_MISC_OP;
00191 nextChar(e);
00192 nextChar(e);
00193 break;
00194 } else {
00195 skipComments(e);
00196 continue;
00197 }
00198 } else if(ch == '-' || ch == '=') {
00199 if(lookAhead(e,1)=='>') {
00200 token->text[0] = ch;
00201 token->text[1] = '>';
00202 token->text[2] = '\0';
00203 token->type = TK_MISC_OP;
00204 nextChar(e);
00205 nextChar(e);
00206 break;
00207 }
00208 } else if (ch == ':') {
00209 if (rulegen && lookAhead(e, 1) == ':'
00210 && lookAhead(e, 2) == ':') {
00211 token->text[0] = ch;
00212 token->text[1] = lookAhead(e, 1);
00213 token->text[2] = lookAhead(e, 2);
00214 token->text[3] = '\0';
00215 token->type = TK_MISC_OP;
00216 nextChar(e);
00217 nextChar(e);
00218 } else {
00219 *(token->text) = ch;
00220 (token->text)[1] = '\0';
00221 token->type = TK_MISC_OP;
00222 }
00223 nextChar(e);
00224 break;
00225 } else if (ch == '*' || ch == '$') {
00226 token->type = ch == '*' ? TK_LOCAL_VAR : TK_SESSION_VAR;
00227
00228 ch = nextChar(e);
00229 if (ch == '_' || isalpha(ch)) {
00230 ch = nextChar(e);
00231 while (ch == '_' || isalnum(ch)) {
00232 ch = nextChar(e);
00233 }
00234 FPOS;
00235 dupString(e, &start, (int) (pos.exprloc - start.exprloc), token->text);
00236 break;
00237 } else {
00238 seekInFile(e, start.exprloc);
00239 }
00240 }
00241 char op[100];
00242 dupString(e, &start, 10, op);
00243 int found = 0;
00244 for (i = 0; i < num_ops; i++) {
00245 int len = strlen(new_ops[i].string);
00246 if (strncmp(op, new_ops[i].string, len) == 0 &&
00247 (!isalpha(new_ops[i].string[0])
00248 || !isalnum(op[len]))) {
00249 strcpy(token->text, new_ops[i].string);
00250 token->type = TK_OP;
00251 nextChars(e, len);
00252 found = 1;
00253 break;
00254 }
00255 }
00256 if (found)
00257 break;
00258 if (isdigit(ch) || ch == '.') {
00259 ch = nextChar(e);
00260 while (isdigit(ch) || ch == '.') {
00261 ch = nextChar(e);
00262 }
00263 FPOS;
00264 dupString(e, &start, (int) (pos.exprloc - start.exprloc), token->text);
00265 if (strchr(token->text, '.')) {
00266 token->type = TK_DOUBLE;
00267 } else {
00268 token->type = TK_INT;
00269 }
00270 } else if (ch == '_' || isalpha(ch) || ch == '~') {
00271 ch = nextChar(e);
00272 while (ch == '_' || isalnum(ch)) {
00273 ch = nextChar(e);
00274 }
00275 FPOS;
00276 dupString(e, &start, (int) (pos.exprloc - start.exprloc), token->text);
00277 token->type = TK_TEXT;
00278 } else if (ch == '\"') {
00279 nextString(e, token->text, token->vars);
00280 token->type = TK_STRING;
00281 } else if (ch == '\'') {
00282 nextString2(e, token->text, token->vars);
00283 token->type = TK_STRING;
00284 } else if (ch == '`') {
00285 if(lookAhead(e, 1) == '`') {
00286 if(nextStringBase2(e, token->text, "``")==-1) {
00287 token->type = N_ERROR;
00288 } else {
00289 token->type = TK_STRING;
00290 token->vars[0] = -1;
00291 }
00292 } else {
00293 nextStringBase(e, token->text, "`", 1, '\\', token->vars);
00294 token->type = TK_BACKQUOTED;
00295 }
00296 } else {
00297 token->type = N_ERROR;
00298 }
00299 break;
00300 }
00301 }
00302 return token;
00303 }
00304
00305 void pushback(Pointer *e, Token *token, ParserContext *context) {
00306 if(token->type == TK_EOS) {
00307 return;
00308 }
00309 DEC_MOD(context->tqp, 1024);
00310 }
00311
00312 void syncTokenQueue(Pointer *e, ParserContext *context) {
00313 if(context->tqp == context->tqtop) {
00314 return;
00315 }
00316 Token *nextToken = &context->tokenQueue[context->tqp];
00317 seekInFile(e, nextToken->exprloc);
00318 context->tqtop = context->tqp;
00319 }
00320
00321 int eol(char ch) {
00322 return ch=='\n' || ch=='\r';
00323 }
00324
00325
00326
00327
00328
00329
00330 PARSER_FUNC_BEGIN1(Rule, int backwardCompatible)
00331 char *rk;
00332 int rulegen = 0;
00333 TRY(defType)
00334 TTEXT("data");
00335 NT(RuleName);
00336 BUILD_NODE(N_DATA_DEF, "DATA", &start, 1, 1);
00337 int n = 0;
00338 OPTIONAL_BEGIN(consDefs)
00339 TTEXT("=");
00340 OPTIONAL_BEGIN(semicolon)
00341 TTEXT("|");
00342 OPTIONAL_END(semicolon)
00343 LOOP_BEGIN(cons)
00344 Label cpos = *FPOS;
00345 TTYPE(TK_TEXT);
00346 BUILD_NODE(TK_TEXT, token->text, &pos, 0, 0);
00347 TTEXT(":");
00348 NT(FuncType);
00349 BUILD_NODE(N_CONSTRUCTOR_DEF, "CONSTR", &cpos, 2, 2);
00350 n++;
00351 TRY(delim)
00352 TTEXT("|");
00353 OR(delim)
00354 DONE(cons);
00355 END_TRY(delim)
00356 LOOP_END(cons)
00357 OPTIONAL_END(consDefs)
00358 OPTIONAL_BEGIN(semicolon)
00359 TTEXT(";");
00360 OPTIONAL_END(semicolon)
00361 n = n+1;
00362 BUILD_NODE(N_RULE_PACK, "INDUCT", &start, n, n);
00363 OR(defType)
00364 TTEXT("constructor");
00365 TTYPE(TK_TEXT);
00366 BUILD_NODE(TK_TEXT, token->text, &pos, 0, 0);
00367 TTEXT(":")
00368 NT(FuncType);
00369 BUILD_NODE(N_CONSTRUCTOR_DEF, "CONSTR", &start, 2, 2);
00370 BUILD_NODE(N_RULE_PACK, "CONSTR", &start, 1, 1);
00371 OR(defType)
00372 TTYPE(TK_TEXT);
00373 BUILD_NODE(TK_TEXT, token->text, &pos, 0, 0);
00374 TTEXT(":");
00375 NT(FuncType);
00376 BUILD_NODE(N_EXTERN_DEF, "EXTERN", &start, 2, 2);
00377 BUILD_NODE(N_RULE_PACK, "EXTERN", &start, 1, 1);
00378 OR(defType)
00379 NT(RuleName);
00380 TRY(ruleType)
00381 TTEXT("{");
00382 rulegen = 1;
00383 rk = "REL";
00384 OR(ruleType)
00385 TTEXT("|");
00386 rulegen = 0;
00387 rk = "REL";
00388 OR(ruleType)
00389 TTEXT("=");
00390 rulegen = 1;
00391 rk = "FUNC";
00392 END_TRY(ruleType);
00393 if(strcmp(rk, "FUNC")==0) {
00394 BUILD_NODE(TK_BOOL, "true", FPOS, 0, 0);
00395 NT(FuncExpr);
00396 NT(Metadata);
00397 OPTIONAL_BEGIN(semicolon)
00398 TTEXT(";");
00399 OPTIONAL_END(semicolon)
00400 BUILD_NODE(N_RULE,"RULE", &start,5, 5);
00401 BUILD_NODE(N_RULE_PACK,rk, &start,1, 1);
00402 /* } else if(PARSER_LAZY) {
00403 char buf[MAX_RULE_LEN];
00404 Label rcpos = *FPOS;
00405 getRuleCode(buf, e, rulegen, context);
00406 BUILD_NODE(N_RULE_CODE, buf, &rcpos, 0, 0);
00407 BUILD_NODE(N_UNPARSED,"UNPARSED", &start,2, 2);
00408 BUILD_NODE(N_RULE_PACK,rk, &start,1, 1); */
00409 } else if(rulegen) {
00410 int numberOfRules = 0;
00411 LOOP_BEGIN(rule)
00412 TRY(rulePack)
00413 TRY(rulePackCond)
00414 TTEXT("ON");
00415 OR(rulePackCond)
00416 TTEXT("on");
00417 OR(rulePackCond)
00418 TTEXT("ORON");
00419 OR(rulePackCond)
00420 TTEXT("oron");
00421 END_TRY(rulePackCond)
00422 NT2(Term, 1, MIN_PREC);
00423 TTEXT("{");
00424 NT2(Actions, 1, 0);
00425 TTEXT("}");
00426 NT(Metadata);
00427 BUILD_NODE(N_RULE, "RULE", &start, 5, 4);
00428 SWAP;
00429 numberOfRules++;
00430 OR(rulePack)
00431 TRY(rulePackUncond)
00432 TTEXT("OR");
00433 OR(rulePackUncond)
00434 TTEXT("or");
00435 END_TRY(rulePackUncond)
00436 BUILD_NODE(TK_BOOL, "true", FPOS, 0, 0);
00437 TTEXT("{");
00438 NT2(Actions, 1, 0);
00439 TTEXT("}");
00440 NT(Metadata);
00441 BUILD_NODE(N_RULE, "RULE", &start, 5, 4);
00442 SWAP;
00443 numberOfRules++;
00444 OR(rulePack)
00445 ABORT(numberOfRules == 0);
00446 TTEXT("}");
00447 DONE(rule);
00448 OR(rulePack)
00449 ABORT(numberOfRules != 0);
00450 BUILD_NODE(TK_BOOL, "true", FPOS, 0, 0);
00451 NT2(Actions, 1, 0);
00452 TTEXT("}");
00453 NT(Metadata);
00454 numberOfRules = 1;
00455 BUILD_NODE(N_RULE, "RULE", &start, 5, 4);
00456 SWAP;
00457 DONE(rule);
00458 END_TRY(rulePack)
00459 LOOP_END(rule)
00460 (void) POP;
00461 BUILD_NODE(N_RULE_PACK, rk, &start, numberOfRules, numberOfRules);
00462 } else {
00463 Label pos = *FPOS;
00464 TRY(ruleCond)
00465 /* empty condition */
00466 TTEXT("|");
00467 BUILD_NODE(TK_BOOL, "true", FPOS, 0, 0);
00468 OR(ruleCond)
00469 if(backwardCompatible >= 0) {
00470 NT1(ExprBackwardCompatible, 0);
00471 } else {
00472 NT2(Term, 0, MIN_PREC);
00473 }
00474 TTEXT("|");
00475 BUILD_NODE(N_TUPLE, TUPLE, &pos, 1, 1);
00476 END_TRY(ruleCond)
00477
00478
00479 NT2(Actions, 0, backwardCompatible >= 0? 1: 0);
00480 TTEXT("|");
00481 NT2(Actions, 0, backwardCompatible>= 0? 1: 0);
00482 int n = 0;
00483 Label metadataStart = *FPOS;
00484 OPTIONAL_BEGIN(ruleId)
00485 TTEXT("|");
00486 TTYPE(TK_INT);
00487 BUILD_NODE(TK_STRING,"id", &pos, 0, 0);
00488 BUILD_NODE(TK_STRING,token->text, &pos, 0, 0);
00489 BUILD_NODE(TK_STRING,"", &pos, 0, 0);
00490 BUILD_NODE(N_AVU,AVU, &pos, 3, 3);
00491 n++;
00492 OPTIONAL_END(ruleId)
00493 BUILD_NODE(N_META_DATA, META_DATA, &metadataStart, n, n);
00494 BUILD_NODE(N_RULE,"RULE", &start, 5, 5);
00495 BUILD_NODE(N_RULE_PACK, rk, &start, 1, 1);
00496 }
00497 /*OR(defType)
00498 TTYPE(TK_LOCAL_VAR);
00499 BUILD_NODE(TK_VAR, token->text, &pos, 0, 0);
00500 TTEXT("=");
00501 NT2(Term, 0, MIN_PREC);
00502 BUILD_NODE(N_RULE_PACK, "GLOBAL", &start, 2, 2);*/
00503 END_TRY(defType)
00504 PARSER_FUNC_END(Rule)
00505
00506 PARSER_FUNC_BEGIN(RuleName)
00507 int rulegen = 0;
00508 TTYPE(TK_TEXT);
00509 char *ruleName = cpStringExt(token->text, context->region);
00510 Label paramListStart = *FPOS;
00511 TRY(params)
00512 TTEXT("(");
00513 int n = 0;
00514 LOOP_BEGIN(params)
00515 NT2(Term, rulegen, MIN_PREC);
00516 n++;
00517 CHOICE_BEGIN(paramType)
00518 BRANCH_BEGIN(paramType)
00519 TTEXT(":");
00520 NT(Type);
00521 BRANCH_END(paramType)
00522 BRANCH_BEGIN(paramType)
00523 BUILD_NODE(T_UNSPECED, NULL, FPOS, 0, 0);
00524 BRANCH_END(paramType)
00525 CHOICE_END(paramType)
00526 CHOICE_BEGIN(paramDelim)
00527 BRANCH_BEGIN(paramDelim)
00528 TTEXT(",");
00529 BRANCH_END(paramDelim)
00530 BRANCH_BEGIN(paramDelim)
00531 TTEXT(")");
00532 DONE(params);
00533 BRANCH_END(paramDelim)
00534 CHOICE_END(paramDelim)
00535 LOOP_END(params);
00536 UNZIP(n);
00537 BUILD_NODE(N_PARAM_TYPE_LIST, "paramTypelist", ¶mListStart, n, n);
00538 Node *node = POP;
00539 BUILD_NODE(N_PARAM_LIST, "paramlist", ¶mListStart, n, n);
00540 PUSH(node);
00541 OR(params)
00542 OPTIONAL_BEGIN(epl)
00543 TTEXT("(");
00544 TTEXT(")");
00545 OPTIONAL_END(epl)
00546 BUILD_NODE(N_PARAM_LIST, "paramlist", ¶mListStart, 0, 0);
00547 BUILD_NODE(N_PARAM_TYPE_LIST, "paramTypelist", ¶mListStart, 0, 0);
00548 END_TRY(params)
00549
00550 TRY(retType)
00551 TTEXT(":");
00552 NT(FuncType);
00553 OR(retType)
00554 BUILD_NODE(T_UNSPECED, NULL, FPOS, 0, 0);
00555 END_TRY(retType)
00556 BUILD_NODE(N_RULE_NAME, ruleName, &start, 3, 3);
00557 PARSER_FUNC_END(RuleName)
00558
00559 PARSER_FUNC_BEGIN(Metadata)
00560 int rulegen = 1;
00561 int n = 0;
00562 LOOP_BEGIN(metadata)
00563 TRY(avu)
00564 TTEXT("@");
00565 TTEXT("(");
00566 TTYPE(TK_STRING);
00567 BUILD_NODE(TK_STRING, token->text, &pos, 0, 0);
00568 TTEXT(",");
00569 TTYPE(TK_STRING);
00570 BUILD_NODE(TK_STRING, token->text, &pos, 0, 0);
00571 TRY(u)
00572 TTEXT(",");
00573 TTYPE(TK_STRING);
00574 BUILD_NODE(TK_STRING, token->text, &pos, 0, 0);
00575 TTEXT(")");
00576 OR(u)
00577 TTEXT(")");
00578 BUILD_NODE(TK_STRING, "", &pos, 0, 0);
00579 END_TRY(u)
00580 BUILD_NODE(N_AVU, AVU, &pos, 3, 3);
00581 n++;
00582 OR(avu)
00583 DONE(metadata);
00584 END_TRY(avu)
00585 LOOP_END(metadata)
00586 BUILD_NODE(N_META_DATA, META_DATA, &start, n, n);
00587 PARSER_FUNC_END(Metadata)
00588
00589
00590 PARSER_FUNC_BEGIN(FuncExpr)
00591 int rulegen = 1;
00592 NT2(Term, 1, MIN_PREC);
00593 CHOICE_BEGIN(reco)
00594 BRANCH_BEGIN(reco)
00595 TTEXT(":::");
00596 NT2(Term, 1, MIN_PREC);
00597 BRANCH_END(reco)
00598 BRANCH_BEGIN(reco)
00599 BUILD_APP_NODE("nop", FPOS, 0);
00600 BRANCH_END(reco)
00601 CHOICE_END(reco)
00602 PARSER_FUNC_END(FuncExpr)
00603
00604 PARSER_FUNC_BEGIN2(Actions, int rulegen, int backwardCompatible)
00605 int n = 0;
00606 TRY(actions)
00607 ABORT(backwardCompatible);
00608 TTEXT_LOOKAHEAD("}");
00609 OR(actions)
00610 LOOP_BEGIN(actions);
00611 if(!backwardCompatible) {
00612 NT2(Term, rulegen, MIN_PREC);
00613 } else {
00614 NT(TermBackwardCompatible);
00615 }
00616 if(rulegen) {
00617 CHOICE_BEGIN(reco)
00618 BRANCH_BEGIN(reco)
00619 TTEXT(":::");
00620 NT2(Term, rulegen, MIN_PREC);
00621 BRANCH_END(reco)
00622 BRANCH_BEGIN(reco)
00623 BUILD_APP_NODE("nop", NULL, 0);
00624 BRANCH_END(reco)
00625 CHOICE_END(reco)
00626 }
00627 n++;
00628 if(rulegen) {
00629 OPTIONAL_BEGIN(actionSemiColon)
00630 TTEXT(";");
00631 OPTIONAL_END(actionSemiColon)
00632 OPTIONAL_BEGIN(actionSemiColonBrace)
00633 TTEXT_LOOKAHEAD("}");
00634 DONE(actions);
00635 OPTIONAL_END(actionSemiColonBrace)
00636 } else {
00637 CHOICE_BEGIN(actionDelim)
00638 BRANCH_BEGIN(actionDelim)
00639 TTEXT("##");
00640 BRANCH_END(actionDelim)
00641 BRANCH_BEGIN(actionDelim)
00642 DONE(actions);
00643 BRANCH_END(actionDelim)
00644 CHOICE_END(actionDelim)
00645 }
00646 LOOP_END(actions)
00647 END_TRY(actions)
00648 if(rulegen)
00649 UNZIP(n);
00650 BUILD_NODE(N_ACTIONS, "ACTIONS", &start, n, n);
00651 if(rulegen) {
00652 Node *node = POP;
00653 BUILD_NODE(N_ACTIONS, "ACTIONS", &start, n, n);
00654 PUSH(node);
00655 }
00656 PARSER_FUNC_END(Actions)
00657
00658 PARSER_FUNC_BEGIN(ActionsToStrings)
00659 int rulegen = 1;
00660 int n = 0;
00661 #define bufferSize 10000
00662 char actiBuffer[bufferSize], recoBuffer[bufferSize];
00663 int actiP = 0, recoP = 0;
00664 Label start, finish;
00665 TRY(actions)
00666 TTEXT_LOOKAHEAD("}");
00667 OR(actions)
00668 LOOP_BEGIN(actions);
00669 start = *FPOS;
00670 NT2(Term, rulegen, MIN_PREC);
00671 (void) POP;
00672 finish = *FPOS;
00673 ABORT(actiP + finish.exprloc - start.exprloc + 1 >= bufferSize);
00674 dupString(e, &start, finish.exprloc - start.exprloc, actiBuffer + actiP);
00675 actiP += finish.exprloc - start.exprloc;
00676 actiBuffer[actiP++] = ';';
00677 if(rulegen) {
00678 CHOICE_BEGIN(reco)
00679 BRANCH_BEGIN(reco)
00680 TTEXT(":::");
00681 start = *FPOS;
00682 NT2(Term, rulegen, MIN_PREC);
00683 (void) POP;
00684 finish = *FPOS;
00685 ABORT(finish.exprloc - start.exprloc + 1 + recoP >= bufferSize);
00686 dupString(e, &start, finish.exprloc - start.exprloc, recoBuffer + recoP);
00687 recoP += finish.exprloc - start.exprloc;
00688 recoBuffer[actiP++] = ';';
00689 BRANCH_END(reco)
00690 BRANCH_BEGIN(reco)
00691 ABORT(recoP + 4 >= bufferSize);
00692 strcpy(recoBuffer + recoP, "nop;");
00693 recoP += 4;
00694 BRANCH_END(reco)
00695 CHOICE_END(reco)
00696 }
00697 n++;
00698 if(rulegen) {
00699 OPTIONAL_BEGIN(actionSemiColon)
00700 TTEXT(";");
00701 OPTIONAL_END(actionSemiColon)
00702 OPTIONAL_BEGIN(actionSemiColonBrace)
00703 TTEXT_LOOKAHEAD("}");
00704 DONE(actions);
00705 OPTIONAL_END(actionSemiColonBrace)
00706 } else {
00707 CHOICE_BEGIN(actionDelim)
00708 BRANCH_BEGIN(actionDelim)
00709 TTEXT("##");
00710 BRANCH_END(actionDelim)
00711 BRANCH_BEGIN(actionDelim)
00712 DONE(actions);
00713 BRANCH_END(actionDelim)
00714 CHOICE_END(actionDelim)
00715 }
00716 LOOP_END(actions)
00717 END_TRY(actions)
00718 actiBuffer[actiP] = recoBuffer[recoP] = '\0';
00719 BUILD_NODE(TK_STRING, actiBuffer, &start, 0, 0);
00720 BUILD_NODE(TK_STRING, recoBuffer, &start, 0, 0);
00721 PARSER_FUNC_END(ActionsToStrings)
00722
00723 PARSER_FUNC_BEGIN1(TermSystemBackwardCompatible, int level)
00724 int rulegen = 0;
00725 TRY(func)
00726 TTEXT("ifExec");
00727 TTEXT("(");
00728 if(level == 1) {
00729 NT1(ExprBackwardCompatible, 0);
00730 } else {
00731 NT2(Term, 0, MIN_PREC);
00732 }
00733 TTEXT(",");
00734 NT2(Actions, 0, level);
00735 TTEXT(",");
00736 NT2(Actions, 0, level);
00737 TTEXT(",");
00738 NT2(Actions, 0, level);
00739 TTEXT(",");
00740 NT2(Actions, 0, level);
00741 TTEXT(")");
00742 BUILD_APP_NODE("if", &start, 5);
00743 OR(func)
00744 TTEXT("whileExec");
00745 TTEXT("(");
00746 if(level == 1) {
00747 NT1(ExprBackwardCompatible, 0);
00748 } else {
00749 NT2(Term, 0, MIN_PREC);
00750 }
00751 TTEXT(",");
00752 NT2(Actions, 0, level);
00753 TTEXT(",");
00754 NT2(Actions, 0, level);
00755 TTEXT(")");
00756 BUILD_APP_NODE("while", &start, 3);
00757 OR(func)
00758 TTEXT("forEachExec");
00759 TTEXT("(");
00760 TTYPE(TK_LOCAL_VAR);
00761 BUILD_NODE(TK_VAR, token->text, &start, 0, 0);
00762 TTEXT(",");
00763 NT2(Actions, 0, level);
00764 TTEXT(",");
00765 NT2(Actions, 0, level);
00766 TTEXT(")");
00767 BUILD_APP_NODE("foreach", &start, 3);
00768
00769 OR(func)
00770 TTEXT("assign");
00771 TTEXT("(");
00772 TTYPE(TK_LOCAL_VAR);
00773 BUILD_NODE(TK_VAR, token->text, &pos, 0, 0);
00774 TTEXT(",");
00775 if(level == 1) {
00776 TRY(expr)
00777 NT1(ExprBackwardCompatible, 1);
00778 OR(expr)
00779 NT(ActionArgumentBackwardCompatible);
00780 END_TRY(expr)
00781 } else {
00782 NT2(Term, 0, MIN_PREC);
00783 }
00784 TTEXT(")");
00785 if(level == 1) {
00786 BUILD_APP_NODE("assignStr", &start, 2);
00787 } else {
00788 BUILD_APP_NODE("assign", &start, 2);
00789 }
00790 OR(func)
00791 TTEXT("forExec");
00792 TTEXT("(");
00793 NT2(Term, 0, MIN_PREC);
00794 TTEXT(",");
00795 NT2(Term, 0, MIN_PREC);
00796 TTEXT(",");
00797 NT2(Term, 0, MIN_PREC);
00798 TTEXT(",");
00799 NT2(Actions, 0, level);
00800 TTEXT(",");
00801 NT2(Actions, 0, level);
00802 TTEXT(")");
00803 BUILD_APP_NODE("for", &start, 5);
00804 OR(func)
00805 TTEXT("breakExec");
00806 BUILD_APP_NODE("break", &start, 0);
00807 OR(func)
00808 TTEXT("delayExec");
00809 TTEXT("(");
00810 NT(ActionArgumentBackwardCompatible)
00811 TTEXT(",");
00812 Token strtoken;
00813 nextActionArgumentStringBackwardCompatible(e, &strtoken);
00814 if(strtoken.type != TK_STRING) {
00815 BUILD_NODE(N_ERROR, "reached the end of stream while parsing an action argument", FPOS,0,0);
00816 } else {
00817 BUILD_NODE(TK_STRING, strtoken.text, &pos, 0, 0);
00818 }
00819 TTEXT(",");
00820 nextActionArgumentStringBackwardCompatible(e, &strtoken);
00821 if(strtoken.type != TK_STRING) {
00822 BUILD_NODE(N_ERROR, "reached the end of stream while parsing an action argument", FPOS,0,0);
00823 } else {
00824 BUILD_NODE(TK_STRING, strtoken.text, &pos, 0, 0);
00825 }
00826 TTEXT(")");
00827 BUILD_APP_NODE("delayExec", &start, 3);
00828 OR(func)
00829 TTEXT("remoteExec");
00830 TTEXT("(");
00831
00832 NT(ActionArgumentBackwardCompatible)TTEXT(",");
00833 NT(ActionArgumentBackwardCompatible)TTEXT(",");
00834 Token strtoken;
00835 nextActionArgumentStringBackwardCompatible(e, &strtoken);
00836 if(strtoken.type != TK_STRING) {
00837 BUILD_NODE(N_ERROR, "reached the end of stream while parsing an action argument", FPOS,0,0);
00838 } else {
00839 BUILD_NODE(TK_STRING, strtoken.text, &pos, 0, 0);
00840 }TTEXT(",");
00841 nextActionArgumentStringBackwardCompatible(e, &strtoken);
00842 if(strtoken.type != TK_STRING) {
00843 BUILD_NODE(N_ERROR, "reached the end of stream while parsing an action argument", FPOS,0,0);
00844 } else {
00845 BUILD_NODE(TK_STRING, strtoken.text, &pos, 0, 0);
00846 }
00847 TTEXT(")");
00848 BUILD_APP_NODE("remoteExec", &start, 4);
00849 END_TRY(func)
00850 PARSER_FUNC_END(TermSystemBackwardCompatible)
00851
00852 PARSER_FUNC_BEGIN1(ExprBackwardCompatible, int level)
00853 int rulegen =0;
00854 TRY(func)
00855 ABORT(level == 1);
00856 NT(TermBackwardCompatible);
00857 OR(func)
00858 TTEXT("(");
00859 NT1(ExprBackwardCompatible, level);
00860 TTEXT(")");
00861 OR(func)
00862 NT1(T, 0);
00863 END_TRY(func)
00864 OPTIONAL_BEGIN(term2)
00865 TTYPE(TK_OP);
00866 char *fn = cpStringExt(token->text, context->region);
00867 ABORT(!isBinaryOp(token));
00868 if(TOKEN_TEXT("like") || TOKEN_TEXT("not like") || TOKEN_TEXT("==") || TOKEN_TEXT("!=")) {
00869 BUILD_APP_NODE("str", FPOS, 1);
00870 NT(ActionArgumentBackwardCompatible);
00871 } else if(TOKEN_TEXT("+") || TOKEN_TEXT("-") || TOKEN_TEXT("*") || TOKEN_TEXT("/") || TOKEN_TEXT("<") || TOKEN_TEXT("<=") || TOKEN_TEXT(">") || TOKEN_TEXT(">=")) {
00872 BUILD_APP_NODE("double", FPOS, 1);
00873 NT1(ExprBackwardCompatible, 1);
00874 BUILD_APP_NODE("double", FPOS, 1);
00875 } else if(TOKEN_TEXT("%%") || TOKEN_TEXT("&&")) {
00876 BUILD_APP_NODE("bool", FPOS, 1);
00877 NT1(ExprBackwardCompatible, 1);
00878 BUILD_APP_NODE("bool", FPOS, 1);
00879 } else {
00880 BUILD_APP_NODE("str", FPOS, 1);
00881 NT1(ExprBackwardCompatible, 1);
00882 BUILD_APP_NODE("str", FPOS, 1);
00883 }
00884 BUILD_APP_NODE(fn, &start, 2);
00885 OPTIONAL_END(term2)
00886 PARSER_FUNC_END(ExprBackwardCompatible)
00887
00888 PARSER_FUNC_BEGIN(TermBackwardCompatible)
00889 int rulegen =0;
00890 TRY(func)
00891 NT1(TermSystemBackwardCompatible, 1);
00892
00893 OR(func)
00894 TTYPE(TK_TEXT);
00895 char *fn = cpStringExt(token->text, context->region);
00896 TTEXT("(");
00897 TTEXT(")");
00898 BUILD_APP_NODE(fn, &start, 0);
00899
00900 OR(func)
00901 TTYPE(TK_TEXT);
00902 char *fn = cpStringExt(token->text, context->region);
00903 TTEXT("(");
00904 int n = 0;
00905 LOOP_BEGIN(func)
00906 NT(ActionArgumentBackwardCompatible);
00907 n++;
00908 CHOICE_BEGIN(paramDelim)
00909 BRANCH_BEGIN(paramDelim)
00910 TTEXT(",");
00911 BRANCH_END(paramDelim)
00912 BRANCH_BEGIN(paramDelim)
00913 TTEXT(")");
00914 DONE(func);
00915 BRANCH_END(paramDelim)
00916 CHOICE_END(paramDelim)
00917 LOOP_END(func)
00918 BUILD_APP_NODE(fn, &start, n);
00919 OR(func)
00920 TTYPE(TK_TEXT);
00921 char *fn = cpStringExt(token->text, context->region);
00922 BUILD_APP_NODE(fn, &start, 0);
00923
00924 END_TRY(func)
00925
00926 PARSER_FUNC_END(ValueBackwardCompatible)
00927
00928
00929 PARSER_FUNC_BEGIN(ActionArgumentBackwardCompatible)
00930 int rulegen = 0;
00931 Token strtoken;
00932 TRY(var)
00933 Label vpos = *FPOS;
00934 TTYPE(TK_LOCAL_VAR);
00935 char *vn = cpStringExt(token->text, context->region);
00936 TTEXT3(",", "|", ")");
00937 PUSHBACK;
00938 BUILD_NODE(TK_VAR, vn, &vpos, 0, 0);
00939 OR(var)
00940 syncTokenQueue(e, context);
00941
00942 nextActionArgumentStringBackwardCompatible(e, &strtoken);
00943 if(strtoken.type != TK_STRING) {
00944 BUILD_NODE(N_ERROR, "reached the end of stream while parsing an action argument", FPOS,0,0);
00945 } else {
00946 NT1(StringExpression, &strtoken);
00947 }
00948 END_TRY(var)
00949 PARSER_FUNC_END(ActionArgumentBackwardCompatible)
00950
00951 PARSER_FUNC_BEGIN2(Term, int rulegen, int prec)
00952 NT1(Value, rulegen);
00953 int done = 0;
00954 while (!done && NO_SYNTAX_ERROR) {
00955 CHOICE_BEGIN(term)
00956 BRANCH_BEGIN(term)
00957 TTYPE(TK_OP);
00958 ABORT(!isBinaryOp(token));
00959 if(prec>=getBinaryPrecedence(token)) {
00960 PUSHBACK;
00961 done = 1;
00962 } else {
00963 char *fn;
00964 if(TOKEN_TEXT("=")) {
00965 fn = "assign";
00966 } else {
00967 fn = token->text;
00968 }
00969 NT2(Term, rulegen, getBinaryPrecedence(token));
00970 #ifdef DEBUG_VERBOSE
00971 char err[1024];
00972 generateErrMsg(fn, FPOS->exprloc, "ftest", err);
00973 printf("%s", err);
00974 #endif
00975 BUILD_APP_NODE(fn, &start, 2);
00976 }
00977
00978 BRANCH_END(term)
00979 BRANCH_BEGIN(term)
00980 TRY(syntacticalArg)
00981 TTEXT_LOOKAHEAD("(");
00982 OR(syntacticalArg)
00983 TTEXT_LOOKAHEAD("[");
00984 END_TRY(syntacticalArg)
00985
00986 Token appToken;
00987 strcpy(appToken.text, "@@");
00988 NT2(Term, rulegen, getBinaryPrecedence(&appToken));
00989 BUILD_NODE(N_APPLICATION, APPLICATION, &start, 2, 2);
00990 BRANCH_END(term)
00991 BRANCH_BEGIN(term)
00992 done = 1;
00993 BRANCH_END(term)
00994 CHOICE_END(term)
00995 }
00996 if(!done) {
00997 break;
00998 }
00999 PARSER_FUNC_END(Term)
01000
01001 PARSER_FUNC_BEGIN1(StringExpression, Token *tk)
01002 int rulegen = 0;
01003 Token *strToken = NULL;
01004 if(tk == NULL) {
01005 TTYPE(TK_STRING);
01006 strToken = token;
01007 } else {
01008 strToken = tk;
01009 }
01010 int i = 0, k = 0;
01011 pos.base = e->base;
01012 long startLoc = strToken->exprloc;
01013 char *str = strToken->text;
01014 int st[100];
01015 int end[100];
01016 int noi = 1;
01017 st[0] = 0;
01018 end[0] = strlen(str);
01019 while(strToken->vars[i]!=-1) {
01020 /* this string contains reference to vars */
01021 int vs = strToken->vars[i];
01022 i++;
01023 if(!isalpha(str[vs+1]) && str[vs+1]!='_') {
01024 continue;
01025 }
01026 int ve;
01027 ve = vs+2;
01028 while(isalnum(str[ve]) || str[ve]=='_') ve++;
01029 end[noi]=end[noi-1];
01030 end[noi-1]=vs;
01031 st[noi]=ve;
01032 noi++;
01033 }
01034 char sbuf[MAX_RULE_LEN];
01035 char delim[1];
01036 delim[0] = '\0';
01037 strncpy(sbuf, str+st[0], end[0]-st[0]);
01038 strcpy(sbuf+end[0]-st[0], delim);
01039 pos.exprloc = startLoc + st[0];
01040 int startloc = pos.exprloc;
01041 BUILD_NODE(TK_STRING, sbuf, &pos,0,0);
01042 k=1; // JMC cppcheck - syntax error
01043 while(k<noi) { // JMC cppcheck - syntax error
01044 //for(k=1;k<noi;k++) {
01045 strncpy(sbuf, str+end[k-1], st[k]-end[k-1]); /* var */
01046 strcpy(sbuf+st[k]-end[k-1], delim);
01047 pos.exprloc = startLoc + end[k-1];
01048 BUILD_NODE(TK_VAR, sbuf, &pos, 0, 0);
01049
01050 BUILD_APP_NODE("str", &pos, 1);
01051
01052 pos.exprloc = startloc;
01053 BUILD_APP_NODE("++", &pos, 2);
01054
01055 strncpy(sbuf, str+st[k], end[k]-st[k]);
01056 strcpy(sbuf+end[k]-st[k], delim);
01057 pos.exprloc = startLoc + st[k];
01058 BUILD_NODE(TK_STRING, sbuf, &pos, 0, 0);
01059
01060 pos.exprloc = startloc;
01061 BUILD_APP_NODE("++", &pos, 2);
01062 k++; // JMC cppcheck - syntax error
01063 }
01064 PARSER_FUNC_END(StringExpression)
01065
01066 PARSER_FUNC_BEGIN1(T, int rulegen)
01067 TRY(value)
01068 TTYPE(TK_LOCAL_VAR);
01069 BUILD_NODE(TK_VAR, token->text, &pos,0,0);
01070 OR(value)
01071 TTYPE(TK_SESSION_VAR);
01072 BUILD_NODE(TK_VAR, token->text, &pos,0,0);
01073 OR(value)
01074 TTYPE(TK_INT);
01075 BUILD_NODE(TK_INT, token->text, &start, 0, 0);
01076 OR(value)
01077 TTYPE(TK_DOUBLE);
01078 BUILD_NODE(TK_DOUBLE, token->text, &start, 0, 0);
01079 END_TRY(value)
01080 PARSER_FUNC_END(StringExpression)
01081
01082 PARSER_FUNC_BEGIN1(Value, int rulegen)
01083 TRY(value)
01084 NT1(T, rulegen);
01085 OR(value)
01086 TTEXT2("true", "false");
01087 BUILD_NODE(TK_BOOL, token->text, &pos,0,0);
01088 OR(value)
01089 TTEXT("(");
01090 TRY(tuple)
01091 TTEXT(")");
01092 BUILD_NODE(N_TUPLE, TUPLE, &start, 0, 0);
01093 OR(tuple)
01094 NT2(Term, rulegen, MIN_PREC);
01095 int n = 1;
01096 LOOP_BEGIN(tupleLoop)
01097 TRY(tupleComp)
01098 TTEXT(",");
01099 NT2(Term, rulegen, MIN_PREC);
01100 n++;
01101 OR(tupleComp)
01102 TTEXT(")");
01103 DONE(tupleLoop);
01104 END_TRY(tupleComp)
01105 LOOP_END(tupleLoop)
01106 BUILD_NODE(N_TUPLE, TUPLE, &start, n, n);
01107
01108
01109 END_TRY(tuple)
01110
01111 OR(value)
01112 TTEXT("{");
01113 NT2(Actions, rulegen, 0);
01114 if(rulegen)
01115 BUILD_NODE(N_ACTIONS_RECOVERY, "ACTIONS_RECOVERY", &start, 2,2);
01116 TTEXT("}");
01117
01118 OR(value)
01119 TTYPE(TK_OP);
01120 ABORT(!isUnaryOp(token));
01121 NT2(Term, rulegen, getUnaryPrecedence(token));
01122 char *fn;
01123 if(strcmp(token->text, "-")==0) {
01124 fn = "neg";
01125 } else {
01126 fn = token->text;
01127 }
01128 BUILD_APP_NODE(fn, &start,1);
01129
01130 OR(value)
01131 int n = 0;
01132 TTEXT("SELECT");
01133 LOOP_BEGIN(columns)
01134 NT(Column);
01135 n++;
01136 TRY(columnDelim)
01137 TTEXT(",");
01138 OR(columnDelim)
01139 DONE(columns)
01140 END_TRY(columnDelim)
01141 LOOP_END(columns)
01142 OPTIONAL_BEGIN(where)
01143 TTEXT("WHERE");
01144 LOOP_BEGIN(queryConds)
01145 NT(QueryCond);
01146 n++;
01147 TRY(queryCondDelim)
01148 TTEXT("AND");
01149 OR(queryCondDelim)
01150 DONE(queryConds)
01151 END_TRY(queryCondDelim)
01152 LOOP_END(queryConds)
01153 OPTIONAL_END(where)
01154 BUILD_APP_NODE("query", &start, n);
01155
01156 OR(value)
01157 TRY(func)
01158 ABORT(!rulegen);
01159 TRY(funcIf)
01160 TTEXT("if");
01161 TTEXT("(");
01162 NT2(Term, 1, MIN_PREC);
01163 TTEXT(")");
01164 OPTIONAL_BEGIN(ifThen)
01165 TTEXT("then");
01166 OPTIONAL_END(ifThen)
01167 TTEXT("{");
01168 NT2(Actions, 1, 0);
01169 TTEXT("}");
01170 TRY(ifElse)
01171 TTEXT("else");
01172 TTEXT_LOOKAHEAD("if");
01173 NT2(Term, 1, MIN_PREC);
01174 BUILD_NODE(N_ACTIONS, "ACTIONS", &pos, 1, 1);
01175 BUILD_APP_NODE("nop", FPOS, 0);
01176 BUILD_NODE(N_ACTIONS, "ACTIONS", FPOS, 1, 1);
01177 OR(ifElse)
01178 TTEXT("else");
01179 TTEXT("{");
01180 NT2(Actions, 1, 0);
01181 TTEXT("}");
01182 OR(ifElse)
01183 BUILD_APP_NODE("nop", FPOS, 0);
01184 BUILD_NODE(N_ACTIONS, "ACTIONS", FPOS, 1, 1);
01185 BUILD_APP_NODE("nop", FPOS, 0);
01186 BUILD_NODE(N_ACTIONS, "ACTIONS", FPOS, 1, 1);
01187 END_TRY(ifElse)
01188 UNZIP(2);
01189 BUILD_APP_NODE("if", &start, 5);
01190 OR(funcIf)
01191 TTEXT("if");
01192 NT2(Term, rulegen, MIN_PREC);
01193 TTEXT("then");
01194 NT2(Term, 1, MIN_PREC);
01195 BUILD_APP_NODE("nop", FPOS, 0);
01196 TTEXT("else")
01197 NT2(Term, 1, MIN_PREC);
01198 BUILD_APP_NODE("nop", FPOS, 0);
01199 UNZIP(2);
01200 BUILD_APP_NODE("if2", &start, 5);
01201 END_TRY(funcIf)
01202 OR(func)
01203 ABORT(!rulegen);
01204 TRY(whil)
01205 TTEXT("while");
01206 OR(whil)
01207 TTEXT("whileExec");
01208 END_TRY(whil)
01209 TTEXT("(");
01210 NT2(Term, 1, MIN_PREC);
01211 TTEXT(")");
01212 TTEXT("{");
01213 NT2(Actions, 1, 0);
01214 TTEXT("}");
01215 BUILD_APP_NODE("while", &start, 3);
01216 OR(func)
01217 ABORT(!rulegen);
01218 TRY(foreach)
01219 TTEXT("foreach");
01220 OR(foreach)
01221 TTEXT("forEachExec");
01222 END_TRY(foreach)
01223 TTEXT("(");
01224 TTYPE(TK_LOCAL_VAR);
01225 BUILD_NODE(TK_VAR, token->text, &pos, 0, 0);
01226 TRY(foreach2)
01227 TTEXT(")");
01228 TTEXT("{");
01229 NT2(Actions, 1, 0);
01230 TTEXT("}");
01231 BUILD_APP_NODE("foreach", &start, 3);
01232 OR(foreach2)
01233 TTEXT("in");
01234 NT2(Term, 1, MIN_PREC);
01235 TTEXT(")");
01236 TTEXT("{");
01237 NT2(Actions, 1, 0);
01238 TTEXT("}");
01239 BUILD_APP_NODE("foreach2", &start, 4);
01240 END_TRY(foreach2)
01241
01242 OR(func)
01243 ABORT(!rulegen);
01244 TRY(fo)
01245 TTEXT("for");
01246 OR(fo)
01247 TTEXT("forExec");
01248 END_TRY(fo)
01249 TTEXT("(");
01250 NT2(Term, 1, MIN_PREC);
01251 TTEXT(";");
01252 NT2(Term, 1, MIN_PREC);
01253 TTEXT(";");
01254 NT2(Term, 1, MIN_PREC);
01255 TTEXT(")");
01256 TTEXT("{");
01257 NT2(Actions, 1, 0);
01258 TTEXT("}");
01259 BUILD_APP_NODE("for", &start, 5);
01260 OR(func)
01261 ABORT(!rulegen);
01262 TTEXT("remote");
01263 TTEXT("(");
01264 NT2(Term, 1, MIN_PREC);
01265 TTEXT(",");
01266 NT2(Term, 1, MIN_PREC);
01267 TTEXT(")");
01268 TTEXT("{");
01269 char buf[10000];
01270 Label actionsStart = *FPOS;
01271 NT2(Actions, 1, 0);
01272 (void) POP;
01273 (void) POP;
01274 Label actionsFinish = *FPOS;
01275 TTEXT("}");
01276 dupString(e, &actionsStart, actionsFinish.exprloc - actionsStart.exprloc, buf);
01277 BUILD_NODE(TK_STRING, buf, &actionsStart, 0, 0);
01278 BUILD_NODE(TK_STRING, "", &actionsFinish, 0, 0);
01279 BUILD_APP_NODE("remoteExec", &start, 4);
01280 OR(func)
01281 ABORT(!rulegen);
01282 TTEXT("delay");
01283 TTEXT("(");
01284 NT2(Term, 1, MIN_PREC);
01285 TTEXT(")");
01286 TTEXT("{");
01287 char buf[10000];
01288 Label actionsStart = *FPOS;
01289 NT2(Actions, 1, 0);
01290 (void) POP;
01291 (void) POP;
01292 Label actionsFinish = *FPOS;
01293 TTEXT("}");
01294 dupString(e, &actionsStart, actionsFinish.exprloc - actionsStart.exprloc, buf);
01295 BUILD_NODE(TK_STRING, buf, &actionsStart, 0, 0);
01296 BUILD_NODE(TK_STRING, "", &actionsFinish, 0, 0);
01297 BUILD_APP_NODE("delayExec", &start, 3);
01298 OR(func)
01299 ABORT(!rulegen);
01300 TTEXT("let");
01301 NT2(Term, 1, 2);
01302 TTEXT("=");
01303 NT2(Term, 1, MIN_PREC);
01304 TTEXT("in");
01305 NT2(Term, 1, MIN_PREC);
01306 BUILD_APP_NODE("let", &start, 3);
01307 OR(func)
01308 ABORT(!rulegen);
01309 TTEXT("match");
01310 NT2(Term, 1, 2);
01311 TTEXT("with");
01312 int n = 0;
01313 OPTIONAL_BEGIN(semicolon)
01314 TTEXT("|");
01315 OPTIONAL_END(semicolon)
01316 LOOP_BEGIN(cases)
01317 Label cpos = *FPOS;
01318 NT2(Term, 1, MIN_PREC);
01319 TTEXT("=>");
01320 NT2(Term, 1, MIN_PREC);
01321 BUILD_NODE(N_TUPLE, TUPLE, &cpos, 2, 2);
01322 n++;
01323 TRY(vbar)
01324 TTEXT("|");
01325 OR(vbar)
01326 DONE(cases)
01327
01328 END_TRY(vbar);
01329 LOOP_END(cases)
01330 BUILD_APP_NODE("match", &start, n+1);
01331 OR(func)
01332 ABORT(rulegen);
01333 NT1(TermSystemBackwardCompatible, 0);
01334 OR(func)
01335 TTYPE(TK_TEXT);
01336 ABORT(rulegen && isKeyword(token->text));
01337 char *fn = cpStringExt(token->text, context->region);
01338 BUILD_NODE(TK_TEXT, fn, &start, 0, 0);
01339 #ifdef DEBUG_VERBOSE
01340 char err[1024];
01341 generateErrMsg(fn, start.exprloc, start.base, err);
01342 printf("%s, %ld\n", err, start.exprloc);
01343 #endif
01344 TRY(nullary)
01345 TTEXT_LOOKAHEAD("(");
01346 OR(nullary)
01347 TTEXT_LOOKAHEAD("[");
01348 OR(nullary)
01349 Node *n = POP;
01350 BUILD_APP_NODE(n->text, &start, 0);
01351 END_TRY(nullary)
01352 END_TRY(func)
01353 OR(value)
01354 NT1(StringExpression, NULL);
01355 END_TRY(value)
01356 PARSER_FUNC_END(Value)
01357
01358 PARSER_FUNC_BEGIN(Column)
01359 int rulegen = 1;
01360
01361 TRY(Column)
01362 Label colFuncStart = *FPOS;
01363 char *columnFunc;
01364 TRY(columnFunc)
01365 TTEXT2("count", "COUNT");
01366 columnFunc = "count";
01367 OR(columnFunc)
01368 TTEXT2("sum", "SUM");
01369 columnFunc = "sum";
01370 OR(columnFunc)
01371 TTEXT2("order_desc", "ORDER_DESC");
01372 columnFunc = "order_desc";
01373 OR(columnFunc)
01374 TTEXT2("order_asc", "ORDER_ASC");
01375 columnFunc = "order_asc";
01376 END_TRY(columnFunc)
01377 TTEXT("(");
01378 Label colStart = *FPOS;
01379 TTYPE(TK_TEXT);
01380 BUILD_NODE(TK_COL, token->text, &colStart, 0, 0);
01381 TTEXT(")");
01382 BUILD_NODE(N_ATTR, columnFunc, &colFuncStart, 1, 1);
01383 OR(Column)
01384 Label colStart = *FPOS;
01385 TTYPE(TK_TEXT);
01386 BUILD_NODE(TK_COL, token->text, &colStart, 0, 0);
01387 BUILD_NODE(N_ATTR, "", &colStart, 1, 1);
01388 END_TRY(Column)
01389 PARSER_FUNC_END(Column)
01390
01391 PARSER_FUNC_BEGIN(QueryCond)
01392 int rulegen = 1;
01393
01394 TRY(QueryCond)
01395 NT(Column)
01396 TRY(QueryCondOp)
01397 TTEXT2("=", "==");
01398 NT1(Value, 1);
01399 BUILD_NODE(N_QUERY_COND, "=", &start, 2, 2);
01400 OR(QueryCondOp)
01401 TTEXT2("<>", "!=");
01402 NT1(Value, 1);
01403 BUILD_NODE(N_QUERY_COND, "<>", &start, 2, 2);
01404 OR(QueryCondOp)
01405 TTEXT(">");
01406 NT1(Value, 1);
01407 BUILD_NODE(N_QUERY_COND, ">", &start, 2, 2);
01408 OR(QueryCondOp)
01409 TTEXT("<");
01410 NT1(Value, 1);
01411 BUILD_NODE(N_QUERY_COND, "<", &start, 2, 2);
01412 OR(QueryCondOp)
01413 TTEXT(">=");
01414 NT1(Value, 1);
01415 BUILD_NODE(N_QUERY_COND, ">=", &start, 2, 2);
01416 OR(QueryCondOp)
01417 TTEXT("<=");
01418 NT1(Value, 1);
01419 BUILD_NODE(N_QUERY_COND, "<=", &start, 2, 2);
01420 OR(QueryCondOp)
01421 TTEXT2("in", "IN");
01422 NT1(Value, 1);
01423 BUILD_NODE(N_QUERY_COND, "in", &start, 2, 2);
01424 OR(QueryCondOp)
01425 TTEXT2("between", "BETWEEN");
01426 NT1(Value, 1);
01427 NT1(Value, 1);
01428 BUILD_NODE(N_QUERY_COND, "between", &start, 3, 3);
01429 OR(QueryCondOp)
01430 TTEXT2("like", "LIKE");
01431 NT1(Value, 1);
01432 BUILD_NODE(N_QUERY_COND, "like", &start, 2, 2);
01433 OR(QueryCondOp)
01434 TTEXT2("not", "NOT");
01435 TTEXT2("like", "LIKE");
01436 NT1(Value, 1);
01437 BUILD_NODE(N_QUERY_COND, "not like", &start, 2, 2);
01438 END_TRY(QueryCondOp)
01439 END_TRY(QueryCond)
01440 PARSER_FUNC_END(QueryCond)
01441
01442 int nextStringBase2(Pointer *e, char *value, char* delim) {
01443 nextChar(e);
01444 int ch = nextChar(e);
01445 while(ch!=-1) {
01446 if(delim[0] == ch && delim[1] == lookAhead(e, 1)) {
01447 if(delim[0] == delim[1]) {
01448 while(lookAhead(e, 2) == delim[1]) {
01449 *(value++) = delim[0];
01450 nextChar(e);
01451 }
01452 }
01453 *value='\0';
01454 nextChar(e);
01455 nextChar(e);
01456 return 0;
01457 }
01458 *(value++) = ch;
01459 ch = nextChar(e);
01460 }
01461 return -1;
01462
01463 }
01464 /*
01465 * return number of vars or -1 if no string found
01466 */
01467 int nextStringBase(Pointer *e, char *value, char* delim, int consumeDelim, char escape, int vars[]) {
01468 int mode=1; /* 1 string 3 escape */
01469 int nov = 0;
01470 char* value0=value;
01471 *value = lookAhead(e, 0);
01472 value++;
01473 int ch = nextChar(e);
01474 while(ch!=-1) {
01475 *value = ch;
01476 switch(mode) {
01477 case 1:
01478 if(ch ==escape) {
01479 value--;
01480 mode = 3;
01481 } else if(strchr(delim, ch)!=NULL) {
01482 if(consumeDelim) {
01483 value[1]='\0';
01484 trimquotes(value0);
01485 nextChar(e);
01486 } else {
01487 value[0]='\0';
01488 }
01489 vars[nov] = -1;
01490 return nov;
01491 } else if((ch =='*' || ch=='$') &&
01492 isalpha(lookAhead(e, 1))) {
01493 vars[nov++] = value - value0 - 1;
01494 }
01495
01496
01497 break;
01498 case 3:
01499 if(ch=='n') {
01500 *value = '\n';
01501 } else if(ch == 't') {
01502 *value = '\t';
01503 } else if(ch =='r') {
01504 *value = '\r';
01505 } else if(ch =='0') {
01506 *value = '\0';
01507 } else {
01508 *value = ch;
01509 }
01510 mode -= 2;
01511 }
01512 ch = nextChar(e);
01513 value ++;
01514 }
01515 return -1;
01516 }
01517 int nextStringParsed(Pointer *e, char *value, char* deliml, char *delimr, char *delim, int consumeDelim, int vars[]) {
01518 int mode=0; /* level */
01519 int nov = 0;
01520 char* value0=value;
01521 int ch = lookAhead(e, 0);
01522 while(ch!=-1) {
01523 *value = ch;
01524 if(strchr(deliml, ch)!=NULL) {
01525 mode ++;
01526 } else if(mode > 0 && strchr(delimr, ch)!=NULL) {
01527 mode --;
01528 } else if(mode == 0 && strchr(delim, ch)) {
01529 if(consumeDelim) {
01530 value[1]='\0';
01531 trimquotes(value0);
01532 nextChar(e);
01533 } else {
01534 value[0]='\0';
01535 }
01536 vars[nov] = -1;
01537 return nov;
01538 } else if((ch =='*' || ch=='$') &&
01539 isalpha(lookAhead(e, 1))) {
01540 vars[nov++] = value - value0;
01541 }
01542 ch = nextChar(e);
01543 value ++;
01544 }
01545 return -1;
01546 }
01547 int nextString(Pointer *e, char *value, int vars[]) {
01548 return nextStringBase(e, value, "\"", 1, '\\', vars);
01549 }
01550 int nextString2(Pointer *e, char *value, int vars[]) {
01551 return nextStringBase(e, value, "\'", 1, '\\', vars);
01552 }
01553
01554 int getBinaryPrecedence(Token * token) {
01555 int i;
01556 for(i=0;i<num_ops;i++) {
01557 if(new_ops[i].arity==2 && strcmp(new_ops[i].string,token->text)==0) {
01558 return new_ops[i].prec;
01559 }
01560 }
01561 return -1;
01562 }
01563 int getUnaryPrecedence(Token * token) {
01564 int i;
01565 for(i=0;i<num_ops;i++) {
01566 if(new_ops[i].arity==1 && strcmp(new_ops[i].string,token->text)==0) {
01567 return new_ops[i].prec;
01568 }
01569 }
01570 return -1;
01571 }
01572 int isUnaryOp(Token *token) {
01573 int i;
01574 for (i=0;i<num_ops;i++) {
01575 if (strcmp(token->text, new_ops[i].string) == 0) {
01576 if(new_ops[i].arity == 1) return 1;
01577 }
01578 }
01579 return 0;
01580 }
01581 int isBinaryOp(Token *token) {
01582 int i;
01583 for (i=0;i<num_ops;i++) {
01584 if (strcmp(token->text, new_ops[i].string) == 0) {
01585 if(new_ops[i].arity == 2) return 1;
01586 }
01587 }
01588 return 0;
01589 }
01590 int isOp(char *token) {
01591 int i;
01592 for (i=0;i<num_ops;i++) {
01593 if (strcmp(token, new_ops[i].string) == 0) {
01594 return 1;
01595 }
01596 }
01597 return 0;
01598 }
01599 char* trim(char* str) {
01600 char* trimmed = str;
01601 while(*trimmed =='\t' || *trimmed==' ') {
01602 trimmed ++;
01603 }
01604 int l = strlen(trimmed)-1;
01605 while(l>=0 && (trimmed[l] =='\t' || trimmed[l]==' ')) {
01606 l--;
01607 }
01608 trimmed[l+1] = '\0';
01609 return trimmed;
01610
01611 }
01612 void trimquotes(char *string) {
01613 int len = strlen(string)-2;
01614 memmove(string, string+1, len*sizeof(char));
01615 string[len]='\0';
01616 }
01617
01618 void printTree(Node *n, int indent) {
01619 printIndent(indent);
01620 char buf[128], buf2[128];
01621 if(getNodeType(n) >= T_UNSPECED && getNodeType(n) <= T_TYPE ) {
01622 typeToString(n, NULL, buf, 128);
01623 printf("%s:%d\n", buf, getNodeType(n));
01624 return;
01625 } else if(getNodeType(n) >= TC_LT && getNodeType(n) <= TC_SET) {
01626 printf("%s:%d\n",n->text, getNodeType(n));
01627 } else {
01628 if(n->coercionType!=NULL) {
01629 typeToString(n->coercionType, NULL, buf, 128);
01630 } else {
01631 buf[0] = '\0';
01632 }
01633 if(n->exprType!=NULL) {
01634 typeToString(n->exprType, NULL, buf2, 128);
01635 } else {
01636 buf2[0] = '\0';
01637 }
01638 char iotype[128];
01639 strcpy(iotype, "");
01640 if(getIOType(n) & IO_TYPE_INPUT) {
01641 strcat(iotype, "i");
01642 }
01643 if(getIOType(n) & IO_TYPE_OUTPUT) {
01644 strcat(iotype, "o");
01645 }
01646 if(getIOType(n) & IO_TYPE_DYNAMIC) {
01647 strcat(iotype, "d");
01648 }
01649 if(getIOType(n) & IO_TYPE_EXPRESSION) {
01650 strcat(iotype, "e");
01651 }
01652 if(getIOType(n) & IO_TYPE_ACTIONS) {
01653 strcat(iotype, "a");
01654 }
01655 printf("%s:%d %s => %s(option=%d)[%s]\n",n->text, getNodeType(n), buf2, buf, n->option, iotype);
01656 }
01657 int i;
01658 for(i=0;i<n->degree;i++) {
01659 printTree(n->subtrees[i],indent+1);
01660 }
01661
01662 }
01663 void patternToString(char **p, int *s, int indent, int prec, Node *n) {
01664 switch(getNodeType(n)) {
01665 case N_APPLICATION:
01666 if(getNodeType(n->subtrees[0]) == TK_TEXT) {
01667 char *fn = n->subtrees[0]->text;
01668 Token t;
01669 strcpy(t.text, fn);
01670 if(isBinaryOp(&t)) {
01671 int opPrec = getBinaryPrecedence(&t);
01672 if(opPrec < prec) {
01673 PRINT(p, s, "%s", "(");
01674 }
01675 patternToString(p, s, indent, prec, n->subtrees[1]->subtrees[0]);
01676 PRINT(p, s, " %s ", fn);
01677 patternToString(p, s, indent, prec+1, n->subtrees[1]->subtrees[1]);
01678 if(opPrec < prec) {
01679 PRINT(p, s, "%s", ")");
01680 }
01681 } else {
01682 patternToString(p, s, indent, MIN_PREC, n->subtrees[0]);
01683 if(getNodeType(n->subtrees[1]) != N_TUPLE || n->subtrees[1]->degree != 0) {
01684 patternToString(p, s, indent, MIN_PREC, n->subtrees[1]);
01685 }
01686 }
01687 } else {
01688 PRINT(p, s, "%s", "<unsupported>");
01689 }
01690 break;
01691 case N_TUPLE:
01692 PRINT(p, s, "%s", "(");
01693 int i;
01694 for(i=0;i<n->degree;i++) {
01695 if(i!=0) {
01696 PRINT(p, s, "%s", ",");
01697 }
01698 patternToString(p, s, indent, MIN_PREC, n->subtrees[i]);
01699 }
01700 PRINT(p, s, "%s", ")");
01701 break;
01702 case TK_BOOL:
01703 case TK_DOUBLE:
01704 case TK_INT:
01705 case TK_VAR:
01706 case TK_TEXT:
01707 PRINT(p, s, "%s", n->text);
01708 break;
01709 case TK_STRING:
01710 PRINT(p, s, "%s", "\"");
01711 unsigned int k;
01712 for(k=0;k<strlen(n->text);k++) {
01713 switch(n->text[k]) {
01714 case '\t':
01715 PRINT(p, s, "%s", "\\t");
01716 break;
01717 case '\n':
01718 PRINT(p, s, "%s", "\\n");
01719 break;
01720 case '\r':
01721 PRINT(p, s, "%s", "\\r");
01722 break;
01723 case '$':
01724 case '*':
01725 case '\\':
01726 case '\"':
01727 case '\'':
01728 PRINT(p, s, "%s", "\\");
01729 PRINT(p, s, "%c", n->text[k]);
01730 break;
01731 default:
01732 PRINT(p, s, "%c", n->text[k]);
01733
01734 }
01735 }
01736 PRINT(p, s, "%s", "\"");
01737 break;
01738 default:
01739 PRINT(p, s, "%s", "<unsupported>");
01740 }
01741 }
01742 void termToString(char **p, int *s, int indent, int prec, Node *n, int quote) {
01743 switch(getNodeType(n)) {
01744 case N_ACTIONS_RECOVERY:
01745 actionsToString(p, s, indent, n->subtrees[0], n->subtrees[1]);
01746 break;
01747 case N_APPLICATION:
01748 if(getNodeType(n->subtrees[0]) == TK_TEXT) {
01749 char *fn = n->subtrees[0]->text;
01750 if(strcmp(fn, "if") == 0) {
01751 PRINT(p, s, "%s", "if (");
01752 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0],quote);
01753 PRINT(p, s, "%s", ") ");
01754 actionsToString(p, s, indent, n->subtrees[1]->subtrees[1], n->subtrees[1]->subtrees[3]);
01755 PRINT(p, s, "%s", " else ");
01756 actionsToString(p, s, indent, n->subtrees[1]->subtrees[2], n->subtrees[1]->subtrees[4]);
01757 break;
01758 }
01759 if(strcmp(fn, "if2") == 0) {
01760 PRINT(p, s, "%s", "if ");
01761 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0],quote);
01762 PRINT(p, s, "%s", " then ");
01763 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[1],quote);
01764 PRINT(p, s, "%s", " else ");
01765 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[2],quote);
01766 break;
01767 }
01768 if(strcmp(fn, "while") == 0) {
01769 PRINT(p, s, "%s", "while (");
01770 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0],quote);
01771 PRINT(p, s, "%s", ") ");
01772 actionsToString(p, s, indent, n->subtrees[1]->subtrees[1], n->subtrees[1]->subtrees[2]);
01773 break;
01774 }
01775 if(strcmp(fn, "foreach") == 0) {
01776 PRINT(p, s, "%s", "foreach (");
01777 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0],quote);
01778 PRINT(p, s, "%s", ") ");
01779 actionsToString(p, s, indent, n->subtrees[1]->subtrees[1], n->subtrees[1]->subtrees[2]);
01780 break;
01781 }
01782 if(strcmp(fn, "foreach2") == 0) {
01783 PRINT(p, s, "%s", "foreach (");
01784 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0],quote);
01785 PRINT(p, s, "%s", " in ");
01786 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[1],quote);
01787 PRINT(p, s, "%s", ") ");
01788 actionsToString(p, s, indent, n->subtrees[1]->subtrees[2], n->subtrees[1]->subtrees[3]);
01789 break;
01790 }
01791 if(strcmp(fn, "for") == 0) {
01792 PRINT(p, s, "%s", "for (");
01793 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0],quote);
01794 PRINT(p, s, "%s", ";");
01795 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[1],quote);
01796 PRINT(p, s, "%s", ";");
01797 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[2],quote);
01798 PRINT(p, s, "%s", ") ");
01799 actionsToString(p, s, indent, n->subtrees[1]->subtrees[3], n->subtrees[1]->subtrees[4]);
01800 break;
01801 }
01802 if(strcmp(fn, "let") == 0) {
01803 PRINT(p, s, "%s", "let ");
01804 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0],quote);
01805 PRINT(p, s, "%s", " = ");
01806 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[1],quote);
01807 PRINT(p, s, "%s", " in ");
01808 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[2],quote);
01809 break;
01810 }
01811 if(strcmp(fn, "match") == 0) {
01812 PRINT(p, s, "%s", "match ");
01813 termToString(p, s, indent, MIN_PREC, N_APP_ARG(n, 0),quote);
01814 PRINT(p, s, "%s", " with");
01815 int i;
01816 for(i=1;i<N_APP_ARITY(n);i++) {
01817 PRINT(p, s, "%s", "\n");
01818 indentToString(p, s, indent + 1);
01819 PRINT(p, s, "%s", "| ");
01820 patternToString(p, s, indent + 1, MIN_PREC, N_APP_ARG(n, i)->subtrees[0]);
01821 PRINT(p, s, "%s", " => ");
01822 termToString(p, s, indent + 1, MIN_PREC, N_APP_ARG(n, i)->subtrees[1],quote);
01823 }
01824 break;
01825 }
01826 if(strcmp(fn, "assign") == 0) {
01827 patternToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[0]);
01828 PRINT(p, s, "%s", " = ");
01829 termToString(p, s, indent, MIN_PREC, n->subtrees[1]->subtrees[1],quote);
01830 break;
01831 }
01832 Token t;
01833 strcpy(t.text, fn);
01834 if(isBinaryOp(&t)) {
01835 int opPrec = getBinaryPrecedence(&t);
01836 if(opPrec < prec) {
01837 PRINT(p, s, "%s", "(");
01838 }
01839 termToString(p, s, indent, prec, n->subtrees[1]->subtrees[0],quote);
01840 PRINT(p, s, " %s ", fn);
01841 termToString(p, s, indent, prec+1, n->subtrees[1]->subtrees[1],quote);
01842 if(opPrec < prec) {
01843 PRINT(p, s, "%s", ")");
01844 }
01845 break;
01846 }
01847 }
01848 termToString(p, s, indent, MIN_PREC, n->subtrees[0],quote);
01849 termToString(p, s, indent, MIN_PREC, n->subtrees[1],quote);
01850 break;
01851 case N_TUPLE:
01852 PRINT(p, s, "%s", "(");
01853 int i;
01854 for(i=0;i<n->degree;i++) {
01855 if(i!=0) {
01856 PRINT(p, s, "%s", ",");
01857 }
01858 termToString(p, s, indent, MIN_PREC, n->subtrees[i],quote);
01859 }
01860 PRINT(p, s, "%s", ")");
01861 break;
01862 case TK_BOOL:
01863 case TK_DOUBLE:
01864 case TK_INT:
01865 case TK_VAR:
01866 case TK_TEXT:
01867 PRINT(p, s, "%s", n->text);
01868 break;
01869 case TK_STRING:
01870 PRINT(p, s, "%s", quote?"\'":"\"");
01871 unsigned int k;
01872 for(k=0;k<strlen(n->text);k++) {
01873 switch(n->text[k]) {
01874 case '\t':
01875 PRINT(p, s, "%s", "\\t");
01876 break;
01877 case '\n':
01878 PRINT(p, s, "%s", "\\n");
01879 break;
01880 case '\r':
01881 PRINT(p, s, "%s", "\\r");
01882 break;
01883 case '$':
01884 case '*':
01885 case '\\':
01886 case '\"':
01887 case '\'':
01888 PRINT(p, s, "%s", "\\");
01889 PRINT(p, s, "%c", n->text[k]);
01890 break;
01891 default:
01892 PRINT(p, s, "%c", n->text[k]);
01893
01894 }
01895
01896 }
01897 PRINT(p, s, "%s", quote?"\'":"\"");
01898 break;
01899 default:
01900 PRINT(p, s, "%s", "<unsupported>");
01901 }
01902 }
01903 void indentToString(char **p, int *s, int indent) {
01904 int i;
01905 for(i=0;i<indent;i++) {
01906 PRINT(p, s, "%s", " ");
01907 }
01908
01909 }
01910 void actionsToString(char **p, int *s, int indent, Node *na, Node *nr) {
01911 int n = na->degree;
01912
01913 int i;
01914 PRINT(p, s, "%s", "{\n");
01915 for(i=0;i<n;i++) {
01916 indentToString(p, s, indent+1);
01917 termToString(p, s, indent+1, MIN_PREC, na->subtrees[i],0);
01918 if(nr!=NULL && i<nr->degree && (getNodeType(nr->subtrees[i])!=N_APPLICATION || strcmp(nr->subtrees[i]->subtrees[0]->text, "nop")!=0)) {
01919 PRINT(p, s, "%s", ":::");
01920 termToString(p, s, indent+1, MIN_PREC, nr->subtrees[i],0);
01921 }
01922 if((*p)[-1]!='}')
01923 PRINT(p, s, "%s", ";");
01924 PRINT(p, s, "%s", "\n");
01925 }
01926 indentToString(p, s, indent);
01927 PRINT(p, s, "%s", "}");
01928 }
01929
01930 void metadataToString(char **p, int *s, int indent, Node *nm) {
01931 int n = nm->degree;
01932 int i;
01933 for(i=0;i<n;i++) {
01934 indentToString(p, s, indent);
01935 PRINT(p, s, "%s", "@(");
01936 termToString(p, s, indent, MIN_PREC, nm->subtrees[i]->subtrees[0],0);
01937 PRINT(p, s, "%s", ", ");
01938 termToString(p, s, indent, MIN_PREC, nm->subtrees[i]->subtrees[1],0);
01939 PRINT(p, s, "%s", ", ");
01940 termToString(p, s, indent, MIN_PREC, nm->subtrees[i]->subtrees[2],0);
01941 PRINT(p, s, "%s", ")\n");
01942 }
01943 }
01944
01945 void ruleNameToString(char **p, int *s, int indent, Node *rn) {
01946 PRINT(p, s, "%s", rn->text);
01947 PRINT(p, s, "%s", "(");
01948 int i;
01949 for(i=0;i<rn->subtrees[0]->degree;i++) {
01950 if(i!=0) {
01951 PRINT(p, s, "%s", ",");
01952 }
01953 patternToString(p, s, indent, MIN_PREC, rn->subtrees[0]->subtrees[i]);
01954 }
01955 PRINT(p, s, "%s", ")");
01956 }
01957 void typeToStringParser(char **p, int *s, int indent, int lifted, ExprType *type) {
01958 ExprType *etype = type;
01959
01960 if(getIOType(etype) == (IO_TYPE_INPUT | IO_TYPE_OUTPUT)) {
01961 PRINT(p, s, "%s ", "input output");
01962 } else if(getIOType(etype) == IO_TYPE_OUTPUT) {
01963 PRINT(p, s, "%s ", "output");
01964 } else if(getIOType(etype) == IO_TYPE_DYNAMIC) {
01965 PRINT(p, s, "%s ", "dynamic");
01966 } else if(getIOType(etype) == IO_TYPE_ACTIONS) {
01967 PRINT(p, s, "%s ", "actions");
01968 } else if(getIOType(etype) == IO_TYPE_EXPRESSION) {
01969 PRINT(p, s, "%s ", "expression");
01970 }
01971 if(getNodeType(etype) == T_VAR) {
01972 PRINT(p, s, "%s", etype->text);
01973 if(T_VAR_NUM_DISJUNCTS(type)!=0) {
01974 PRINT(p, s, " %s", "{");
01975 int i;
01976 for(i=0;i<T_VAR_NUM_DISJUNCTS(type);i++) {
01977 typeToStringParser(p, s, indent, 0, T_VAR_DISJUNCT(type, i));
01978 PRINT(p, s, "%s", " ");
01979 }
01980 PRINT(p, s, "%s", "}");
01981 }
01982 } else if(getNodeType(etype) == T_CONS) {
01983 if(strcmp(etype->text, FUNC) == 0) {
01984
01985 typeToStringParser(p, s, indent, 1, T_CONS_TYPE_ARG(etype, 0));
01986 if(getVararg(type) == OPTION_VARARG_OPTIONAL) {
01987 PRINT(p, s, " %s", "?");
01988 } else if(getVararg(type) == OPTION_VARARG_STAR) {
01989 PRINT(p, s, " %s", "*");
01990 } else if(getVararg(type) == OPTION_VARARG_PLUS) {
01991 PRINT(p, s, " %s", "+");
01992 }
01993 PRINT(p, s, " %s ", "->");
01994 typeToStringParser(p, s, indent, 0, T_CONS_TYPE_ARG(etype, 1));
01995
01996 } else {
01997 PRINT(p, s, "%s", T_CONS_TYPE_NAME(etype));
01998 int i;
01999 if(T_CONS_ARITY(etype) != 0) {
02000 PRINT(p, s, "%s", "(");
02001 for(i=0;i<T_CONS_ARITY(etype);i++) {
02002 if(i!=0) {
02003 PRINT(p, s, "%s ", ",");
02004 }
02005 typeToStringParser(p, s, indent, 0, T_CONS_TYPE_ARG(etype, i));
02006 }
02007 PRINT(p, s, "%s", ")");
02008 }
02009 }
02010 } else if(getNodeType(etype) == T_FLEX) {
02011 PRINT(p, s, "%s ", typeName_Parser(getNodeType(etype)));
02012 typeToStringParser(p, s, indent, 0, etype->subtrees[0]);
02013 } else if(getNodeType(etype) == T_FIXD) {
02014 PRINT(p, s, "%s ", typeName_Parser(getNodeType(etype)));
02015 typeToStringParser(p, s, indent, 0, etype->subtrees[0]);
02016 PRINT(p, s, " %s ", "=>");
02017 typeToStringParser(p, s, indent, 0, etype->subtrees[1]);
02018 } else if(getNodeType(etype) == T_TUPLE) {
02019 if(T_CONS_ARITY(etype) == 0) {
02020 PRINT(p, s, "%s", "unit");
02021 } else {
02022 if(T_CONS_ARITY(etype) == 1 && !lifted) {
02023 PRINT(p, s, "%s", "<");
02024 }
02025 int i;
02026 for(i=0;i<T_CONS_ARITY(etype);i++) {
02027 if(i!=0) {
02028 PRINT(p, s, " %s ", "*");
02029 }
02030 typeToStringParser(p, s, indent, 0, T_CONS_TYPE_ARG(etype, i));
02031 }
02032 if(T_CONS_ARITY(etype) == 1 && !lifted) {
02033 PRINT(p, s, "%s", ">");
02034 }
02035 }
02036 } else if(getNodeType(etype) == T_IRODS) {
02037 PRINT(p, s, "`%s`", etype->text);
02038 } else {
02039 PRINT(p, s, "%s", typeName_Parser(getNodeType(etype)));
02040 }
02041
02042 }
02043
02044 void ruleToString(char *buf, int size, RuleDesc *rd) {
02045 Node *node = rd->node;
02046 char **p = &buf;
02047 int *s = &size;
02048 Node *subt = NULL;
02049 switch(rd->ruleType) {
02050 case RK_REL:
02051 ruleNameToString(p, s, 0, node->subtrees[0]);
02052
02053 int indent;
02054 subt = node->subtrees[1];
02055 while(getNodeType(subt) == N_TUPLE && subt->degree == 1) {
02056 subt = subt->subtrees[0];
02057 }
02058
02059 PRINT(p, s, "%s", " ");
02060 if(getNodeType(subt) != TK_BOOL ||
02061 strcmp(subt->text, "true") != 0) {
02062 PRINT(p, s, "%s", "{\n");
02063 indentToString(p, s, 1);
02064 PRINT(p, s, "%s", "on ");
02065 termToString(p, s, 1, MIN_PREC, node->subtrees[1],0);
02066 PRINT(p, s, "%s", " ");
02067 indent = 1;
02068 } else {
02069 indent = 0;
02070 }
02071 actionsToString(p, s, indent, node->subtrees[2], node->subtrees[3]);
02072 if(indent == 1) {
02073 PRINT(p, s, "%s", "\n");
02074 indentToString(p, s, 1);
02075 metadataToString(p, s, 0, node->subtrees[4]);
02076 PRINT(p, s, "%s", "}\n");
02077 } else {
02078 PRINT(p, s, "%s", "\n");
02079 metadataToString(p, s, 0, node->subtrees[4]);
02080 }
02081 break;
02082 case RK_FUNC:
02083 ruleNameToString(p, s, 0, node->subtrees[0]);
02084 PRINT(p, s, "%s", " = ");
02085 termToString(p, s, 1, MIN_PREC, node->subtrees[2],0);
02086 PRINT(p, s, "%s", "\n");
02087 metadataToString(p, s, 0, node->subtrees[4]);
02088 break;
02089 case RK_CONSTRUCTOR:
02090 PRINT(p, s, "constructor %s", node->subtrees[0]->text);
02091 PRINT(p, s, "%s", " : ");
02092 typeToStringParser(p, s, 0, 0, node->subtrees[1]);
02093 PRINT(p, s, "%s", "\n");
02094
02095 break;
02096 case RK_DATA:
02097 PRINT(p, s, "%s ", "data");
02098 ruleNameToString(p, s, 0, node->subtrees[0]);
02099 PRINT(p, s, "%s", "\n");
02100 break;
02101 case RK_EXTERN:
02102 PRINT(p, s, "%s : ", node->subtrees[0]->text);
02103 typeToStringParser(p, s, 0, 0, node->subtrees[1]);
02104 PRINT(p, s, "%s", "\n");
02105 break;
02106
02107
02108 }
02109
02110 }
02111
02112 void functionApplicationToString(char *buf, int size, char *fn, Node **args, int n) {
02113 char **p = &buf;
02114 int *s = &size;
02115 PRINT(p, s, "%s(", fn);
02116 int i;
02117 char *res;
02118 for(i=0;i<n;i++) {
02119 switch(getNodeType(args[i])) {
02120 case N_VAL:
02121 res = convertResToString(args[i]);
02122 PRINT(p, s, "%s", res);
02123 free(res);
02124 break;
02125 case N_ACTIONS:
02126 actionsToString(p, s, 0, args[i], NULL);
02127 break;
02128 default:
02129 termToString(p, s, 0, MIN_PREC, args[i],0);
02130 }
02131 if(i != n-1) {
02132 PRINT(p, s, "%s", ", ");
02133 }
02134 }
02135 PRINT(p, s, "%s", ")");
02136 return;
02137 }
02138
02139 void printTreeDeref(Node *n, int indent, Hashtable *var_types, Region *r) {
02140 printIndent(indent);
02141 printf("%s:%d->",n->text, getNodeType(n));
02142 printType(n->coercionType, var_types);
02143 printf("\n");
02144 int i;
02145 for(i=0;i<n->degree;i++) {
02146 printTreeDeref(n->subtrees[i],indent+1, var_types, r);
02147 }
02148
02149 }
02150
02151 void printIndent(int n) {
02152 int i;
02153 for(i=0;i<n;i++) {
02154 printf("\t");
02155 }
02156 }
02157
02158 int eqExprNodeSyntactic(Node *a, Node *b) {
02159 if(getNodeType(a) == getNodeType(b) &&
02160 strcmp(a->text, b->text) == 0 &&
02161 a->degree == b->degree) {
02162 int i;
02163 for(i=0;i<a->degree;i++) {
02164 if(!eqExprNodeSyntactic(a->subtrees[i], b->subtrees[i])) {
02165 return 0;
02166 }
02167 }
02168 }
02169 return 1;
02170 }
02171 int eqExprNodeSyntacticVarMapping(Node *a, Node *b, Hashtable *varMapping ) {
02172 char *val;
02173 if(getNodeType(a) == TK_VAR && getNodeType(b) == TK_VAR &&
02174 (val = (char *)lookupFromHashTable(varMapping, a->text))!=NULL &&
02175 strcmp(val, b->text) == 0) {
02176 return 1;
02177 }
02178 if(getNodeType(a) == getNodeType(b) &&
02179 strcmp(a->text, b->text) == 0 &&
02180 a->degree == b->degree) {
02181 int i;
02182 for(i=0;i<a->degree;i++) {
02183 if(!eqExprNodeSyntactic(a->subtrees[i], b->subtrees[i])) {
02184 return 0;
02185 }
02186 }
02187 }
02188 return 1;
02189 }
02190
02191 StringList *getVarNamesInExprNode(Node *expr, Region *r) {
02192 return getVarNamesInExprNodeAux(expr, NULL, r);
02193 }
02194
02195 StringList *getVarNamesInExprNodeAux(Node *expr, StringList *vars, Region *r) {
02196 int i;
02197 switch(getNodeType(expr)) {
02198 case TK_VAR:
02199 if(expr->text[0] == '*') {
02200 StringList *nvars = (StringList*)region_alloc(r, sizeof(StringList));
02201 nvars->next = vars;
02202 nvars->str = expr->text;
02203 return nvars;
02204 }
02205
02206 default:
02207 for(i =0;i<expr->degree;i++) {
02208 vars = getVarNamesInExprNodeAux(expr->subtrees[i], vars, r);
02209 }
02210 return vars;
02211 }
02212 }
02213
02214
02215
02216 void nextChars(Pointer *p, int len) {
02217 int i;
02218 for(i=0;i<len;i++) {
02219 nextChar(p);
02220 }
02221 }
02222
02223
02224
02225
02226 int nextChar(Pointer *p) {
02227 if(p->isFile) {
02228 int ch = lookAhead(p, 1);
02229
02230 p->p++;
02231
02232 return ch;
02233 } else {
02234 if(p->strbuf[p->strp] == '\0') {
02235 return -1;
02236 }
02237 int ch = p->strbuf[++p->strp];
02238 if(ch == '\0') {
02239 ch = -1;
02240 }
02241 return ch;
02242 }
02243 }
02244
02245 Pointer *newPointer(FILE *fp, char *ruleBaseName) {
02246 Pointer *e = (Pointer *)malloc(sizeof(Pointer));
02247 initPointer(e, fp, ruleBaseName);
02248 return e;
02249 }
02250 Pointer *newPointer2(char* buf) {
02251 Pointer *e = (Pointer *)malloc(sizeof(Pointer));
02252 initPointer2(e, buf);
02253
02254 return e;
02255 }
02256 void deletePointer(Pointer* buf) {
02257 if(buf->isFile) {
02258 fclose(buf->fp);
02259 }
02260 free(buf->base);
02261 free(buf);
02262
02263 }
02264
02265 void initPointer(Pointer *p, FILE* fp, char* ruleBaseName ) {
02266 fseek(fp, 0, SEEK_SET);
02267 p->fp = fp;
02268 p->fpos = 0;
02269 p->len = 0;
02270 p->p = 0;
02271 p->isFile = 1;
02272 p->base = (char *)malloc(strlen(ruleBaseName)+2);
02273 p->base[0] = 'f';
02274 strcpy(p->base + 1, ruleBaseName);
02275 }
02276
02277 void initPointer2(Pointer *p, char *buf) {
02278 p->strbuf = buf;
02279 p->strlen = strlen(buf);
02280 p->strp = 0;
02281 p->isFile = 0;
02282 p->base = (char *)malloc(strlen(buf)+2);
02283 p->base[0] = 's';
02284 strcpy(p->base + 1, buf);
02285 }
02286
02287 void readToBuffer(Pointer *p) {
02288 if(p->isFile) {
02289 unsigned int move = (p->len+1)/2;
02290 move = move > p->p? p->p : move;
02291 int startpos = p->len - move;
02292 int load = POINTER_BUF_SIZE - startpos;
02293
02294 memmove(p->buf,p->buf+move,startpos*sizeof(char));
02295
02296 int count = fread(p->buf+startpos, sizeof(char), load, p->fp);
02297 p->len = startpos + count;
02298 p->p -= move;
02299 p->fpos += move * sizeof(char);
02300 } else {
02301 }
02302 }
02303
02304 void seekInFile(Pointer *p, unsigned long x) {
02305 if(p -> isFile) {
02306 if(p->fpos < x * sizeof(char) || p->fpos + p->len >= x * sizeof(char)) {
02307 fseek(p->fp, x * sizeof(char), SEEK_SET);
02308 clearBuffer(p);
02309 p->fpos = x * sizeof(char);
02310 readToBuffer(p);
02311 } else {
02312 p->p = x * sizeof(char) - p->fpos;
02313 }
02314 } else {
02315 p->strp = x;
02316 }
02317 }
02318
02319 void clearBuffer(Pointer *p) {
02320 if(p->isFile) {
02321 p->fpos += p->len * sizeof(char);
02322 p->len = p->p = 0;
02323 } else {
02324 }
02325 }
02326
02327
02328 int dupString(Pointer *p, Label * start, int n, char *buf) {
02329 if(p->isFile) {
02330 Label curr;
02331 getFPos(&curr, p, NULL);
02332 seekInFile(p, start->exprloc);
02333 int len = 0;
02334 int ch;
02335 while(len < n && (ch=lookAhead(p, 0)) != -1) {
02336 buf[len++] = (char) ch;
02337 nextChar(p);
02338 }
02339 buf[len] = '\0';
02340 seekInFile(p, curr.exprloc);
02341 return len;
02342 } else {
02343 int len = strlen(p->strbuf + start->exprloc);
02344 len = len > n ? n : len;
02345 memcpy(buf, p->strbuf + start->exprloc, len * sizeof(char));
02346 buf[len] = '\0';
02347 return len;
02348 }
02349 }
02350
02351 int dupLine(Pointer *p, Label * start, int n, char *buf) {
02352 Label pos;
02353 getFPos(&pos, p, NULL);
02354 seekInFile(p, 0);
02355 int len = 0;
02356 int i = 0;
02357 int ch = lookAhead(p, 0);
02358 while(ch != -1) {
02359 if(ch=='\n') {
02360 if(i<start->exprloc)
02361 len = 0;
02362 else {
02363 break;
02364 }
02365 } else {
02366 buf[len] = ch;
02367 len++;
02368 if(len == n - 1) {
02369 break;
02370 }
02371 }
02372 i++;
02373 ch = nextChar(p);
02374 }
02375 buf[len] = '\0';
02376 seekInFile(p, pos.exprloc);
02377 return len;
02378 }
02379
02380 void getCoor(Pointer *p, Label * errloc, int coor[2]) {
02381 Label pos;
02382 getFPos(&pos, p, NULL);
02383 seekInFile(p, 0);
02384 coor[0] = coor[1] = 0;
02385 int i;
02386 char ch = lookAhead(p, 0);
02387 for(i =0;i<errloc->exprloc;i++) {
02388 if(ch=='\n') {
02389 coor[0]++;
02390 coor[1] = 0;
02391 } else {
02392 coor[1]++;
02393 }
02394 ch = nextChar(p);
02395
02396
02397
02398 }
02399 seekInFile(p, pos.exprloc);
02400 }
02401
02402 int getLineRange(Pointer *p, int line, rodsLong_t range[2]) {
02403 Label pos;
02404 getFPos(&pos, p, NULL);
02405 seekInFile(p, 0);
02406 Label l;
02407 range[0] = range[1] = 0;
02408 int i = 0;
02409 int ch = lookAhead(p, 0);
02410 while (i < line && ch != -1) {
02411 if(ch=='\n') {
02412 i++;
02413 }
02414 ch = nextChar(p);
02415
02416
02417
02418 }
02419 if(ch == -1) {
02420 return -1;
02421 }
02422 range[0] = getFPos(&l, p, NULL)->exprloc;
02423 while (i == line && ch != -1) {
02424 if(ch=='\n') {
02425 i++;
02426 }
02427 ch = nextChar(p);
02428
02429
02430
02431 }
02432 range[1] = getFPos(&l, p, NULL)->exprloc;
02433 seekInFile(p, pos.exprloc);
02434 return 0;
02435 }
02436
02437 Label *getFPos(Label *l, Pointer *p, ParserContext *context) {
02438 if(context == NULL || context->tqtop == context->tqp) {
02439 if(p->isFile) {
02440 l->exprloc = p->fpos/sizeof(char) + p->p;
02441 } else {
02442 l->exprloc = p->strp;
02443 }
02444 } else {
02445 l->exprloc = context->tokenQueue[context->tqp].exprloc;
02446 }
02447 l->base = p->base;
02448 return l;
02449 }
02450
02451 int lookAhead(Pointer *p, unsigned int n) {
02452 if(p->isFile) {
02453 if(p->p+n >= p->len) {
02454 readToBuffer(p);
02455 if(p->p+n >= p->len) {
02456 return -1;
02457 }
02458 }
02459 return (int)(p->buf[p->p+n]);
02460 } else {
02461 if(n+p->strp >= p->strlen) {
02462 return -1;
02463 }
02464 return (int)p->strbuf[p->strp+n];
02465 }
02466
02467 }
02468
02469
02470 char *functionParameters(char *e, char *value) {
02471 int mode=0;
02472 int l0 = 0;
02473 while(*e!=0) {
02474 *value = *e;
02475 switch(mode) {
02476 case 0:
02477
02478 switch(*e) {
02479 case '(':
02480 l0++;
02481 break;
02482 case '\"':
02483 mode = 1;
02484 break;
02485 case '\'':
02486 mode = 2;
02487 break;
02488 case ')':
02489 l0--;
02490 if(l0==0) {
02491 value[1]='\0';
02492 return e+1;
02493 }
02494 }
02495 break;
02496 case 1:
02497 switch(*e) {
02498 case '\\':
02499 mode = 3;
02500 break;
02501 case '\"':
02502 mode = 0;
02503 }
02504 break;
02505 case 2:
02506 switch(*e) {
02507 case '\\':
02508 mode = 4;
02509 break;
02510 case '\'':
02511 mode = 0;
02512 }
02513 break;
02514 case 3:
02515 case 4:
02516 mode -= 2;
02517 }
02518 e++; value ++;
02519 }
02520 *value=0;
02521 return e;
02522 }
02523 char *nextStringString(char *e, char *value) {
02524 int mode=1;
02525 char* e0=e;
02526 char* value0=value;
02527 *value = *e;
02528 value++;
02529 e++;
02530 while(*e!=0) {
02531 *value = *e;
02532 switch(mode) {
02533 case 1:
02534 switch(*e) {
02535 case '\\':
02536 value--;
02537 mode = 3;
02538 break;
02539 case '\"':
02540 value[1]='\0';
02541 trimquotes(value0);
02542 return e+1;
02543 }
02544 break;
02545 case 3:
02546 mode -= 2;
02547 }
02548 e++; value ++;
02549 }
02550 return e0;
02551 }
02552 char *nextString2String(char *e, char *value) {
02553 int mode=1;
02554 char* e0=e;
02555 char* value0 = value;
02556 *value = *e;
02557 value ++;
02558 e++;
02559 while(*e!=0) {
02560 *value = *e;
02561 switch(mode) {
02562 case 1:
02563 switch(*e) {
02564 case '\\':
02565 value--;
02566 mode = 3;
02567 break;
02568 case '\'':
02569 value[1]='\0';
02570 trimquotes(value0);
02571 return e+1;
02572 }
02573 break;
02574 case 3:
02575 mode -= 2;
02576 }
02577 e++; value ++;
02578 }
02579 return e0;
02580 }
02581
02582
02583 char * nextRuleSection(char* buf, char* value) {
02584 char* e=buf;
02585 int mode=0;
02586 while(*e!=0) {
02587 *value = *e;
02588 switch(mode) {
02589 case 0:
02590
02591 switch(*e) {
02592 case '\"':
02593 mode = 1;
02594 break;
02595 case '\'':
02596 mode = 2;
02597 break;
02598 case '|':
02599 *value='\0';
02600 return e+1;
02601 }
02602 break;
02603 case 1:
02604 switch(*e) {
02605 case '\\':
02606 mode = 3;
02607 break;
02608 case '\"':
02609 mode = 0;
02610 }
02611 break;
02612 case 2:
02613 switch(*e) {
02614 case '\\':
02615 mode = 4;
02616 break;
02617 case '\'':
02618 mode = 0;
02619 }
02620 break;
02621 case 3:
02622 case 4:
02623 mode -= 2;
02624 }
02625 e++; value ++;
02626 }
02627 *value=0;
02628 return e;
02629
02630
02631 }
02632
02633 void nextActionArgumentStringBackwardCompatible(Pointer *e, Token *token) {
02634 skipWhitespace(e);
02635 Label start;
02636 token->exprloc = getFPos(&start, e, NULL)->exprloc;
02637 int ch = lookAhead(e, 0);
02638 if (ch==-1) {
02639 token->type = TK_EOS;
02640 strcpy(token->text,"EOS");
02641 } else {
02642 ch = lookAhead(e, 0);
02643 if(ch == '\"') {
02644 nextStringBase(e, token->text, "\"", 1, '\\', token->vars);
02645 skipWhitespace(e);
02646 } else if( ch == '\'') {
02647 nextStringBase(e, token->text, "\'", 1, '\\', token->vars);
02648 skipWhitespace(e);
02649 } else {
02650 nextStringParsed(e, token->text, "(", ")", ",|)", 0, token->vars);
02651
02652 int l0;
02653 l0 = strlen(token->text);
02654 while(isspace(token->text[l0-1])) {
02655 l0--;
02656 }
02657 token->text[l0++]='\0';
02658 }
02659 token->type = TK_STRING;
02660 }
02661 }
02662
02663 PARSER_FUNC_BEGIN(TypingConstraints)
02664 Hashtable *temp = context->symtable;
02665 context->symtable = newHashTable2(10, context->region);
02666 TRY(exec)
02667 NT(_TypingConstraints);
02668 FINALLY(exec)
02669 context->symtable = temp;
02670 END_TRY(exec)
02671
02672 PARSER_FUNC_END(TypingConstraints)
02673 PARSER_FUNC_BEGIN(Type)
02674 Hashtable *temp = context->symtable;
02675 context->symtable = newHashTable2(10, context->region);
02676 TRY(exec)
02677 NT2(_Type, 0, 0);
02678 FINALLY(exec)
02679 context->symtable = temp;
02680 END_TRY(exec)
02681 PARSER_FUNC_END(Type)
02682
02683 PARSER_FUNC_BEGIN(FuncType)
02684 Hashtable *temp = context->symtable;
02685 context->symtable = newHashTable2(10, context->region);
02686 TRY(exec)
02687 NT(_FuncType);
02688 OR(exec)
02689 NT2(_Type, 0, 0);
02690 BUILD_NODE(T_TUPLE, TUPLE, &start, 0, 0);
02691 SWAP;
02692 BUILD_NODE(T_CONS, FUNC, &start, 2, 2);
02693 FINALLY(exec)
02694 context->symtable = temp;
02695 END_TRY(exec)
02696 PARSER_FUNC_END(FuncType)
02697
02698 PARSER_FUNC_BEGIN2(_Type, int prec, int lifted)
02699 int rulegen = 1;
02700 int arity = 0;
02701 Node *node = NULL;
02702 TRY(type)
02703 ABORT(prec == 1);
02704 TRY(typeEnd)
02705 TTEXT_LOOKAHEAD("->");
02706 OR(typeEnd)
02707 TTEXT_LOOKAHEAD("=>");
02708 OR(typeEnd)
02709 TTEXT_LOOKAHEAD(")");
02710 OR(typeEnd)
02711 TTEXT_LOOKAHEAD(">");
02712 OR(typeEnd)
02713 TTYPE_LOOKAHEAD(TK_EOS);
02714 END_TRY(typeEnd)
02715 OR(type)
02716 LOOP_BEGIN(type)
02717 int cont = 0;
02718 Label vpos = *FPOS;
02719 TRY(type)
02720 TTYPE(TK_BACKQUOTED);
02721 BUILD_NODE(T_IRODS, token->text, &vpos, 0, 0);
02722 OR(type)
02723 TRY(typeVar)
02724 TTYPE(TK_INT);
02725 OR(typeVar)
02726 TTYPE(TK_TEXT);
02727 ABORT(!isupper(token->text[0]));
02728 END_TRY(typeVar)
02729 char *vname = cpStringExt(token->text, context->region);
02730
02731 Node *tvar;
02732 if ((tvar = (ExprType *) lookupFromHashTable(context->symtable, vname)) == NULL) {
02733 TRY(typeVarBound)
02734
02735 NT(TypeSet);
02736 OR(typeVarBound)
02737 BUILD_NODE(T_VAR, vname, &vpos, 0, 0);
02738 END_TRY(typeVarBound)
02739 tvar = POP;
02740 T_VAR_ID(tvar) = newTVarId();
02741 insertIntoHashTable(context->symtable, vname, tvar);
02742 }
02743 CASCADE(tvar);
02744 OR(type)
02745 TTEXT("?");
02746 CASCADE(newSimpType(T_DYNAMIC, context->region));
02747 OR(type)
02748 TTEXT2("integer", "int");
02749 CASCADE(newSimpType(T_INT, context->region));
02750 OR(type)
02751 TTEXT("double");
02752 CASCADE(newSimpType(T_DOUBLE, context->region));
02753 OR(type)
02754 TTEXT("boolean");
02755 CASCADE(newSimpType(T_BOOL, context->region));
02756 OR(type)
02757 TTEXT("time");
02758 CASCADE(newSimpType(T_DATETIME, context->region));
02759 OR(type)
02760 TTEXT("string");
02761 CASCADE(newSimpType(T_STRING, context->region));
02762 OR(type)
02763 TTEXT("list");
02764 NT2(_Type, 1, 0);
02765 BUILD_NODE(T_CONS, LIST, &vpos, 1, 1);
02766 Node *node = POP;
02767 setVararg(node, OPTION_VARARG_ONCE);
02768 PUSH(node);
02769 OR(type)
02770 TTEXT("unit");
02771 BUILD_NODE(T_TUPLE, TUPLE, &vpos, 0, 0);
02772 OR(type)
02773 TTEXT("(");
02774 NT2(_Type, 0, 0);
02775 TTEXT(")");
02776 OR(type)
02777 TTEXT("<")
02778 NT2(_Type, 0, 1);
02779 TTEXT(">");
02780 OR(type)
02781 TTEXT("forall");
02782 TTYPE(TK_TEXT);
02783 ABORT(!isupper(token->text[0]));
02784 char *vname = cpStringExt(token->text, context->region);
02785 TRY(typeVarBound)
02786 TTEXT("in");
02787 NT(TypeSet);
02788 OR(typeVarBound)
02789 BUILD_NODE(T_VAR, vname, &vpos, 0, 0);
02790 END_TRY(typeVarBound)
02791 Node *tvar = POP;
02792 T_VAR_ID(tvar) = newTVarId();
02793 TTEXT(",");
02794 insertIntoHashTable(context->symtable, vname, tvar);
02795 cont = 1;
02796 OR(type)
02797 TTEXT("f");
02798
02799 NT2(_Type, 1, 0);
02800 TRY(ftype)
02801 TTEXT("=>");
02802 NT2(_Type, 1, 0);
02803 BUILD_NODE(T_FIXD, NULL, &start, 2, 2);
02804 OR(ftype)
02805 BUILD_NODE(T_FLEX, NULL, &start, 1, 1);
02806 END_TRY(ftype);
02807
02808 OR(type)
02809 TTEXT2("output","o");
02810 NT2(_Type, 1, 0);
02811 node = POP;
02812 setIOType(node, IO_TYPE_OUTPUT);
02813 PUSH(node);
02814 OR(type)
02815 TTEXT2("input","i");
02816 NT2(_Type, 1, 0);
02817 node = POP;
02818 setIOType(node, IO_TYPE_INPUT | (getIOType(node) & IO_TYPE_OUTPUT));
02819 PUSH(node);
02820 OR(type)
02821 TTEXT2("expression","e");
02822 NT2(_Type, 1, 0);
02823 node = POP;
02824 setIOType(node, IO_TYPE_EXPRESSION);
02825 PUSH(node);
02826 OR(type)
02827 TTEXT2("actions","a");
02828 NT2(_Type, 1, 0);
02829 node = POP;
02830 setIOType(node, IO_TYPE_ACTIONS);
02831 PUSH(node);
02832 OR(type)
02833 TTEXT2("dynamic", "d");
02834 NT2(_Type, 1, 0);
02835 node = POP;
02836 setIOType(node, IO_TYPE_DYNAMIC);
02837 PUSH(node);
02838 OR(type)
02839 TTEXT("type");
02840 CASCADE(newSimpType(T_TYPE, context->region));
02841
02842 OR(type)
02843 TTEXT("set");
02844 CASCADE(newSimpType(T_TYPE, context->region));
02845
02846 OR(type)
02847 TTYPE(TK_TEXT);
02848 char *cons = cpStringExt(token->text, context->region);
02849
02850 int n = 0;
02851 OPTIONAL_BEGIN(argList)
02852 TTEXT("(");
02853 LOOP_BEGIN(args)
02854 NT2(_Type, 1, 0);
02855 n++;
02856 TRY(delim)
02857 TTEXT(",");
02858 OR(delim)
02859 DONE(args);
02860 END_TRY(delim)
02861 LOOP_END(args)
02862 TTEXT(")")
02863 OPTIONAL_END(argList)
02864 BUILD_NODE(T_CONS, cons, &start, n, n);
02865 END_TRY(type)
02866 if(!cont) {
02867 arity ++;
02868 TRY(typeEnd)
02869 ABORT(prec!=1);
02870 DONE(type);
02871 OR(typeEnd)
02872 TTYPE_LOOKAHEAD(TK_EOS);
02873 DONE(type);
02874 OR(typeEnd)
02875 TTEXT("*");
02876 TTEXT("->");
02877 PUSHBACK;
02878 PUSHBACK;
02879 DONE(type);
02880 OR(typeEnd)
02881 TTEXT("*");
02882 OR(typeEnd);
02883 DONE(type);
02884 END_TRY(typeEnd)
02885 }
02886 LOOP_END(type)
02887 END_TRY(type)
02888 if(arity != 1 || lifted) {
02889 BUILD_NODE(T_TUPLE, TUPLE, &start, arity, arity);
02890 }
02891 PARSER_FUNC_END(_Type)
02892
02893 PARSER_FUNC_BEGIN(TypeSet)
02894 int rulegen = 1;
02895 TTEXT("{");
02896 int n = 0;
02897 int done2 = 0;
02898 while (!done2 && NO_SYNTAX_ERROR) {
02899 NT2(_Type, 1, 0);
02900 n++;
02901 OPTIONAL_BEGIN(typeVarBoundEnd)
02902 TTEXT("}");
02903 done2 = 1;
02904 OPTIONAL_END(typeVarBoundEnd)
02905 }
02906 if(done2) {
02907 BUILD_NODE(T_VAR, NULL, &start, n, n);
02908 } else {
02909 break;
02910 }
02911 PARSER_FUNC_END(TypeSet)
02912
02913 PARSER_FUNC_BEGIN(_TypingConstraints)
02914 int rulegen = 1;
02915 TTEXT("{");
02916 int n = 0;
02917 LOOP_BEGIN(tc)
02918 Label pos2 = *FPOS;
02919 NT2(_Type, 0, 0);
02920 TTEXT("<=");
02921 NT2(_Type, 0, 0);
02922 BUILD_NODE(TC_LT, "", &pos2, 0, 0); /* node for generating error messages */
02923 BUILD_NODE(TC_LT, "<=", &pos2, 3, 3);
02924 n++;
02925 TRY(tce)
02926 TTEXT(",");
02927 OR(tce)
02928 TTEXT("}");
02929 DONE(tc);
02930 END_TRY(tce)
02931 LOOP_END(tc)
02932 BUILD_NODE(TC_SET, "{}", &start, n, n);
02933 PARSER_FUNC_END(TypingConstraints)
02934
02935 PARSER_FUNC_BEGIN(_FuncType)
02936 int rulegen = 1;
02937 int vararg = 0;
02938 NT2(_Type, 0, 1);
02939 TRY(vararg)
02940 TTEXT("*");
02941 vararg = OPTION_VARARG_STAR;
02942 OR(vararg)
02943 TTEXT("+");
02944 vararg = OPTION_VARARG_PLUS;
02945 OR(vararg)
02946 TTEXT("?");
02947 vararg = OPTION_VARARG_OPTIONAL;
02948 OR(vararg)
02949 vararg = OPTION_VARARG_ONCE;
02950 END_TRY(vararg)
02951 TTEXT("->");
02952 NT2(_Type, 0, 0);
02953 BUILD_NODE(T_CONS, FUNC, &start, 2, 2);
02954 Node *node = POP;
02955 setVararg(node, vararg);
02956 PUSH(node);
02957 PARSER_FUNC_END(_FuncType)
02958
02959 int parseRuleSet(Pointer *e, RuleSet *ruleSet, Env *funcDescIndex, int *errloc, rError_t *errmsg, Region *r) {
02960 char errbuf[ERR_MSG_LEN];
02961 Token *token;
02962 ParserContext *pc = newParserContext(errmsg, r);
02963
02964 int ret = 1;
02965 /* parser variables */
02966 int backwardCompatible = 0; /* 0 auto 1 true -1 false */
02967
02968 while(ret == 1) {
02969 pc->nodeStackTop = 0;
02970 pc->stackTopStackTop = 0;
02971 token = nextTokenRuleGen(e, pc, 1);
02972 switch(token->type) {
02973 case N_ERROR:
02974 return -1;
02975 case TK_EOS:
02976 ret = 0;
02977 continue;
02978 case TK_MISC_OP:
02979 case TK_TEXT:
02980 if(token->text[0] == '#') {
02981 skipComments(e);
02982 continue;
02983 } else if(token->text[0] == '@') { /* directive */
02984 token = nextTokenRuleGen(e, pc, 1);
02985 if(strcmp(token->text, "backwardCompatible")==0) {
02986 token = nextTokenRuleGen(e, pc, 1);
02987 if(token->type == TK_TEXT) {
02988 if(strcmp(token->text, "true")==0) {
02989 backwardCompatible = 1;
02990 } else if(strcmp(token->text, "false")==0) {
02991 backwardCompatible = -1;
02992 } else if(strcmp(token->text, "auto")==0) {
02993 backwardCompatible = 0;
02994 } else {
02995 /* todo error handling */
02996 }
02997 } else {
02998 /* todo error handling */
02999 }
03000 } else if(strcmp(token->text, "include")==0) {
03001 token = nextTokenRuleGen(e, pc, 1);
03002 if(token->type == TK_TEXT || token->type == TK_STRING) {
03003 CASCASE_NON_ZERO(readRuleSetFromFile(token->text, ruleSet, funcDescIndex, errloc, errmsg, r));
03004 } else {
03005 /* todo error handling */
03006 }
03007 } else {
03008 /* todo error handling */
03009 }
03010 continue;
03011 }
03012 break;
03013 default:
03014 break;
03015 }
03016 pushback(e, token, pc);
03017
03018 Node *node = parseRuleRuleGen(e, backwardCompatible, pc);
03019 if(node==NULL) {
03020 addRErrorMsg(errmsg, RE_OUT_OF_MEMORY, "parseRuleSet: out of memory.");
03021 return RE_OUT_OF_MEMORY;
03022 } else if(getNodeType(node) == N_ERROR) {
03023 *errloc = NODE_EXPR_POS(node);
03024 generateErrMsg("parseRuleSet: error parsing rule.", *errloc, e->base, errbuf);
03025 addRErrorMsg(errmsg, RE_PARSER_ERROR, errbuf);
03026 /* skip the current line and try to parse the rule from the next line */
03027 skipComments(e);
03028 return RE_PARSER_ERROR;
03029 } else {
03030 int n = node->degree;
03031 Node **nodes = node->subtrees;
03032 RuleType rk;
03033 /* if(strcmp(node->text, "UNPARSED") == 0) {
03034 pushRule(ruleSet, newRuleDesc(RK_UNPARSED, nodes[0], r));
03035 } else */ if(strcmp(node->text, "INDUCT") == 0) {
03036 int k;
03037 pushRule(ruleSet, newRuleDesc(RK_DATA, nodes[0], 0, r));
03038 for(k=1;k<n;k++) {
03039 if(lookupFromEnv(funcDescIndex, nodes[k]->subtrees[0]->text)!=NULL) {
03040 generateErrMsg("parseRuleSet: redefinition of constructor.", NODE_EXPR_POS(nodes[k]->subtrees[0]), nodes[k]->subtrees[0]->base, errbuf);
03041 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
03042 return RE_TYPE_ERROR;
03043 }
03044 insertIntoHashTable(funcDescIndex->current, nodes[k]->subtrees[0]->text, newConstructorFD2(nodes[k]->subtrees[1], r));
03045 pushRule(ruleSet, newRuleDesc(RK_CONSTRUCTOR, nodes[k], 0, r));
03046 }
03047 } else if(strcmp(node->text, "CONSTR") == 0) {
03048 if(lookupFromEnv(funcDescIndex, nodes[0]->subtrees[0]->text)!=NULL) {
03049 generateErrMsg("parseRuleSet: redefinition of constructor.", NODE_EXPR_POS(nodes[0]->subtrees[0]), nodes[0]->subtrees[0]->base, errbuf);
03050 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
03051 return RE_TYPE_ERROR;
03052 }
03053 insertIntoHashTable(funcDescIndex->current, nodes[0]->subtrees[0]->text, newConstructorFD2(nodes[0]->subtrees[1], r));
03054 pushRule(ruleSet, newRuleDesc(RK_CONSTRUCTOR, nodes[0], 0, r));
03055 } else if(strcmp(node->text, "EXTERN") == 0) {
03056 FunctionDesc *fd;
03057 if((fd = (FunctionDesc *) lookupFromEnv(funcDescIndex, nodes[0]->subtrees[0]->text))!=NULL) {
03058 generateErrMsg("parseRuleSet: redefinition of function.", NODE_EXPR_POS(nodes[0]->subtrees[0]), nodes[0]->subtrees[0]->base, errbuf);
03059 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
03060 return RE_TYPE_ERROR;
03061 }
03062 insertIntoHashTable(funcDescIndex->current, nodes[0]->subtrees[0]->text, newExternalFD(nodes[0]->subtrees[1], r));
03063 pushRule(ruleSet, newRuleDesc(RK_EXTERN, nodes[0], 0, r));
03064 } else {
03065 int notyping;
03066 if(strcmp(node->text, "REL")==0) {
03067 rk = RK_REL;
03068 notyping = backwardCompatible >= 0 ? 1 : 0;
03069 } else if(strcmp(node->text, "FUNC")==0) {
03070 rk = RK_FUNC;
03071 notyping = 0;
03072 }
03073 int k;
03074 for(k=0;k<n;k++) {
03075 Node *node = nodes[k];
03076 pushRule(ruleSet, newRuleDesc(rk, node, notyping, r));
03077 /* printf("%s\n", node->subtrees[0]->text);
03078 printTree(node, 0); */
03079 }
03080 }
03081 }
03082 }
03083 deleteParserContext(pc);
03084 return 0;
03085 }
03086
03087 /*
03088 * parse the string for an ExprType
03089 * supported types:
03090 * ? dynamic
03091 * i integer
03092 * b boolean
03093 * d double
03094 * t time
03095 * s string
03096 * list <type> list
03097 * f <type> flexible
03098 * <var> ({ <type> ... <type> })? variable
03099 * <type> * ... * <type> product
03100 * < <type> * ... * <type> > lifted product
03101 * `irods PI` irods
03102 *
03103 * <type> (*|+|?)? -> <type> function
03104 * forall <var> (in { <type> ... <type> })?, <type> universal
03105 */
03106 Node* parseFuncTypeFromString(char *string, Region *r) {
03107 Pointer *p = newPointer2(string);
03108 ParserContext *pc = newParserContext(NULL, r);
03109 nextRuleGenFuncType(p, pc);
03110 Node *exprType = pc->nodeStack[0];
03111 deleteParserContext(pc);
03112 deletePointer(p);
03113 return exprType;
03114 }
03115 Node* parseTypingConstraintsFromString(char *string, Region *r) {
03116 Pointer *p = newPointer2(string);
03117 ParserContext *pc = newParserContext(NULL, r);
03118 nextRuleGenTypingConstraints(p, pc);
03119 Node *exprType = pc->nodeStack[0];
03120 /*char buf[ERR_MSG_LEN];
03121 errMsgToString(pc->errmsg, buf, ERR_MSG_LEN);
03122 printf("%s", buf);*/
03123 deleteParserContext(pc);
03124 deletePointer(p);
03125 return exprType;
03126 }
03127 Node *parseRuleRuleGen(Pointer *expr, int backwardCompatible, ParserContext *pc) {
03128 nextRuleGenRule(expr, pc, backwardCompatible);
03129 Node *rulePackNode = pc->nodeStack[0];
03130 if(pc->error) {
03131 if(pc->errnode!=NULL) {
03132 rulePackNode =pc->errnode;
03133 } else {
03134 rulePackNode =createErrorNode("parser error", &pc->errloc, pc->region);
03135 }
03136 }
03137 return rulePackNode;
03138 }
03139 Node *parseTermRuleGen(Pointer *expr, int rulegen, ParserContext *pc) {
03140 nextRuleGenTerm(expr, pc, rulegen, 0);
03141 Node *rulePackNode = pc->nodeStack[0];
03142 if(pc->error) {
03143 if(pc->errnode!=NULL) {
03144 rulePackNode =pc->errnode;
03145 } else {
03146 rulePackNode =createErrorNode("parser error", &pc->errloc, pc->region);
03147 }
03148 }
03149
03150 return rulePackNode;
03151
03152 }
03153 Node *parseActionsRuleGen(Pointer *expr, int rulegen, int backwardCompatible, ParserContext *pc) {
03154 nextRuleGenActions(expr, pc, rulegen, backwardCompatible);
03155 Node *rulePackNode = pc->nodeStack[0];
03156 if(pc->error) {
03157 if(pc->errnode!=NULL) {
03158 rulePackNode =pc->errnode;
03159 } else {
03160 rulePackNode =createErrorNode("parser error", &pc->errloc, pc->region);
03161 }
03162 }
03163
03164 return rulePackNode;
03165
03166 }
03167 char* typeName_Res(Res *s) {
03168 return typeName_ExprType(s->exprType);
03169 }
03170
03171 char* typeName_ExprType(ExprType *s) {
03172 switch(getNodeType(s)) {
03173 case T_IRODS:
03174 return s->text;
03175 default:
03176 return typeName_NodeType(getNodeType(s));
03177 }
03178 }
03179
03180 char* typeName_Parser(NodeType s) {
03181 switch(s) {
03182 case T_IRODS:
03183 return "IRODS";
03184 case T_VAR:
03185 return "VAR";
03186 case T_DYNAMIC:
03187 return "?";
03188 case T_CONS:
03189 return "CONS";
03190 case T_FLEX:
03191 return "f";
03192 case T_FIXD:
03193 return "f";
03194 case T_BOOL:
03195 return "boolean";
03196 case T_INT:
03197 return "integer";
03198 case T_DOUBLE:
03199 return "double";
03200 case T_STRING:
03201 return "string";
03202 case T_ERROR:
03203 return "ERROR";
03204 case T_DATETIME:
03205 return "time";
03206 case T_TYPE:
03207 return "set";
03208 case T_TUPLE:
03209 return "TUPLE";
03210 default:
03211 return "OTHER";
03212 }
03213 }
03214
03215 char* typeName_NodeType(NodeType s) {
03216 switch(s) {
03217 case T_IRODS:
03218 return "IRODS";
03219 case T_VAR:
03220 return "VAR";
03221 case T_DYNAMIC:
03222 return "DYNAMIC";
03223 case T_CONS:
03224 return "CONS";
03225 case T_FLEX:
03226 return "FLEX";
03227 case T_FIXD:
03228 return "FIXD";
03229 case T_BOOL:
03230 return "BOOLEAN";
03231 case T_INT:
03232 return "INTEGER";
03233 case T_DOUBLE:
03234 return "DOUBLE";
03235 case T_STRING:
03236 return "STRING";
03237 case T_ERROR:
03238 return "ERROR";
03239 case T_DATETIME:
03240 return "DATETIME";
03241 case T_TYPE:
03242 return "TYPE";
03243 case T_TUPLE:
03244 return "TUPLE";
03245 default:
03246 return "OTHER";
03247 }
03248 }
03249
03250 void generateErrMsgFromFile(char *msg, long errloc, char *ruleBaseName, char* ruleBasePath, char errbuf[ERR_MSG_LEN]) {
03251 FILE *fp = fopen(ruleBasePath, "r");
03252 Pointer *e = newPointer(fp, ruleBaseName);
03253 Label l;
03254 l.base = NULL;
03255 l.exprloc = errloc;
03256 generateErrMsgFromPointer(msg, &l, e, errbuf);
03257 deletePointer(e);
03258 }
03259
03260 void generateErrMsgFromSource(char *msg, long errloc, char *src, char errbuf[ERR_MSG_LEN]) {
03261 Pointer *e = newPointer2(src);
03262 Label l;
03263 l.base = NULL;
03264 l.exprloc = errloc;
03265 generateErrMsgFromPointer(msg, &l, e, errbuf);
03266 deletePointer(e);
03267 }
03268 void generateErrMsgFromPointer(char *msg, Label *l, Pointer *e, char errbuf[ERR_MSG_LEN]) {
03269 char buf[ERR_MSG_LEN];
03270 dupLine(e, l, ERR_MSG_LEN, buf);
03271 int len = strlen(buf);
03272 int coor[2];
03273 getCoor(e, l, coor);
03274 int i;
03275 if(len < ERR_MSG_LEN - 1) {
03276 buf[len++] = '\n';
03277 }
03278 for(i=0;i<coor[1];i++) {
03279 if(len >= ERR_MSG_LEN - 1) {
03280 break;
03281 }
03282 buf[len++] = buf[i] == '\t'?'\t':' ';
03283 }
03284 if(len < ERR_MSG_LEN - 2) {
03285 buf[len++] = '^';
03286 }
03287 buf[len++] = '\0';
03288 if(e->isFile)
03289 snprintf(errbuf, ERR_MSG_LEN,
03290 "%s\nline %d, col %d, rule base %s\n%s\n", msg, coor[0], coor[1], e->base+1, buf);
03291 else
03292 snprintf(errbuf, ERR_MSG_LEN,
03293 "%s\nline %d, col %d\n%s\n", msg, coor[0], coor[1], buf);
03294
03295 }
03296 void generateAndAddErrMsg(char *msg, Node *node, int errcode, rError_t *errmsg) {
03297 char errmsgBuf[ERR_MSG_LEN];
03298 generateErrMsg(msg, NODE_EXPR_POS(node), node->base, errmsgBuf);
03299 addRErrorMsg(errmsg, errcode, errmsgBuf);
03300 }
03301 char *generateErrMsg(char *msg, long errloc, char *ruleBaseName, char errmsg[ERR_MSG_LEN]) {
03302 char ruleBasePath[MAX_NAME_LEN];
03303 switch(ruleBaseName[0]) {
03304 case 's': // source
03305 generateErrMsgFromSource(msg, errloc, ruleBaseName + 1, errmsg);
03306 return errmsg;
03307 case 'f': // file
03308 getRuleBasePath(ruleBaseName + 1, ruleBasePath);
03309 generateErrMsgFromFile(msg, errloc, ruleBaseName + 1, ruleBasePath, errmsg);
03310 return errmsg;
03311 default:
03312 snprintf(errmsg, ERR_MSG_LEN, "<unknown source type>");
03313 return errmsg;
03314 }
03315 }