mod cg;
mod clause;
pub mod operators;
mod query;
mod term;
pub use cg::CgClause;
use crate::parse_error::ParseError;
use crate::tokenizer::{Token, TokenKind};
use plg_shared::{AtomId, Span, StringInterner, VarId};
use std::collections::HashMap;
#[derive(Debug, Default, Clone)]
pub struct ProgramDirectives {
pub dynamic: Vec<(AtomId, usize)>,
}
#[derive(Debug, Clone)]
pub struct CallSite {
pub functor: AtomId,
pub arity: usize,
pub span: Span,
}
pub struct Parser<'a> {
tokens: Vec<Token>,
pos: usize,
interner: &'a mut StringInterner,
var_map: HashMap<String, VarId>,
next_var: VarId,
call_sites: Vec<CallSite>,
file_id: plg_shared::FileId,
}
impl<'a> Parser<'a> {
fn from_tokens(tokens: Vec<Token>, interner: &'a mut StringInterner) -> Self {
Parser {
tokens,
pos: 0,
interner,
var_map: HashMap::new(),
next_var: 0,
call_sites: Vec::new(),
file_id: 0,
}
}
fn record_call_site(&mut self, functor: AtomId, arity: usize, span: Span) {
self.call_sites.push(CallSite {
functor,
arity,
span,
});
}
fn reset_vars(&mut self) {
self.var_map.clear();
self.next_var = 0;
}
fn current(&self) -> Option<&Token> {
self.tokens.get(self.pos)
}
fn current_kind(&self) -> Option<&TokenKind> {
self.current().map(|t| &t.kind)
}
fn at_eof(&self) -> bool {
matches!(self.current_kind(), None | Some(TokenKind::Eof))
}
fn advance(&mut self) -> &Token {
let tok = &self.tokens[self.pos];
self.pos += 1;
tok
}
fn here_span(&self) -> Span {
match self.current() {
Some(t) => Span::new(0, t.lo, t.hi),
None => self.eof_span(),
}
}
fn eof_span(&self) -> Span {
let off = self.tokens.last().map(|t| t.hi).unwrap_or(0);
Span::point(0, off)
}
fn error_here(&self, message: impl Into<String>) -> ParseError {
ParseError::new(message, self.here_span())
}
fn expect(&mut self, kind: &TokenKind) -> Result<(), ParseError> {
match self.current() {
Some(tok) if &tok.kind == kind => {
self.advance();
Ok(())
}
Some(tok) => {
let msg = format!("expected {}, got {}", kind, tok.kind);
Err(self.error_here(msg))
}
None => Err(self.error_here(format!("expected {kind}, got end of input"))),
}
}
pub fn var_names(&self) -> &HashMap<String, VarId> {
&self.var_map
}
}