示例#1
0
文件: parser.c 项目: konijn/angband
/* 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;
}
示例#2
0
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;
  }
}