// Generated by ReScript, PLEASE EDIT WITH CARE

import * as Curry from "rescript/lib/es6/curry.js";
import * as Lexing from "rescript/lib/es6/lexing.js";
import * as Caml_obj from "rescript/lib/es6/caml_obj.js";
import * as Caml_option from "rescript/lib/es6/caml_option.js";
import * as Res_comment from "./res_comment.js";
import * as Res_scanner from "./res_scanner.js";
import * as Res_diagnostics from "./res_diagnostics.js";

function err(startPos, endPos, p, error) {
  var match = p.regions;
  if (!match) {
    return ;
  }
  var region = match.hd;
  var match$1 = region.contents;
  if (match$1) {
    return ;
  }
  var d = Res_diagnostics.make(startPos !== undefined ? startPos : p.startPos, endPos !== undefined ? endPos : p.endPos, error);
  p.diagnostics = {
    hd: d,
    tl: p.diagnostics
  };
  region.contents = /* Silent */1;
  
}

function beginRegion(p) {
  p.regions = {
    hd: {
      contents: /* Report */0
    },
    tl: p.regions
  };
  
}

function endRegion(p) {
  var match = p.regions;
  if (match) {
    p.regions = match.tl;
    return ;
  }
  
}

function next(_prevEndPos, p) {
  while(true) {
    var prevEndPos = _prevEndPos;
    if (p.token === /* Eof */26) {
      throw {
            RE_EXN_ID: "Assert_failure",
            _1: [
              "res_parser.res",
              59,
              4
            ],
            Error: new Error()
          };
    }
    var prevEndPos$1 = prevEndPos !== undefined ? prevEndPos : p.endPos;
    var match = Res_scanner.scan(p.scanner);
    var token = match[2];
    var endPos = match[1];
    if (typeof token !== "number" && token.TAG === /* Comment */6) {
      var c = token._0;
      Res_comment.setPrevTokEndPos(c, p.endPos);
      p.comments = {
        hd: c,
        tl: p.comments
      };
      p.prevEndPos = p.endPos;
      p.endPos = endPos;
      _prevEndPos = prevEndPos$1;
      continue ;
    }
    p.token = token;
    p.prevEndPos = prevEndPos$1;
    p.startPos = match[0];
    p.endPos = endPos;
    return ;
  };
}

function nextUnsafe(p) {
  if (p.token !== /* Eof */26) {
    return next(undefined, p);
  }
  
}

function nextTemplateLiteralToken(p) {
  var match = Res_scanner.scanTemplateLiteralToken(p.scanner);
  p.token = match[2];
  p.prevEndPos = p.endPos;
  p.startPos = match[0];
  p.endPos = match[1];
  
}

function checkProgress(prevEndPos, result, p) {
  if (p.endPos === prevEndPos) {
    return ;
  } else {
    return Caml_option.some(result);
  }
}

function make(modeOpt, src, filename) {
  var mode = modeOpt !== undefined ? modeOpt : /* ParseForTypeChecker */0;
  var scanner = Res_scanner.make(filename, src);
  var parserState = {
    mode: mode,
    scanner: scanner,
    token: /* Semicolon */8,
    startPos: Lexing.dummy_pos,
    endPos: Lexing.dummy_pos,
    prevEndPos: Lexing.dummy_pos,
    breadcrumbs: /* [] */0,
    errors: /* [] */0,
    diagnostics: /* [] */0,
    comments: /* [] */0,
    regions: {
      hd: {
        contents: /* Report */0
      },
      tl: /* [] */0
    }
  };
  parserState.scanner.err = (function (startPos, endPos, error) {
      var diagnostic = Res_diagnostics.make(startPos, endPos, error);
      parserState.diagnostics = {
        hd: diagnostic,
        tl: parserState.diagnostics
      };
      
    });
  next(undefined, parserState);
  return parserState;
}

function leaveBreadcrumb(p, circumstance) {
  var crumb_1 = p.startPos;
  var crumb = [
    circumstance,
    crumb_1
  ];
  p.breadcrumbs = {
    hd: crumb,
    tl: p.breadcrumbs
  };
  
}

function eatBreadcrumb(p) {
  var match = p.breadcrumbs;
  if (match) {
    p.breadcrumbs = match.tl;
    return ;
  }
  
}

function optional(p, token) {
  if (Caml_obj.caml_equal(p.token, token)) {
    next(undefined, p);
    return true;
  } else {
    return false;
  }
}

function expect(grammar, token, p) {
  if (Caml_obj.caml_equal(p.token, token)) {
    return next(undefined, p);
  }
  var error = Res_diagnostics.expected(grammar, p.prevEndPos, token);
  return err(p.prevEndPos, undefined, p, error);
}

function lookahead(p, callback) {
  var err = p.scanner.err;
  var ch = p.scanner.ch;
  var offset = p.scanner.offset;
  var lineOffset = p.scanner.lineOffset;
  var lnum = p.scanner.lnum;
  var mode = p.scanner.mode;
  var token = p.token;
  var startPos = p.startPos;
  var endPos = p.endPos;
  var prevEndPos = p.prevEndPos;
  var breadcrumbs = p.breadcrumbs;
  var errors = p.errors;
  var diagnostics = p.diagnostics;
  var comments = p.comments;
  var res = Curry._1(callback, p);
  p.scanner.err = err;
  p.scanner.ch = ch;
  p.scanner.offset = offset;
  p.scanner.lineOffset = lineOffset;
  p.scanner.lnum = lnum;
  p.scanner.mode = mode;
  p.token = token;
  p.startPos = startPos;
  p.endPos = endPos;
  p.prevEndPos = prevEndPos;
  p.breadcrumbs = breadcrumbs;
  p.errors = errors;
  p.diagnostics = diagnostics;
  p.comments = comments;
  return res;
}

var Scanner;

var Diagnostics;

var Token;

var Grammar;

var Reporting;

var $$Comment;

export {
  Scanner ,
  Diagnostics ,
  Token ,
  Grammar ,
  Reporting ,
  $$Comment ,
  err ,
  beginRegion ,
  endRegion ,
  next ,
  nextUnsafe ,
  nextTemplateLiteralToken ,
  checkProgress ,
  make ,
  leaveBreadcrumb ,
  eatBreadcrumb ,
  optional ,
  expect ,
  lookahead ,
  
}
/* Res_comment Not a pure module */
