/* This is a bit long and should probably be refactored a bit. */ enum parser_error parser_parse(struct parser *p, const char *line) { char *cline; char *tok; struct parser_hook *h; struct parser_spec *s; struct parser_value *v; char *sp = NULL; assert(p); assert(line); parser_freeold(p); p->lineno++; p->colno = 1; p->fhead = NULL; p->ftail = NULL; /* Ignore empty lines and comments. */ while (*line && (isspace(*line))) line++; if (!*line || *line == '#') return PARSE_ERROR_NONE; cline = string_make(line); tok = strtok(cline, ":"); if (!tok) { mem_free(cline); p->error = PARSE_ERROR_MISSING_FIELD; return PARSE_ERROR_MISSING_FIELD; } h = findhook(p, tok); if (!h) { my_strcpy(p->errmsg, tok, sizeof(p->errmsg)); p->error = PARSE_ERROR_UNDEFINED_DIRECTIVE; mem_free(cline); return PARSE_ERROR_UNDEFINED_DIRECTIVE; } /* There's a little bit of trickiness here to account for optional * types. The optional flag has a bit assigned to it in the spec's type * tag; we compute a temporary type for the spec with that flag removed * and use that instead. */ for (s = h->fhead; s; s = s->next) { int t = s->type & ~T_OPT; p->colno++; /* These types are tokenized on ':'; strings are not tokenized * at all (i.e., they consume the remainder of the line) */ if (t == T_INT || t == T_SYM || t == T_RAND || t == T_UINT) { tok = strtok(sp, ":"); sp = NULL; } else if (t == T_CHAR) { tok = strtok(sp, ""); if (tok) sp = tok + 2; } else { tok = strtok(sp, ""); sp = NULL; } if (!tok) { if (!(s->type & T_OPT)) { my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_MISSING_FIELD; mem_free(cline); return PARSE_ERROR_MISSING_FIELD; } break; } /* Allocate a value node, parse out its value, and link it into * the value list. */ v = mem_alloc(sizeof *v); v->spec.next = NULL; v->spec.type = s->type; v->spec.name = s->name; if (t == T_INT) { char *z = NULL; v->u.ival = strtol(tok, &z, 0); if (z == tok) { mem_free(v); mem_free(cline); my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_NOT_NUMBER; return PARSE_ERROR_NOT_NUMBER; } } else if (t == T_UINT) { char *z = NULL; v->u.uval = strtoul(tok, &z, 0); if (z == tok || *tok == '-') { mem_free(v); mem_free(cline); my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_NOT_NUMBER; return PARSE_ERROR_NOT_NUMBER; } } else if (t == T_CHAR) { v->u.cval = *tok; } else if (t == T_SYM || t == T_STR) { v->u.sval = string_make(tok); } else if (t == T_RAND) { if (!parse_random(tok, &v->u.rval)) { mem_free(v); mem_free(cline); my_strcpy(p->errmsg, s->name, sizeof(p->errmsg)); p->error = PARSE_ERROR_NOT_RANDOM; return PARSE_ERROR_NOT_RANDOM; } } if (!p->fhead) p->fhead = v; else p->ftail->spec.next = &v->spec; p->ftail = v; } mem_free(cline); p->error = h->func(p); return p->error; }
void CommandLine::parse_and_exec(){ try{ if(vm->count("help")){ print_help(); return; } else if(vm->count("interactive")){ InteractiveMode * im = new InteractiveMode(); im->start(); return; } if(vm->count("file") + vm->count("max") + vm->count("random") != 1){ std::cerr << "Need to provide exactly one of 'file', 'max' or 'random' options when not using interactive mode." << std::endl; return; } CNFFormula f; if(vm->count("file")){ parse_file_options(f); } if(vm->count("random")){ parse_random(f); } if(vm->count("max")){ parse_max(f); } if(vm->count("minimalize")){ f.minimalize(); } if(vm->count("bruteforce")){ SolvedCNF * solf = new SolvedCNF(f); std::cout << *solf << std::endl; delete solf; } if(vm->count("ppzfull")){ Ppz * ppz = new Ppz(f); PpzRunStats stats; ppz->full_solve_ppz(stats); std::cout << stats << std::endl; delete ppz; } if(vm->count("ppzfulloracle")){ Ppz * ppz = new Ppz(f); PpzRunStats stats; ppz->full_solve_ppz(stats,true); std::cout << stats << std::endl; delete ppz; } if(vm->count("ppzrandom")){ Ppz * ppz = new Ppz(f); double limit = pow(2, f.get_n()-1.0/f.get_k()); ppz->random_solve_ppz(limit); } std::string savefilename = "formula.cnf"; if(vm->count("save")){ savefilename = (*vm)["save"].as<std::string>(); f.save(savefilename); } } catch(std::exception & e){ std::cerr << e.what() << std::endl; } }