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 void printTreeDeref(Node *n, int indent, Hashtable *var_types, Region *r) {
02216 printIndent(indent);
02217 printf("%s:%d->",n->text, getNodeType(n));
02218 printType(n->coercionType, var_types);
02219 printf("\n");
02220 int i;
02221 for(i=0;i<n->degree;i++) {
02222 printTreeDeref(n->subtrees[i],indent+1, var_types, r);
02223 }
02224
02225 }
02226
02227 void printIndent(int n) {
02228 int i;
02229 for(i=0;i<n;i++) {
02230 printf("\t");
02231 }
02232 }
02233
02234 int eqExprNodeSyntactic(Node *a, Node *b) {
02235 if(getNodeType(a) == getNodeType(b) &&
02236 strcmp(a->text, b->text) == 0 &&
02237 a->degree == b->degree) {
02238 int i;
02239 for(i=0;i<a->degree;i++) {
02240 if(!eqExprNodeSyntactic(a->subtrees[i], b->subtrees[i])) {
02241 return 0;
02242 }
02243 }
02244 }
02245 return 1;
02246 }
02247 int eqExprNodeSyntacticVarMapping(Node *a, Node *b, Hashtable *varMapping ) {
02248 char *val;
02249 if(getNodeType(a) == TK_VAR && getNodeType(b) == TK_VAR &&
02250 (val = (char *)lookupFromHashTable(varMapping, a->text))!=NULL &&
02251 strcmp(val, b->text) == 0) {
02252 return 1;
02253 }
02254 if(getNodeType(a) == getNodeType(b) &&
02255 strcmp(a->text, b->text) == 0 &&
02256 a->degree == b->degree) {
02257 int i;
02258 for(i=0;i<a->degree;i++) {
02259 if(!eqExprNodeSyntactic(a->subtrees[i], b->subtrees[i])) {
02260 return 0;
02261 }
02262 }
02263 }
02264 return 1;
02265 }
02266
02267 StringList *getVarNamesInExprNode(Node *expr, Region *r) {
02268 return getVarNamesInExprNodeAux(expr, NULL, r);
02269 }
02270
02271 StringList *getVarNamesInExprNodeAux(Node *expr, StringList *vars, Region *r) {
02272 int i;
02273 switch(getNodeType(expr)) {
02274 case TK_VAR:
02275 if(expr->text[0] == '*') {
02276 StringList *nvars = (StringList*)region_alloc(r, sizeof(StringList));
02277 nvars->next = vars;
02278 nvars->str = expr->text;
02279 return nvars;
02280 }
02281
02282 default:
02283 for(i =0;i<expr->degree;i++) {
02284 vars = getVarNamesInExprNodeAux(expr->subtrees[i], vars, r);
02285 }
02286 return vars;
02287 }
02288 }
02289
02290
02291
02292 void nextChars(Pointer *p, int len) {
02293 int i;
02294 for(i=0;i<len;i++) {
02295 nextChar(p);
02296 }
02297 }
02298
02299
02300
02301
02302 int nextChar(Pointer *p) {
02303 if(p->isFile) {
02304 int ch = lookAhead(p, 1);
02305
02306 p->p++;
02307
02308 return ch;
02309 } else {
02310 if(p->strbuf[p->strp] == '\0') {
02311 return -1;
02312 }
02313 int ch = p->strbuf[++p->strp];
02314 if(ch == '\0') {
02315 ch = -1;
02316 }
02317 return ch;
02318 }
02319 }
02320
02321 Pointer *newPointer(FILE *fp, char *ruleBaseName) {
02322 Pointer *e = (Pointer *)malloc(sizeof(Pointer));
02323 initPointer(e, fp, ruleBaseName);
02324 return e;
02325 }
02326 Pointer *newPointer2(char* buf) {
02327 Pointer *e = (Pointer *)malloc(sizeof(Pointer));
02328 initPointer2(e, buf);
02329
02330 return e;
02331 }
02332 void deletePointer(Pointer* buf) {
02333 if(buf->isFile) {
02334 fclose(buf->fp);
02335 }
02336 free(buf->base);
02337 free(buf);
02338
02339 }
02340
02341 void initPointer(Pointer *p, FILE* fp, char* ruleBaseName ) {
02342 fseek(fp, 0, SEEK_SET);
02343 p->fp = fp;
02344 p->fpos = 0;
02345 p->len = 0;
02346 p->p = 0;
02347 p->isFile = 1;
02348 p->base = (char *)malloc(strlen(ruleBaseName)+2);
02349 p->base[0] = 'f';
02350 strcpy(p->base + 1, ruleBaseName);
02351 }
02352
02353 void initPointer2(Pointer *p, char *buf) {
02354 p->strbuf = buf;
02355 p->strlen = strlen(buf);
02356 p->strp = 0;
02357 p->isFile = 0;
02358 p->base = (char *)malloc(strlen(buf)+2);
02359 p->base[0] = 's';
02360 strcpy(p->base + 1, buf);
02361 }
02362
02363 void readToBuffer(Pointer *p) {
02364 if(p->isFile) {
02365 unsigned int move = (p->len+1)/2;
02366 move = move > p->p? p->p : move;
02367 int startpos = p->len - move;
02368 int load = POINTER_BUF_SIZE - startpos;
02369
02370 memmove(p->buf,p->buf+move,startpos*sizeof(char));
02371
02372 int count = fread(p->buf+startpos, sizeof(char), load, p->fp);
02373 p->len = startpos + count;
02374 p->p -= move;
02375 p->fpos += move * sizeof(char);
02376 } else {
02377 }
02378 }
02379
02380 void seekInFile(Pointer *p, unsigned long x) {
02381 if(p -> isFile) {
02382 if(p->fpos < x * sizeof(char) || p->fpos + p->len >= x * sizeof(char)) {
02383 fseek(p->fp, x * sizeof(char), SEEK_SET);
02384 clearBuffer(p);
02385 p->fpos = x * sizeof(char);
02386 readToBuffer(p);
02387 } else {
02388 p->p = x * sizeof(char) - p->fpos;
02389 }
02390 } else {
02391 p->strp = x;
02392 }
02393 }
02394
02395 void clearBuffer(Pointer *p) {
02396 if(p->isFile) {
02397 p->fpos += p->len * sizeof(char);
02398 p->len = p->p = 0;
02399 } else {
02400 }
02401 }
02402
02403
02404 int dupString(Pointer *p, Label * start, int n, char *buf) {
02405 if(p->isFile) {
02406 Label curr;
02407 getFPos(&curr, p, NULL);
02408 seekInFile(p, start->exprloc);
02409 int len = 0;
02410 int ch;
02411 while(len < n && (ch=lookAhead(p, 0)) != -1) {
02412 buf[len++] = (char) ch;
02413 nextChar(p);
02414 }
02415 buf[len] = '\0';
02416 seekInFile(p, curr.exprloc);
02417 return len;
02418 } else {
02419 int len = strlen(p->strbuf + start->exprloc);
02420 len = len > n ? n : len;
02421 memcpy(buf, p->strbuf + start->exprloc, len * sizeof(char));
02422 buf[len] = '\0';
02423 return len;
02424 }
02425 }
02426
02427 int dupLine(Pointer *p, Label * start, int n, char *buf) {
02428 Label pos;
02429 getFPos(&pos, p, NULL);
02430 seekInFile(p, 0);
02431 int len = 0;
02432 int i = 0;
02433 int ch = lookAhead(p, 0);
02434 while(ch != -1) {
02435 if(ch=='\n') {
02436 if(i<start->exprloc)
02437 len = 0;
02438 else {
02439 break;
02440 }
02441 } else {
02442 buf[len] = ch;
02443 len++;
02444 if(len == n - 1) {
02445 break;
02446 }
02447 }
02448 i++;
02449 ch = nextChar(p);
02450 }
02451 buf[len] = '\0';
02452 seekInFile(p, pos.exprloc);
02453 return len;
02454 }
02455
02456 void getCoor(Pointer *p, Label * errloc, int coor[2]) {
02457 Label pos;
02458 getFPos(&pos, p, NULL);
02459 seekInFile(p, 0);
02460 coor[0] = coor[1] = 0;
02461 int i;
02462 char ch = lookAhead(p, 0);
02463 for(i =0;i<errloc->exprloc;i++) {
02464 if(ch=='\n') {
02465 coor[0]++;
02466 coor[1] = 0;
02467 } else {
02468 coor[1]++;
02469 }
02470 ch = nextChar(p);
02471
02472
02473
02474 }
02475 seekInFile(p, pos.exprloc);
02476 }
02477
02478 int getLineRange(Pointer *p, int line, rodsLong_t range[2]) {
02479 Label pos;
02480 getFPos(&pos, p, NULL);
02481 seekInFile(p, 0);
02482 Label l;
02483 range[0] = range[1] = 0;
02484 int i = 0;
02485 int ch = lookAhead(p, 0);
02486 while (i < line && ch != -1) {
02487 if(ch=='\n') {
02488 i++;
02489 }
02490 ch = nextChar(p);
02491
02492
02493
02494 }
02495 if(ch == -1) {
02496 return -1;
02497 }
02498 range[0] = getFPos(&l, p, NULL)->exprloc;
02499 while (i == line && ch != -1) {
02500 if(ch=='\n') {
02501 i++;
02502 }
02503 ch = nextChar(p);
02504
02505
02506
02507 }
02508 range[1] = getFPos(&l, p, NULL)->exprloc;
02509 seekInFile(p, pos.exprloc);
02510 return 0;
02511 }
02512
02513 Label *getFPos(Label *l, Pointer *p, ParserContext *context) {
02514 if(context == NULL || context->tqtop == context->tqp) {
02515 if(p->isFile) {
02516 l->exprloc = p->fpos/sizeof(char) + p->p;
02517 } else {
02518 l->exprloc = p->strp;
02519 }
02520 } else {
02521 l->exprloc = context->tokenQueue[context->tqp].exprloc;
02522 }
02523 l->base = p->base;
02524 return l;
02525 }
02526
02527 int lookAhead(Pointer *p, unsigned int n) {
02528 if(p->isFile) {
02529 if(p->p+n >= p->len) {
02530 readToBuffer(p);
02531 if(p->p+n >= p->len) {
02532 return -1;
02533 }
02534 }
02535 return (int)(p->buf[p->p+n]);
02536 } else {
02537 if(n+p->strp >= p->strlen) {
02538 return -1;
02539 }
02540 return (int)p->strbuf[p->strp+n];
02541 }
02542
02543 }
02544
02545
02546 char *functionParameters(char *e, char *value) {
02547 int mode=0;
02548 int l0 = 0;
02549 while(*e!=0) {
02550 *value = *e;
02551 switch(mode) {
02552 case 0:
02553
02554 switch(*e) {
02555 case '(':
02556 l0++;
02557 break;
02558 case '\"':
02559 mode = 1;
02560 break;
02561 case '\'':
02562 mode = 2;
02563 break;
02564 case ')':
02565 l0--;
02566 if(l0==0) {
02567 value[1]='\0';
02568 return e+1;
02569 }
02570 }
02571 break;
02572 case 1:
02573 switch(*e) {
02574 case '\\':
02575 mode = 3;
02576 break;
02577 case '\"':
02578 mode = 0;
02579 }
02580 break;
02581 case 2:
02582 switch(*e) {
02583 case '\\':
02584 mode = 4;
02585 break;
02586 case '\'':
02587 mode = 0;
02588 }
02589 break;
02590 case 3:
02591 case 4:
02592 mode -= 2;
02593 }
02594 e++; value ++;
02595 }
02596 *value=0;
02597 return e;
02598 }
02599 char *nextStringString(char *e, char *value) {
02600 int mode=1;
02601 char* e0=e;
02602 char* value0=value;
02603 *value = *e;
02604 value++;
02605 e++;
02606 while(*e!=0) {
02607 *value = *e;
02608 switch(mode) {
02609 case 1:
02610 switch(*e) {
02611 case '\\':
02612 value--;
02613 mode = 3;
02614 break;
02615 case '\"':
02616 value[1]='\0';
02617 trimquotes(value0);
02618 return e+1;
02619 }
02620 break;
02621 case 3:
02622 mode -= 2;
02623 }
02624 e++; value ++;
02625 }
02626 return e0;
02627 }
02628 char *nextString2String(char *e, char *value) {
02629 int mode=1;
02630 char* e0=e;
02631 char* value0 = value;
02632 *value = *e;
02633 value ++;
02634 e++;
02635 while(*e!=0) {
02636 *value = *e;
02637 switch(mode) {
02638 case 1:
02639 switch(*e) {
02640 case '\\':
02641 value--;
02642 mode = 3;
02643 break;
02644 case '\'':
02645 value[1]='\0';
02646 trimquotes(value0);
02647 return e+1;
02648 }
02649 break;
02650 case 3:
02651 mode -= 2;
02652 }
02653 e++; value ++;
02654 }
02655 return e0;
02656 }
02657
02658
02659 char * nextRuleSection(char* buf, char* value) {
02660 char* e=buf;
02661 int mode=0;
02662 while(*e!=0) {
02663 *value = *e;
02664 switch(mode) {
02665 case 0:
02666
02667 switch(*e) {
02668 case '\"':
02669 mode = 1;
02670 break;
02671 case '\'':
02672 mode = 2;
02673 break;
02674 case '|':
02675 *value='\0';
02676 return e+1;
02677 }
02678 break;
02679 case 1:
02680 switch(*e) {
02681 case '\\':
02682 mode = 3;
02683 break;
02684 case '\"':
02685 mode = 0;
02686 }
02687 break;
02688 case 2:
02689 switch(*e) {
02690 case '\\':
02691 mode = 4;
02692 break;
02693 case '\'':
02694 mode = 0;
02695 }
02696 break;
02697 case 3:
02698 case 4:
02699 mode -= 2;
02700 }
02701 e++; value ++;
02702 }
02703 *value=0;
02704 return e;
02705
02706
02707 }
02708
02709 void nextActionArgumentStringBackwardCompatible(Pointer *e, Token *token) {
02710 skipWhitespace(e);
02711 Label start;
02712 token->exprloc = getFPos(&start, e, NULL)->exprloc;
02713 int ch = lookAhead(e, 0);
02714 if (ch==-1) {
02715 token->type = TK_EOS;
02716 strcpy(token->text,"EOS");
02717 } else {
02718 ch = lookAhead(e, 0);
02719 if(ch == '\"') {
02720 nextStringBase(e, token->text, "\"", 1, '\\', 1, token->vars);
02721 skipWhitespace(e);
02722 } else if( ch == '\'') {
02723 nextStringBase(e, token->text, "\'", 1, '\\', 1, token->vars);
02724 skipWhitespace(e);
02725 } else {
02726 nextStringParsed(e, token->text, "(", ")", ",|)", 0, token->vars);
02727
02728 int l0;
02729 l0 = strlen(token->text);
02730 while(isspace(token->text[l0-1])) {
02731 l0--;
02732 }
02733 token->text[l0++]='\0';
02734 }
02735 token->type = TK_STRING;
02736 }
02737 }
02738
02739 PARSER_FUNC_BEGIN(TypingConstraints)
02740 Hashtable *temp = context->symtable;
02741 context->symtable = newHashTable2(10, context->region);
02742 TRY(exec)
02743 NT(_TypingConstraints);
02744 FINALLY(exec)
02745 context->symtable = temp;
02746 END_TRY(exec)
02747
02748 PARSER_FUNC_END(TypingConstraints)
02749 PARSER_FUNC_BEGIN(Type)
02750 Hashtable *temp = context->symtable;
02751 context->symtable = newHashTable2(10, context->region);
02752 TRY(exec)
02753 NT2(_Type, 0, 0);
02754 FINALLY(exec)
02755 context->symtable = temp;
02756 END_TRY(exec)
02757 PARSER_FUNC_END(Type)
02758
02759 PARSER_FUNC_BEGIN(FuncType)
02760 Hashtable *temp = context->symtable;
02761 context->symtable = newHashTable2(10, context->region);
02762 TRY(exec)
02763 NT(_FuncType);
02764 OR(exec)
02765 NT2(_Type, 0, 0);
02766 BUILD_NODE(T_TUPLE, TUPLE, &start, 0, 0);
02767 SWAP;
02768 BUILD_NODE(T_CONS, FUNC, &start, 2, 2);
02769 FINALLY(exec)
02770 context->symtable = temp;
02771 END_TRY(exec)
02772 PARSER_FUNC_END(FuncType)
02773
02774 PARSER_FUNC_BEGIN2(_Type, int prec, int lifted)
02775 int rulegen = 1;
02776 int arity = 0;
02777 Node *node = NULL;
02778 TRY(type)
02779 ABORT(prec == 1);
02780 TRY(typeEnd)
02781 TTEXT_LOOKAHEAD("->");
02782 OR(typeEnd)
02783 TTEXT_LOOKAHEAD("=>");
02784 OR(typeEnd)
02785 TTEXT_LOOKAHEAD(")");
02786 OR(typeEnd)
02787 TTEXT_LOOKAHEAD(">");
02788 OR(typeEnd)
02789 TTYPE_LOOKAHEAD(TK_EOS);
02790 END_TRY(typeEnd)
02791 OR(type)
02792 LOOP_BEGIN(type)
02793 int cont = 0;
02794 Label vpos = *FPOS;
02795 TRY(type)
02796 TTYPE(TK_BACKQUOTED);
02797 BUILD_NODE(T_IRODS, token->text, &vpos, 0, 0);
02798 OR(type)
02799 TRY(typeVar)
02800 TTYPE(TK_INT);
02801 OR(typeVar)
02802 TTYPE(TK_TEXT);
02803 ABORT(!isupper(token->text[0]));
02804 END_TRY(typeVar)
02805 char *vname = cpStringExt(token->text, context->region);
02806
02807 Node *tvar;
02808 if ((tvar = (ExprType *) lookupFromHashTable(context->symtable, vname)) == NULL) {
02809 TRY(typeVarBound)
02810
02811 NT(TypeSet);
02812 OR(typeVarBound)
02813 BUILD_NODE(T_VAR, vname, &vpos, 0, 0);
02814 END_TRY(typeVarBound)
02815 tvar = POP;
02816 T_VAR_ID(tvar) = newTVarId();
02817 insertIntoHashTable(context->symtable, vname, tvar);
02818 }
02819 CASCADE(tvar);
02820 OR(type)
02821 TTEXT("?");
02822 CASCADE(newSimpType(T_DYNAMIC, context->region));
02823 OR(type)
02824 TTEXT2("integer", "int");
02825 CASCADE(newSimpType(T_INT, context->region));
02826 OR(type)
02827 TTEXT("double");
02828 CASCADE(newSimpType(T_DOUBLE, context->region));
02829 OR(type)
02830 TTEXT("boolean");
02831 CASCADE(newSimpType(T_BOOL, context->region));
02832 OR(type)
02833 TTEXT("time");
02834 CASCADE(newSimpType(T_DATETIME, context->region));
02835 OR(type)
02836 TTEXT("string");
02837 CASCADE(newSimpType(T_STRING, context->region));
02838 OR(type)
02839 TTEXT("path");
02840 CASCADE(newSimpType(T_PATH, context->region));
02841 OR(type)
02842 TTEXT("list");
02843 NT2(_Type, 1, 0);
02844 BUILD_NODE(T_CONS, LIST, &vpos, 1, 1);
02845 Node *node = POP;
02846 setVararg(node, OPTION_VARARG_ONCE);
02847 PUSH(node);
02848 OR(type)
02849 TTEXT("unit");
02850 BUILD_NODE(T_TUPLE, TUPLE, &vpos, 0, 0);
02851 OR(type)
02852 TTEXT("(");
02853 NT2(_Type, 0, 0);
02854 TTEXT(")");
02855 OR(type)
02856 TTEXT("<")
02857 NT2(_Type, 0, 1);
02858 TTEXT(">");
02859 OR(type)
02860 TTEXT("forall");
02861 TTYPE(TK_TEXT);
02862 ABORT(!isupper(token->text[0]));
02863 char *vname = cpStringExt(token->text, context->region);
02864 TRY(typeVarBound)
02865 TTEXT("in");
02866 NT(TypeSet);
02867 OR(typeVarBound)
02868 BUILD_NODE(T_VAR, vname, &vpos, 0, 0);
02869 END_TRY(typeVarBound)
02870 Node *tvar = POP;
02871 T_VAR_ID(tvar) = newTVarId();
02872 TTEXT(",");
02873 insertIntoHashTable(context->symtable, vname, tvar);
02874 cont = 1;
02875 OR(type)
02876 TTEXT("f");
02877
02878 NT2(_Type, 1, 0);
02879 TRY(ftype)
02880 TTEXT("=>");
02881 NT2(_Type, 1, 0);
02882 BUILD_NODE(T_FIXD, NULL, &start, 2, 2);
02883 OR(ftype)
02884 BUILD_NODE(T_FLEX, NULL, &start, 1, 1);
02885 END_TRY(ftype);
02886
02887 OR(type)
02888 TTEXT2("output","o");
02889 NT2(_Type, 1, 0);
02890 node = POP;
02891 setIOType(node, IO_TYPE_OUTPUT);
02892 PUSH(node);
02893 OR(type)
02894 TTEXT2("input","i");
02895 NT2(_Type, 1, 0);
02896 node = POP;
02897 setIOType(node, IO_TYPE_INPUT | (getIOType(node) & IO_TYPE_OUTPUT));
02898 PUSH(node);
02899 OR(type)
02900 TTEXT2("expression","e");
02901 NT2(_Type, 1, 0);
02902 node = POP;
02903 setIOType(node, IO_TYPE_EXPRESSION);
02904 PUSH(node);
02905 OR(type)
02906 TTEXT2("actions","a");
02907 NT2(_Type, 1, 0);
02908 node = POP;
02909 setIOType(node, IO_TYPE_ACTIONS);
02910 PUSH(node);
02911 OR(type)
02912 TTEXT2("dynamic", "d");
02913 NT2(_Type, 1, 0);
02914 node = POP;
02915 setIOType(node, IO_TYPE_DYNAMIC);
02916 PUSH(node);
02917 OR(type)
02918 TTEXT("type");
02919 CASCADE(newSimpType(T_TYPE, context->region));
02920
02921 OR(type)
02922 TTEXT("set");
02923 CASCADE(newSimpType(T_TYPE, context->region));
02924
02925 OR(type)
02926 TTYPE(TK_TEXT);
02927 char *cons = cpStringExt(token->text, context->region);
02928
02929 int n = 0;
02930 OPTIONAL_BEGIN(argList)
02931 TTEXT("(");
02932 LOOP_BEGIN(args)
02933 NT2(_Type, 1, 0);
02934 n++;
02935 TRY(delim)
02936 TTEXT(",");
02937 OR(delim)
02938 DONE(args);
02939 END_TRY(delim)
02940 LOOP_END(args)
02941 TTEXT(")")
02942 OPTIONAL_END(argList)
02943 BUILD_NODE(T_CONS, cons, &start, n, n);
02944 END_TRY(type)
02945 if(!cont) {
02946 arity ++;
02947 TRY(typeEnd)
02948 ABORT(prec!=1);
02949 DONE(type);
02950 OR(typeEnd)
02951 TTYPE_LOOKAHEAD(TK_EOS);
02952 DONE(type);
02953 OR(typeEnd)
02954 TTEXT("*");
02955 TTEXT("->");
02956 PUSHBACK;
02957 PUSHBACK;
02958 DONE(type);
02959 OR(typeEnd)
02960 TTEXT("*");
02961 OR(typeEnd);
02962 DONE(type);
02963 END_TRY(typeEnd)
02964 }
02965 LOOP_END(type)
02966 END_TRY(type)
02967 if(arity != 1 || lifted) {
02968 BUILD_NODE(T_TUPLE, TUPLE, &start, arity, arity);
02969 }
02970 PARSER_FUNC_END(_Type)
02971
02972 PARSER_FUNC_BEGIN(TypeSet)
02973 int rulegen = 1;
02974 TTEXT("{");
02975 int n = 0;
02976 int done2 = 0;
02977 while (!done2 && NO_SYNTAX_ERROR) {
02978 NT2(_Type, 1, 0);
02979 n++;
02980 OPTIONAL_BEGIN(typeVarBoundEnd)
02981 TTEXT("}");
02982 done2 = 1;
02983 OPTIONAL_END(typeVarBoundEnd)
02984 }
02985 if(done2) {
02986 BUILD_NODE(T_VAR, NULL, &start, n, n);
02987 } else {
02988 break;
02989 }
02990 PARSER_FUNC_END(TypeSet)
02991
02992 PARSER_FUNC_BEGIN(_TypingConstraints)
02993 int rulegen = 1;
02994 TTEXT("{");
02995 int n = 0;
02996 LOOP_BEGIN(tc)
02997 Label pos2 = *FPOS;
02998 NT2(_Type, 0, 0);
02999 TTEXT("<=");
03000 NT2(_Type, 0, 0);
03001 BUILD_NODE(TC_LT, "", &pos2, 0, 0); /* node for generating error messages */
03002 BUILD_NODE(TC_LT, "<=", &pos2, 3, 3);
03003 n++;
03004 TRY(tce)
03005 TTEXT(",");
03006 OR(tce)
03007 TTEXT("}");
03008 DONE(tc);
03009 END_TRY(tce)
03010 LOOP_END(tc)
03011 BUILD_NODE(TC_SET, "{}", &start, n, n);
03012 PARSER_FUNC_END(TypingConstraints)
03013
03014 PARSER_FUNC_BEGIN(_FuncType)
03015 int rulegen = 1;
03016 int vararg = 0;
03017 NT2(_Type, 0, 1);
03018 TRY(vararg)
03019 TTEXT("*");
03020 vararg = OPTION_VARARG_STAR;
03021 OR(vararg)
03022 TTEXT("+");
03023 vararg = OPTION_VARARG_PLUS;
03024 OR(vararg)
03025 TTEXT("?");
03026 vararg = OPTION_VARARG_OPTIONAL;
03027 OR(vararg)
03028 vararg = OPTION_VARARG_ONCE;
03029 END_TRY(vararg)
03030 TTEXT("->");
03031 NT2(_Type, 0, 0);
03032 BUILD_NODE(T_CONS, FUNC, &start, 2, 2);
03033 Node *node = POP;
03034 setVararg(node, vararg);
03035 PUSH(node);
03036 PARSER_FUNC_END(_FuncType)
03037
03038 int parseRuleSet(Pointer *e, RuleSet *ruleSet, Env *funcDescIndex, int *errloc, rError_t *errmsg, Region *r) {
03039 char errbuf[ERR_MSG_LEN];
03040 Token *token;
03041 ParserContext *pc = newParserContext(errmsg, r);
03042
03043 int ret = 1;
03044 /* parser variables */
03045 int backwardCompatible = 0; /* 0 auto 1 true -1 false */
03046
03047 while(ret == 1) {
03048 pc->nodeStackTop = 0;
03049 pc->stackTopStackTop = 0;
03050 token = nextTokenRuleGen(e, pc, 1, 0);
03051 switch(token->type) {
03052 case N_ERROR:
03053 return -1;
03054 case TK_EOS:
03055 ret = 0;
03056 continue;
03057 case TK_MISC_OP:
03058 case TK_TEXT:
03059 if(token->text[0] == '#') {
03060 skipComments(e);
03061 continue;
03062 } else if(token->text[0] == '@') { /* directive */
03063 token = nextTokenRuleGen(e, pc, 1, 0);
03064 if(strcmp(token->text, "backwardCompatible")==0) {
03065 token = nextTokenRuleGen(e, pc, 1, 0);
03066 if(token->type == TK_TEXT) {
03067 if(strcmp(token->text, "true")==0) {
03068 backwardCompatible = 1;
03069 } else if(strcmp(token->text, "false")==0) {
03070 backwardCompatible = -1;
03071 } else if(strcmp(token->text, "auto")==0) {
03072 backwardCompatible = 0;
03073 } else {
03074 /* todo error handling */
03075 }
03076 } else {
03077 /* todo error handling */
03078 }
03079 } else if(strcmp(token->text, "include")==0) {
03080 token = nextTokenRuleGen(e, pc, 1, 0);
03081 if(token->type == TK_TEXT || token->type == TK_STRING) {
03082 CASCASE_NON_ZERO(readRuleSetFromFile(token->text, ruleSet, funcDescIndex, errloc, errmsg, r));
03083 } else {
03084 /* todo error handling */
03085 }
03086 } else {
03087 /* todo error handling */
03088 }
03089 continue;
03090 }
03091 break;
03092 default:
03093 break;
03094 }
03095 pushback(e, token, pc);
03096
03097 Node *node = parseRuleRuleGen(e, backwardCompatible, pc);
03098 if(node==NULL) {
03099 addRErrorMsg(errmsg, RE_OUT_OF_MEMORY, "parseRuleSet: out of memory.");
03100 return RE_OUT_OF_MEMORY;
03101 } else if(getNodeType(node) == N_ERROR) {
03102 *errloc = NODE_EXPR_POS(node);
03103 generateErrMsg("parseRuleSet: error parsing rule.", *errloc, e->base, errbuf);
03104 addRErrorMsg(errmsg, RE_PARSER_ERROR, errbuf);
03105 /* skip the current line and try to parse the rule from the next line */
03106 skipComments(e);
03107 return RE_PARSER_ERROR;
03108 } else {
03109 int n = node->degree;
03110 Node **nodes = node->subtrees;
03111 RuleType rk;
03112 /* if(strcmp(node->text, "UNPARSED") == 0) {
03113 pushRule(ruleSet, newRuleDesc(RK_UNPARSED, nodes[0], r));
03114 } else */ if(strcmp(node->text, "INDUCT") == 0) {
03115 int k;
03116 pushRule(ruleSet, newRuleDesc(RK_DATA, nodes[0], 0, r));
03117 for(k=1;k<n;k++) {
03118 if(lookupFromEnv(funcDescIndex, nodes[k]->subtrees[0]->text)!=NULL) {
03119 generateErrMsg("parseRuleSet: redefinition of constructor.", NODE_EXPR_POS(nodes[k]->subtrees[0]), nodes[k]->subtrees[0]->base, errbuf);
03120 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
03121 return RE_TYPE_ERROR;
03122 }
03123 insertIntoHashTable(funcDescIndex->current, nodes[k]->subtrees[0]->text, newConstructorFD2(nodes[k]->subtrees[1], r));
03124 pushRule(ruleSet, newRuleDesc(RK_CONSTRUCTOR, nodes[k], 0, r));
03125 }
03126 } else if(strcmp(node->text, "CONSTR") == 0) {
03127 if(lookupFromEnv(funcDescIndex, nodes[0]->subtrees[0]->text)!=NULL) {
03128 generateErrMsg("parseRuleSet: redefinition of constructor.", NODE_EXPR_POS(nodes[0]->subtrees[0]), nodes[0]->subtrees[0]->base, errbuf);
03129 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
03130 return RE_TYPE_ERROR;
03131 }
03132 insertIntoHashTable(funcDescIndex->current, nodes[0]->subtrees[0]->text, newConstructorFD2(nodes[0]->subtrees[1], r));
03133 pushRule(ruleSet, newRuleDesc(RK_CONSTRUCTOR, nodes[0], 0, r));
03134 } else if(strcmp(node->text, "EXTERN") == 0) {
03135 FunctionDesc *fd;
03136 if((fd = (FunctionDesc *) lookupFromEnv(funcDescIndex, nodes[0]->subtrees[0]->text))!=NULL) {
03137 generateErrMsg("parseRuleSet: redefinition of function.", NODE_EXPR_POS(nodes[0]->subtrees[0]), nodes[0]->subtrees[0]->base, errbuf);
03138 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
03139 return RE_TYPE_ERROR;
03140 }
03141 insertIntoHashTable(funcDescIndex->current, nodes[0]->subtrees[0]->text, newExternalFD(nodes[0]->subtrees[1], r));
03142 pushRule(ruleSet, newRuleDesc(RK_EXTERN, nodes[0], 0, r));
03143 } else {
03144 int notyping;
03145 if(strcmp(node->text, "REL")==0) {
03146 rk = RK_REL;
03147 notyping = backwardCompatible >= 0 ? 1 : 0;
03148 } else if(strcmp(node->text, "FUNC")==0) {
03149 rk = RK_FUNC;
03150 notyping = 0;
03151 }
03152 int k;
03153 for(k=0;k<n;k++) {
03154 Node *node = nodes[k];
03155 pushRule(ruleSet, newRuleDesc(rk, node, notyping, r));
03156 /* printf("%s\n", node->subtrees[0]->text);
03157 printTree(node, 0); */
03158 }
03159 }
03160 }
03161 }
03162 deleteParserContext(pc);
03163 return 0;
03164 }
03165
03166 /*
03167 * parse the string for an ExprType
03168 * supported types:
03169 * ? dynamic
03170 * i integer
03171 * b boolean
03172 * d double
03173 * t time
03174 * s string
03175 * list <type> list
03176 * f <type> flexible
03177 * <var> ({ <type> ... <type> })? variable
03178 * <type> * ... * <type> product
03179 * < <type> * ... * <type> > lifted product
03180 * `irods PI` irods
03181 *
03182 * <type> (*|+|?)? -> <type> function
03183 * forall <var> (in { <type> ... <type> })?, <type> universal
03184 */
03185 Node* parseFuncTypeFromString(char *string, Region *r) {
03186 Pointer *p = newPointer2(string);
03187 ParserContext *pc = newParserContext(NULL, r);
03188 nextRuleGenFuncType(p, pc);
03189 Node *exprType = pc->nodeStack[0];
03190 deleteParserContext(pc);
03191 deletePointer(p);
03192 return exprType;
03193 }
03194 Node* parseTypingConstraintsFromString(char *string, Region *r) {
03195 Pointer *p = newPointer2(string);
03196 ParserContext *pc = newParserContext(NULL, r);
03197 nextRuleGenTypingConstraints(p, pc);
03198 Node *exprType = pc->nodeStack[0];
03199 /*char buf[ERR_MSG_LEN];
03200 errMsgToString(pc->errmsg, buf, ERR_MSG_LEN);
03201 printf("%s", buf);*/
03202 deleteParserContext(pc);
03203 deletePointer(p);
03204 return exprType;
03205 }
03206 Node *parseRuleRuleGen(Pointer *expr, int backwardCompatible, ParserContext *pc) {
03207 nextRuleGenRule(expr, pc, backwardCompatible);
03208 Node *rulePackNode = pc->nodeStack[0];
03209 if(pc->error) {
03210 if(pc->errnode!=NULL) {
03211 rulePackNode =pc->errnode;
03212 } else {
03213 rulePackNode =createErrorNode("parser error", &pc->errloc, pc->region);
03214 }
03215 }
03216 return rulePackNode;
03217 }
03218 Node *parseTermRuleGen(Pointer *expr, int rulegen, ParserContext *pc) {
03219 nextRuleGenTerm(expr, pc, rulegen, 0);
03220 Node *rulePackNode = pc->nodeStack[0];
03221 if(pc->error) {
03222 if(pc->errnode!=NULL) {
03223 rulePackNode =pc->errnode;
03224 } else {
03225 rulePackNode =createErrorNode("parser error", &pc->errloc, pc->region);
03226 }
03227 }
03228
03229 return rulePackNode;
03230
03231 }
03232 Node *parseActionsRuleGen(Pointer *expr, int rulegen, int backwardCompatible, ParserContext *pc) {
03233 nextRuleGenActions(expr, pc, rulegen, backwardCompatible);
03234 Node *rulePackNode = pc->nodeStack[0];
03235 if(pc->error) {
03236 if(pc->errnode!=NULL) {
03237 rulePackNode =pc->errnode;
03238 } else {
03239 rulePackNode =createErrorNode("parser error", &pc->errloc, pc->region);
03240 }
03241 }
03242
03243 return rulePackNode;
03244
03245 }
03246 char* typeName_Res(Res *s) {
03247 return typeName_ExprType(s->exprType);
03248 }
03249
03250 char* typeName_ExprType(ExprType *s) {
03251 switch(getNodeType(s)) {
03252 case T_IRODS:
03253 return s->text;
03254 default:
03255 return typeName_NodeType(getNodeType(s));
03256 }
03257 }
03258
03259 char* typeName_Parser(NodeType s) {
03260 switch(s) {
03261 case T_IRODS:
03262 return "IRODS";
03263 case T_VAR:
03264 return "VAR";
03265 case T_DYNAMIC:
03266 return "?";
03267 case T_CONS:
03268 return "CONS";
03269 case T_FLEX:
03270 return "f";
03271 case T_FIXD:
03272 return "f";
03273 case T_BOOL:
03274 return "boolean";
03275 case T_INT:
03276 return "integer";
03277 case T_DOUBLE:
03278 return "double";
03279 case T_STRING:
03280 return "string";
03281 case T_ERROR:
03282 return "ERROR";
03283 case T_DATETIME:
03284 return "time";
03285 case T_PATH:
03286 return "path";
03287 case T_TYPE:
03288 return "set";
03289 case T_TUPLE:
03290 return "TUPLE";
03291 default:
03292 return "OTHER";
03293 }
03294 }
03295
03296 char* typeName_NodeType(NodeType s) {
03297 switch(s) {
03298 case T_IRODS:
03299 return "IRODS";
03300 case T_VAR:
03301 return "VAR";
03302 case T_DYNAMIC:
03303 return "DYNAMIC";
03304 case T_CONS:
03305 return "CONS";
03306 case T_FLEX:
03307 return "FLEX";
03308 case T_FIXD:
03309 return "FIXD";
03310 case T_BOOL:
03311 return "BOOLEAN";
03312 case T_INT:
03313 return "INTEGER";
03314 case T_DOUBLE:
03315 return "DOUBLE";
03316 case T_STRING:
03317 return "STRING";
03318 case T_ERROR:
03319 return "ERROR";
03320 case T_DATETIME:
03321 return "DATETIME";
03322 case T_PATH:
03323 return "PATH";
03324 case T_TYPE:
03325 return "TYPE";
03326 case T_TUPLE:
03327 return "TUPLE";
03328 default:
03329 return "OTHER";
03330 }
03331 }
03332
03333 void generateErrMsgFromFile(char *msg, long errloc, char *ruleBaseName, char* ruleBasePath, char errbuf[ERR_MSG_LEN]) {
03334 FILE *fp = fopen(ruleBasePath, "r");
03335 Pointer *e = newPointer(fp, ruleBaseName);
03336 Label l;
03337 l.base = NULL;
03338 l.exprloc = errloc;
03339 generateErrMsgFromPointer(msg, &l, e, errbuf);
03340 deletePointer(e);
03341 }
03342
03343 void generateErrMsgFromSource(char *msg, long errloc, char *src, char errbuf[ERR_MSG_LEN]) {
03344 Pointer *e = newPointer2(src);
03345 Label l;
03346 l.base = NULL;
03347 l.exprloc = errloc;
03348 generateErrMsgFromPointer(msg, &l, e, errbuf);
03349 deletePointer(e);
03350 }
03351 void generateErrMsgFromPointer(char *msg, Label *l, Pointer *e, char errbuf[ERR_MSG_LEN]) {
03352 char buf[ERR_MSG_LEN];
03353 dupLine(e, l, ERR_MSG_LEN, buf);
03354 int len = strlen(buf);
03355 int coor[2];
03356 getCoor(e, l, coor);
03357 int i;
03358 if(len < ERR_MSG_LEN - 1) {
03359 buf[len++] = '\n';
03360 }
03361 for(i=0;i<coor[1];i++) {
03362 if(len >= ERR_MSG_LEN - 1) {
03363 break;
03364 }
03365 buf[len++] = buf[i] == '\t'?'\t':' ';
03366 }
03367 if(len < ERR_MSG_LEN - 2) {
03368 buf[len++] = '^';
03369 }
03370 buf[len++] = '\0';
03371 if(e->isFile)
03372 snprintf(errbuf, ERR_MSG_LEN,
03373 "%s\nline %d, col %d, rule base %s\n%s\n", msg, coor[0], coor[1], e->base+1, buf);
03374 else
03375 snprintf(errbuf, ERR_MSG_LEN,
03376 "%s\nline %d, col %d\n%s\n", msg, coor[0], coor[1], buf);
03377
03378 }
03379 void generateAndAddErrMsg(char *msg, Node *node, int errcode, rError_t *errmsg) {
03380 char errmsgBuf[ERR_MSG_LEN];
03381 generateErrMsg(msg, NODE_EXPR_POS(node), node->base, errmsgBuf);
03382 addRErrorMsg(errmsg, errcode, errmsgBuf);
03383 }
03384 char *generateErrMsg(char *msg, long errloc, char *ruleBaseName, char errmsg[ERR_MSG_LEN]) {
03385 char ruleBasePath[MAX_NAME_LEN];
03386 switch(ruleBaseName[0]) {
03387 case 's': // source
03388 generateErrMsgFromSource(msg, errloc, ruleBaseName + 1, errmsg);
03389 return errmsg;
03390 case 'f': // file
03391 getRuleBasePath(ruleBaseName + 1, ruleBasePath);
03392 generateErrMsgFromFile(msg, errloc, ruleBaseName + 1, ruleBasePath, errmsg);
03393 return errmsg;
03394 default:
03395 snprintf(errmsg, ERR_MSG_LEN, "<unknown source type>");
03396 return errmsg;
03397 }
03398 }