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