use super::{
lexer::{tokenize, Token},
ManchesterError, ManchesterExpr,
};
struct Parser {
tokens: Vec<(Token, usize)>,
cursor: usize,
}
impl Parser {
fn new(tokens: Vec<(Token, usize)>) -> Self {
Self { tokens, cursor: 0 }
}
fn peek(&self) -> &Token {
&self.tokens[self.cursor].0
}
fn advance(&mut self) -> &Token {
let tok = &self.tokens[self.cursor].0;
if self.cursor + 1 < self.tokens.len() {
self.cursor += 1;
}
tok
}
fn consume(&mut self) -> Token {
let tok = self.tokens[self.cursor].0.clone();
if self.cursor + 1 < self.tokens.len() {
self.cursor += 1;
}
tok
}
fn err(&self, msg: impl Into<String>) -> ManchesterError {
ManchesterError::ParseError {
pos: self.cursor,
msg: msg.into(),
}
}
fn parse_expr(&mut self) -> Result<ManchesterExpr, ManchesterError> {
self.parse_or_expr()
}
fn parse_or_expr(&mut self) -> Result<ManchesterExpr, ManchesterError> {
let first = self.parse_and_expr()?;
if !matches!(self.peek(), Token::Or) {
return Ok(first);
}
let mut arms = vec![first];
while matches!(self.peek(), Token::Or) {
self.advance(); arms.push(self.parse_and_expr()?);
}
Ok(ManchesterExpr::Or(arms))
}
fn parse_and_expr(&mut self) -> Result<ManchesterExpr, ManchesterError> {
let first = self.parse_not_expr()?;
if !matches!(self.peek(), Token::And) {
return Ok(first);
}
let mut arms = vec![first];
while matches!(self.peek(), Token::And) {
self.advance(); arms.push(self.parse_not_expr()?);
}
Ok(ManchesterExpr::And(arms))
}
fn parse_not_expr(&mut self) -> Result<ManchesterExpr, ManchesterError> {
if matches!(self.peek(), Token::Not) {
self.advance(); let inner = self.parse_primary()?;
return Ok(ManchesterExpr::Not(Box::new(inner)));
}
self.parse_primary()
}
fn parse_primary(&mut self) -> Result<ManchesterExpr, ManchesterError> {
match self.peek().clone() {
Token::Ident(_) => {
let name = match self.consume() {
Token::Ident(s) => s,
_ => unreachable!(),
};
self.parse_rest(name)
}
Token::LBrace => {
self.advance(); let mut individuals: Vec<String> = Vec::new();
loop {
match self.peek().clone() {
Token::RBrace => {
self.advance(); break;
}
Token::Ident(_) => {
let ind = match self.consume() {
Token::Ident(s) => s,
_ => unreachable!(),
};
individuals.push(ind);
}
Token::Eof => {
return Err(self.err("unexpected end of input inside `{…}`"));
}
other => {
return Err(self.err(format!(
"expected identifier or `}}` inside `{{…}}`, got {other}"
)));
}
}
}
if individuals.is_empty() {
return Err(ManchesterError::ParseError {
pos: self.cursor,
msg: "`{…}` must contain at least one individual".to_string(),
});
}
Ok(ManchesterExpr::OneOf(individuals))
}
Token::LParen => {
self.advance(); let inner = self.parse_expr()?;
match self.peek() {
Token::RParen => {
self.advance(); }
other => {
return Err(self.err(format!("expected `)`, got {other}")));
}
}
Ok(inner)
}
Token::Eof => Err(self.err("unexpected end of input — expected a class expression")),
other => Err(self.err(format!("expected class name, `{{`, or `(`, got {other}"))),
}
}
fn parse_rest(&mut self, property: String) -> Result<ManchesterExpr, ManchesterError> {
match self.peek().clone() {
Token::Some => {
self.advance();
let filler = self.parse_primary()?;
Ok(ManchesterExpr::Some {
property,
filler: Box::new(filler),
})
}
Token::Only => {
self.advance();
let filler = self.parse_primary()?;
Ok(ManchesterExpr::Only {
property,
filler: Box::new(filler),
})
}
Token::Min => {
self.advance();
let cardinality = self.expect_number()?;
let filler = self.maybe_primary()?;
Ok(ManchesterExpr::Min {
property,
cardinality,
filler: filler.map(Box::new),
})
}
Token::Max => {
self.advance();
let cardinality = self.expect_number()?;
let filler = self.maybe_primary()?;
Ok(ManchesterExpr::Max {
property,
cardinality,
filler: filler.map(Box::new),
})
}
Token::Exactly => {
self.advance();
let cardinality = self.expect_number()?;
let filler = self.maybe_primary()?;
Ok(ManchesterExpr::Exactly {
property,
cardinality,
filler: filler.map(Box::new),
})
}
Token::Value => {
self.advance();
let individual = match self.peek().clone() {
Token::Ident(_) => match self.consume() {
Token::Ident(s) => s,
_ => unreachable!(),
},
other => {
return Err(self.err(format!(
"expected individual name after `value`, got {other}"
)));
}
};
Ok(ManchesterExpr::HasValue {
property,
individual,
})
}
_ => Ok(ManchesterExpr::Class(property)),
}
}
fn expect_number(&mut self) -> Result<u32, ManchesterError> {
match self.peek().clone() {
Token::Number(n) => {
self.advance();
Ok(n)
}
other => Err(self.err(format!("expected a number, got {other}"))),
}
}
fn maybe_primary(&mut self) -> Result<Option<ManchesterExpr>, ManchesterError> {
match self.peek() {
Token::Ident(_) | Token::LBrace | Token::LParen => Ok(Some(self.parse_primary()?)),
_ => Ok(None),
}
}
}
pub fn parse(input: &str) -> Result<ManchesterExpr, ManchesterError> {
if input.trim().is_empty() {
return Err(ManchesterError::ParseError {
pos: 0,
msg: "input is empty — expected a class expression".to_string(),
});
}
let tokens = tokenize(input)?;
let mut parser = Parser::new(tokens);
let expr = parser.parse_expr()?;
match parser.peek() {
Token::Eof => {}
other => {
return Err(ManchesterError::ParseError {
pos: parser.cursor,
msg: format!(
"unexpected token {other} after class expression — expected end of input"
),
});
}
}
Ok(expr)
}