static void reducec(NUM_TYPE* l1,NUM_TYPE * l2) { NUM_TYPE c, i1, i2; i1 = ABS(*l1); i2 = ABS(*l2); if (i2 > i1) { c = i1; i1 = i2; i2 = c; } while (i2 != 0) { c = i2; i2 = REST(i1,i2); i1 = c; } (*l1) = DIV(*l1,i1); (*l2) = DIV(*l2,i1); }
int main() { SICPStream *s = integers(1); for (int i=5; i>=0; --i) { printf("%p, %d\n", s, FIRST(s)); SICPStream *s1 = REST(s); delete s; s = s1; } return 0; }
static reg_errcode_t tre_parse_bound(tre_parse_ctx_t *ctx, tre_ast_node_t **result) { int min, max, i; int cost_ins, cost_del, cost_subst, cost_max; int limit_ins, limit_del, limit_subst, limit_err; const tre_char_t *r = ctx->re; const tre_char_t *start; int minimal = (ctx->cflags & REG_UNGREEDY) ? 1 : 0; int approx = 0; int costs_set = 0; int counts_set = 0; cost_ins = cost_del = cost_subst = cost_max = TRE_PARAM_UNSET; limit_ins = limit_del = limit_subst = limit_err = TRE_PARAM_UNSET; /* Parse number (minimum repetition count). */ min = -1; if (r < ctx->re_end && *r >= L'0' && *r <= L'9') { DPRINT(("tre_parse: min count: '%.*" STRF "'\n", REST(r))); min = tre_parse_int(&r, ctx->re_end); } /* Parse comma and second number (maximum repetition count). */ max = min; if (r < ctx->re_end && *r == CHAR_COMMA) { r++; DPRINT(("tre_parse: max count: '%.*" STRF "'\n", REST(r))); max = tre_parse_int(&r, ctx->re_end); } /* Check that the repeat counts are sane. */ if ((max >= 0 && min > max) || max > RE_DUP_MAX) return REG_BADBR; /* '{' optionally followed immediately by a number == minimum repcount optionally followed by , then a number == maximum repcount + then a number == maximum insertion count - then a number == maximum deletion count # then a number == maximum substitution count ~ then a number == maximum number of errors Any of +, -, # or ~ without followed by a number means that the maximum count/number of errors is infinite. An equation of the form Xi + Yd + Zs < C can be specified to set costs and the cost limit to a value different from the default value: - X is the cost of an insertion - Y is the cost of a deletion - Z is the cost of a substitution - C is the maximum cost If no count limit or cost is set for an operation, the operation is not allowed at all. */ do { int done; start = r; /* Parse count limit settings */ done = 0; if (!counts_set) while (r + 1 < ctx->re_end && !done) { switch (*r) { case CHAR_PLUS: /* Insert limit */ DPRINT(("tre_parse: ins limit: '%.*" STRF "'\n", REST(r))); r++; limit_ins = tre_parse_int(&r, ctx->re_end); if (limit_ins < 0) limit_ins = INT_MAX; counts_set = 1; break; case CHAR_MINUS: /* Delete limit */ DPRINT(("tre_parse: del limit: '%.*" STRF "'\n", REST(r))); r++; limit_del = tre_parse_int(&r, ctx->re_end); if (limit_del < 0) limit_del = INT_MAX; counts_set = 1; break; case CHAR_HASH: /* Substitute limit */ DPRINT(("tre_parse: subst limit: '%.*" STRF "'\n", REST(r))); r++; limit_subst = tre_parse_int(&r, ctx->re_end); if (limit_subst < 0) limit_subst = INT_MAX; counts_set = 1; break; case CHAR_TILDE: /* Maximum number of changes */ DPRINT(("tre_parse: count limit: '%.*" STRF "'\n", REST(r))); r++; limit_err = tre_parse_int(&r, ctx->re_end); if (limit_err < 0) limit_err = INT_MAX; approx = 1; break; case CHAR_COMMA: r++; break; case L' ': r++; break; case L'}': done = 1; break; default: done = 1; break; } } /* Parse cost restriction equation. */ done = 0; if (!costs_set) while (r + 1 < ctx->re_end && !done) { switch (*r) { case CHAR_PLUS: case L' ': r++; break; case L'<': DPRINT(("tre_parse: max cost: '%.*" STRF "'\n", REST(r))); r++; while (*r == L' ') r++; cost_max = tre_parse_int(&r, ctx->re_end); if (cost_max < 0) cost_max = INT_MAX; else cost_max--; approx = 1; break; case CHAR_COMMA: r++; done = 1; break; default: if (*r >= L'0' && *r <= L'9') { #ifdef TRE_DEBUG const tre_char_t *sr = r; #endif /* TRE_DEBUG */ int cost = tre_parse_int(&r, ctx->re_end); /* XXX - make sure r is not past end. */ switch (*r) { case L'i': /* Insert cost */ DPRINT(("tre_parse: ins cost: '%.*" STRF "'\n", REST(sr))); r++; cost_ins = cost; costs_set = 1; break; case L'd': /* Delete cost */ DPRINT(("tre_parse: del cost: '%.*" STRF "'\n", REST(sr))); r++; cost_del = cost; costs_set = 1; break; case L's': /* Substitute cost */ DPRINT(("tre_parse: subst cost: '%.*" STRF "'\n", REST(sr))); r++; cost_subst = cost; costs_set = 1; break; default: return REG_BADBR; } } else { done = 1; break; } } } } while (start != r); /* Missing }. */ if (r >= ctx->re_end) return REG_EBRACE; /* Empty contents of {}. */ if (r == ctx->re) return REG_BADBR; /* Parse the ending '}' or '\}'.*/ if (ctx->cflags & REG_EXTENDED) { if (r >= ctx->re_end || *r != CHAR_RBRACE) return REG_BADBR; r++; } else { if (r + 1 >= ctx->re_end || *r != CHAR_BACKSLASH || *(r + 1) != CHAR_RBRACE) return REG_BADBR; r += 2; } /* Parse trailing '?' marking minimal repetition. */ if (r < ctx->re_end) { if (*r == CHAR_QUESTIONMARK) { minimal = !(ctx->cflags & REG_UNGREEDY); r++; } else if (*r == CHAR_STAR || *r == CHAR_PLUS) { /* These are reserved for future extensions. */ return REG_BADRPT; } } /* Create the AST node(s). */ if (min == 0 && max == 0) { *result = tre_ast_new_literal(ctx->mem, EMPTY, EMPTY, -1); if (*result == NULL) return REG_ESPACE; } else { if (min < 0 && max < 0) /* Only approximate parameters set, no repetitions. */ min = max = 1; *result = tre_ast_new_iter(ctx->mem, *result, min, max, minimal); if (!*result) return REG_ESPACE; /* If approximate matching parameters are set, add them to the iteration node. */ if (approx || costs_set || counts_set) { int *params; tre_iteration_t *iter = (*result)->obj; if (costs_set || counts_set) { if (limit_ins == TRE_PARAM_UNSET) { if (cost_ins == TRE_PARAM_UNSET) limit_ins = 0; else limit_ins = INT_MAX; } if (limit_del == TRE_PARAM_UNSET) { if (cost_del == TRE_PARAM_UNSET) limit_del = 0; else limit_del = INT_MAX; } if (limit_subst == TRE_PARAM_UNSET) { if (cost_subst == TRE_PARAM_UNSET) limit_subst = 0; else limit_subst = INT_MAX; } } if (cost_max == TRE_PARAM_UNSET) cost_max = INT_MAX; if (limit_err == TRE_PARAM_UNSET) limit_err = INT_MAX; ctx->have_approx = 1; params = tre_mem_alloc(ctx->mem, sizeof(*params) * TRE_PARAM_LAST); if (!params) return REG_ESPACE; for (i = 0; i < TRE_PARAM_LAST; i++) params[i] = TRE_PARAM_UNSET; params[TRE_PARAM_COST_INS] = cost_ins; params[TRE_PARAM_COST_DEL] = cost_del; params[TRE_PARAM_COST_SUBST] = cost_subst; params[TRE_PARAM_COST_MAX] = cost_max; params[TRE_PARAM_MAX_INS] = limit_ins; params[TRE_PARAM_MAX_DEL] = limit_del; params[TRE_PARAM_MAX_SUBST] = limit_subst; params[TRE_PARAM_MAX_ERR] = limit_err; iter->params = params; } } DPRINT(("tre_parse_bound: min %d, max %d, costs [%d,%d,%d, total %d], " "limits [%d,%d,%d, total %d]\n", min, max, cost_ins, cost_del, cost_subst, cost_max, limit_ins, limit_del, limit_subst, limit_err)); ctx->re = r; return REG_OK; }
static reg_errcode_t tre_parse_bracket(tre_parse_ctx_t *ctx, tre_ast_node_t **result) { tre_ast_node_t *node = NULL; int negate = 0; reg_errcode_t status = REG_OK; tre_ast_node_t **items, *u, *n; int i = 0, j, max_i = 32, curr_max, curr_min; tre_ctype_t neg_classes[MAX_NEG_CLASSES]; int num_neg_classes = 0; /* Start off with an array of `max_i' elements. */ items = xmalloc(sizeof(*items) * max_i); if (items == NULL) return REG_ESPACE; if (*ctx->re == CHAR_CARET) { DPRINT(("tre_parse_bracket: negate: '%.*" STRF "'\n", REST(ctx->re))); negate = 1; ctx->re++; } status = tre_parse_bracket_items(ctx, negate, neg_classes, &num_neg_classes, &items, &i, &max_i); if (status != REG_OK) goto parse_bracket_done; /* Sort the array if we need to negate it. */ if (negate) qsort(items, (unsigned)i, sizeof(*items), tre_compare_items); curr_max = curr_min = 0; /* Build a union of the items in the array, negated if necessary. */ for (j = 0; j < i && status == REG_OK; j++) { int min, max; tre_literal_t *l = items[j]->obj; min = l->code_min; max = l->code_max; DPRINT(("item: %d - %d, class %p, curr_max = %d\n", (int)l->code_min, (int)l->code_max, (void *)l->u.classt, curr_max)); if (negate) { if (min < curr_max) { /* Overlap. */ curr_max = MAX(max + 1, curr_max); DPRINT(("overlap, curr_max = %d\n", curr_max)); l = NULL; } else { /* No overlap. */ curr_max = min - 1; if (curr_max >= curr_min) { DPRINT(("no overlap\n")); l->code_min = curr_min; l->code_max = curr_max; } else { DPRINT(("no overlap, zero room\n")); l = NULL; } curr_min = curr_max = max + 1; } } if (l != NULL) { int k; DPRINT(("creating %d - %d\n", (int)l->code_min, (int)l->code_max)); l->position = ctx->position; if (num_neg_classes > 0) { l->neg_classes = tre_mem_alloc(ctx->mem, (sizeof(l->neg_classes) * (num_neg_classes + 1))); if (l->neg_classes == NULL) { status = REG_ESPACE; break; } for (k = 0; k < num_neg_classes; k++) l->neg_classes[k] = neg_classes[k]; l->neg_classes[k] = (tre_ctype_t)0; } else l->neg_classes = NULL; if (node == NULL) node = items[j]; else { u = tre_ast_new_union(ctx->mem, node, items[j]); if (u == NULL) status = REG_ESPACE; node = u; } } } if (status != REG_OK) goto parse_bracket_done; if (negate) { int k; DPRINT(("final: creating %d - %d\n", curr_min, (int)TRE_CHAR_MAX)); n = tre_ast_new_literal(ctx->mem, curr_min, TRE_CHAR_MAX, ctx->position); if (n == NULL) status = REG_ESPACE; else { tre_literal_t *l = n->obj; if (num_neg_classes > 0) { l->neg_classes = tre_mem_alloc(ctx->mem, (sizeof(l->neg_classes) * (num_neg_classes + 1))); if (l->neg_classes == NULL) { status = REG_ESPACE; goto parse_bracket_done; } for (k = 0; k < num_neg_classes; k++) l->neg_classes[k] = neg_classes[k]; l->neg_classes[k] = (tre_ctype_t)0; } else l->neg_classes = NULL; if (node == NULL) node = n; else { u = tre_ast_new_union(ctx->mem, node, n); if (u == NULL) status = REG_ESPACE; node = u; } } } if (status != REG_OK) goto parse_bracket_done; #ifdef TRE_DEBUG tre_ast_print(node); #endif /* TRE_DEBUG */ parse_bracket_done: xfree(items); ctx->position++; *result = node; return status; }
static reg_errcode_t tre_parse_bracket_items(tre_parse_ctx_t *ctx, int negate, tre_ctype_t neg_classes[], int *num_neg_classes, tre_ast_node_t ***items, int *num_items, int *items_size) { const tre_char_t *re = ctx->re; reg_errcode_t status = REG_OK; tre_ctype_t classt = (tre_ctype_t)0; int i = *num_items; int max_i = *items_size; int skip; /* Build an array of the items in the bracket expression. */ while (status == REG_OK) { skip = 0; if (re == ctx->re_end) { status = REG_EBRACK; } else if (*re == CHAR_RBRACKET && re > ctx->re) { DPRINT(("tre_parse_bracket: done: '%.*" STRF "'\n", REST(re))); re++; break; } else { tre_cint_t min = 0, max = 0; classt = (tre_ctype_t)0; if (re + 2 < ctx->re_end && *(re + 1) == CHAR_MINUS && *(re + 2) != CHAR_RBRACKET) { DPRINT(("tre_parse_bracket: range: '%.*" STRF "'\n", REST(re))); min = *re; max = *(re + 2); re += 3; /* XXX - Should use collation order instead of encoding values in character ranges. */ if (min > max) status = REG_ERANGE; } else if (re + 1 < ctx->re_end && *re == CHAR_LBRACKET && *(re + 1) == CHAR_PERIOD) status = REG_ECOLLATE; else if (re + 1 < ctx->re_end && *re == CHAR_LBRACKET && *(re + 1) == CHAR_EQUAL) status = REG_ECOLLATE; else if (re + 1 < ctx->re_end && *re == CHAR_LBRACKET && *(re + 1) == CHAR_COLON) { char tmp_str[64]; const tre_char_t *endptr = re + 2; size_t len; DPRINT(("tre_parse_bracket: class: '%.*" STRF "'\n", REST(re))); while (endptr < ctx->re_end && *endptr != CHAR_COLON) endptr++; if (endptr != ctx->re_end) { len = MIN(endptr - re - 2, 63); #ifdef TRE_WCHAR { tre_char_t tmp_wcs[64]; wcsncpy(tmp_wcs, re + 2, len); tmp_wcs[len] = L'\0'; #if defined HAVE_WCSRTOMBS { mbstate_t state; const tre_char_t *src = tmp_wcs; memset(&state, '\0', sizeof(state)); len = wcsrtombs(tmp_str, &src, sizeof(tmp_str), &state); } #elif defined HAVE_WCSTOMBS len = wcstombs(tmp_str, tmp_wcs, 63); #endif /* defined HAVE_WCSTOMBS */ } #else /* !TRE_WCHAR */ strncpy(tmp_str, (const char*)re + 2, len); #endif /* !TRE_WCHAR */ tmp_str[len] = '\0'; DPRINT((" class name: %s\n", tmp_str)); classt = tre_ctype(tmp_str); if (!classt) status = REG_ECTYPE; /* Optimize character classes for 8 bit character sets. */ if (status == REG_OK && ctx->cur_max == 1) { status = tre_expand_ctype(ctx->mem, classt, items, &i, &max_i, ctx->cflags); classt = (tre_ctype_t)0; skip = 1; } re = endptr + 2; } else status = REG_ECTYPE; min = 0; max = TRE_CHAR_MAX; } else { DPRINT(("tre_parse_bracket: char: '%.*" STRF "'\n", REST(re))); if (*re == CHAR_MINUS && *(re + 1) != CHAR_RBRACKET && ctx->re != re) /* Two ranges are not allowed to share and endpoint. */ status = REG_ERANGE; min = max = *re++; } if (status != REG_OK) break; if (classt && negate) if (*num_neg_classes >= MAX_NEG_CLASSES) status = REG_ESPACE; else neg_classes[(*num_neg_classes)++] = classt; else if (!skip) { status = tre_new_item(ctx->mem, min, max, &i, &max_i, items); if (status != REG_OK) break; ((tre_literal_t*)((*items)[i-1])->obj)->u.classt = classt; } /* Add opposite-case counterpoints if REG_ICASE is present. This is broken if there are more than two "same" characters. */ if (ctx->cflags & REG_ICASE && !classt && status == REG_OK && !skip) { tre_cint_t cmin, ccurr; DPRINT(("adding opposite-case counterpoints\n")); while (min <= max) { if (tre_islower(min)) { cmin = ccurr = tre_toupper(min++); while (tre_islower(min) && tre_toupper(min) == ccurr + 1 && min <= max) ccurr = tre_toupper(min++); status = tre_new_item(ctx->mem, cmin, ccurr, &i, &max_i, items); } else if (tre_isupper(min)) { cmin = ccurr = tre_tolower(min++); while (tre_isupper(min) && tre_tolower(min) == ccurr + 1 && min <= max) ccurr = tre_tolower(min++); status = tre_new_item(ctx->mem, cmin, ccurr, &i, &max_i, items); } else min++; if (status != REG_OK) break; } if (status != REG_OK) break; } } } *num_items = i; *items_size = max_i; ctx->re = re; return status; }
/******************************************************************************* *** FUNCTION PROG() ******************************************************************************* *** DESCRIPTION : Processes PROG grammar rule. *** *** PROG -> TYPE idt REST PROG | *** const idt = num ; PROG | *** e ******************************************************************************/ void RecursiveParser::PROG() { EntryPtr ptr; VarType type; ParamPtr paramptr = NULL; base = NULL; bool func; string code; int local_vars = 0; int param_num = 0; if (global->Token == Global::intt || global->Token == Global::floatt || global->Token == Global::chart) { TYPE(type); symtab->insert(global->Lexeme, global->Token, depth); ptr = symtab->lookup(global->Lexeme); funcname = global->Lexeme; match(Global::idt); if (global->Token == Global::lparent) { func = true; code = "proc " + funcname; emit(code); //if function ptr->TypeOfEntry = functionEntry; ptr->function.ReturnType = type; ptr->function.ParamList = new ParamNode(); paramptr = ptr->function.ParamList; ptr->function.NumberOfParameters = 0; base = paramptr; } else { funcname = "::EMPTY::"; //if variable declaration ptr->TypeOfEntry = varEntry; ptr->var.TypeOfVariable = type; ptr->var.Offset = offset; ptr->var.size = getsize(type, offset); } REST(type, offset, paramptr, local_vars, param_num); if (func) { code = "endp " + funcname; emit(code); code = "START PROC " + funcname; emit(code); func = false; } PROG(); } //rest is for constant else if (global->Token == Global::constt) { match(Global::constt); symtab->insert(global->Lexeme, global->Token, depth); ptr = symtab->lookup(global->Lexeme); ptr->TypeOfEntry = constEntry; match(Global::idt); match(Global::assignopt); if (lex->isFloat) { ptr->constant.TypeOfConstant = floatType; ptr->constant.ValueR = global->ValueR; } else { ptr->constant.TypeOfConstant = intType; ptr->constant.Value = global->Value; } match(Global::numt); match(Global::semicolont); PROG(); } else return; }