<commit_before>#include "internal.hpp"

/*------------------------------------------------------------------------*/

// Only used here for error reporting, so also only included here.

#include <string>

/*------------------------------------------------------------------------*/

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

// Parsing utilities.

int Parser::parse_char () { return file->get (); }

// Return an non zero error string if a parse error occurred.

inline const char *
Parser::parse_string (const char * str, char prev) {
  for (const char * p = str; *p; p++)
    if (parse_char () == *p) prev = *p;
    else PER ("expected '%c' after '%c'", *p, prev);
  return 0;
}

inline const char *
Parser::parse_positive_int (int & ch, int & res, const char * name) {
  assert (isdigit (ch));
  res = ch - '0';
  while (isdigit (ch = parse_char ())) {
    int digit = ch - '0';
    if (INT_MAX/10 < res || INT_MAX - digit < 10*res)
      PER ("too large '%s' in header", name);
    res = 10*res + digit;
  }
  return 0;
}

inline const char *
Parser::parse_lit (int & ch, int & lit, const int vars) {
  int sign = 0;
  if (ch == '-') {
    if (!isdigit (ch = parse_char ())) PER ("expected digit after '-'");
    sign = -1;
  } else if (!isdigit (ch)) PER ("expected digit or '-'");
  else sign = 1;
  lit = ch - '0';
  while (isdigit (ch = parse_char ())) {
    int digit = ch - '0';
    if (INT_MAX/10 < lit || INT_MAX - digit < 10*lit)
      PER ("literal too large");
    lit = 10*lit + digit;
  }
  if (ch == '\r') ch = parse_char ();
  if (ch != 'c' && ch != ' ' && ch != '\t' && ch != '\n')
    PER ("expected white space after '%d'", sign*lit);
  if (lit > vars)
    PER ("literal %d exceeds maximum variable %d", sign*lit, vars);
  lit *= sign;
  return 0;
}

/*------------------------------------------------------------------------*/

// Parsing function for CNF in DIMACS format.

const char * Parser::parse_dimacs_non_profiled () {
  int ch, vars = 0, clauses = 0;
  for (;;) {
    ch = parse_char ();
    if (ch != 'c') break;
    string buf;
    while ((ch = parse_char ()) != '\n')
      if (ch == EOF) PER ("unexpected end-of-file in header comment");
      else if (ch != '\r') buf.push_back (ch);
    const char * o;
    for (o = buf.c_str (); *o && *o != '-'; o++)
      ;
    if (!*o) continue;
    VRB ("parse-dimacs", "found option '%s'", o);
    if (*o) internal->opts.set (o);
  }
  if (ch != 'p') PER ("expected 'c' or 'p'");
  const char * err = parse_string (" cnf ", 'p');<commit_msg>allowed EOF after last literal<commit_after>#include "internal.hpp"

/*------------------------------------------------------------------------*/

// Only used here for error reporting, so also only included here.

#include <string>

/*------------------------------------------------------------------------*/

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

// Parsing utilities.

int Parser::parse_char () { return file->get (); }

// Return an non zero error string if a parse error occurred.

inline const char *
Parser::parse_string (const char * str, char prev) {
  for (const char * p = str; *p; p++)
    if (parse_char () == *p) prev = *p;
    else PER ("expected '%c' after '%c'", *p, prev);
  return 0;
}

inline const char *
Parser::parse_positive_int (int & ch, int & res, const char * name) {
  assert (isdigit (ch));
  res = ch - '0';
  while (isdigit (ch = parse_char ())) {
    int digit = ch - '0';
    if (INT_MAX/10 < res || INT_MAX - digit < 10*res)
      PER ("too large '%s' in header", name);
    res = 10*res + digit;
  }
  return 0;
}

inline const char *
Parser::parse_lit (int & ch, int & lit, const int vars) {
  int sign = 0;
  if (ch == '-') {
    if (!isdigit (ch = parse_char ())) PER ("expected digit after '-'");
    sign = -1;
  } else if (!isdigit (ch)) PER ("expected digit or '-'");
  else sign = 1;
  lit = ch - '0';
  while (isdigit (ch = parse_char ())) {
    int digit = ch - '0';
    if (INT_MAX/10 < lit || INT_MAX - digit < 10*lit)
      PER ("literal too large");
    lit = 10*lit + digit;
  }
  if (ch == '\r') ch = parse_char ();
  if (ch != 'c' && ch != ' ' && ch != '\t' && ch != '\n' && ch != EOF)
    PER ("expected white space after '%d'", sign*lit);
  if (lit > vars)
    PER ("literal %d exceeds maximum variable %d", sign*lit, vars);
  lit *= sign;
  return 0;
}

/*------------------------------------------------------------------------*/

// Parsing function for CNF in DIMACS format.

const char * Parser::parse_dimacs_non_profiled () {
  int ch, vars = 0, clauses = 0;
  for (;;) {
    ch = parse_char ();
    if (ch != 'c') break;
    string buf;
    while ((ch = parse_char ()) != '\n')
      if (ch == EOF) PER ("unexpected end-of-file in header comment");
      else if (ch != '\r') buf.push_back (ch);
    const char * o;
    for (o = buf.c_str (); *o && *o != '-'; o++)
      ;
    if (!*o) continue;
    VRB ("parse-dimacs", "found option '%s'", o);
    if (*o) internal->opts.set (o);
  }
  if (ch != 'p') PER ("expected 'c' or 'p'");
  const char * err = parse_string (" cnf ", 'p');
{'fraction_non_alphanumeric': 0.2845559845559846, 'fraction_numerical': 0.009266409266409266, 'mean_word_length': 1.8326954620010936, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '292917', 'n_tokens_mistral': 1728, 'n_tokens_neox': 1685, 'n_words': 575}