use std::collections::HashMap;
use crate::lexer::{EOF,Lexer,Token,TokenType};
use crate::Bytecode;
pub const LOGICAL_CONNECTIVES : &[TokenType] = &[
TokenType::AmpersandAmpersand,
TokenType::BarBar,
TokenType::LongRightArrow
];
pub const ARITHMETIC_COMPARATORS : &[TokenType] = &[
TokenType::EqualsEquals,
TokenType::ShreakEquals,
TokenType::LeftAngle,
TokenType::LeftAngleEquals,
TokenType::RightAngle,
TokenType::RightAngleEquals
];
pub const ARITHMETIC_OPERATORS : &[TokenType] = &[
TokenType::Minus,
TokenType::Percent,
TokenType::Plus,
TokenType::RightSlash,
TokenType::Star
];
pub const BINARY_CONNECTIVES : &[ &[TokenType] ] = &[
ARITHMETIC_OPERATORS,
ARITHMETIC_COMPARATORS,
LOGICAL_CONNECTIVES
];
pub const TYPES : &[TokenType] = &[
TokenType::Uint
];
pub struct Parser {
lexer: Lexer,
env: Environment,
bytecodes: Vec<Bytecode>
}
impl Parser {
pub fn new(content: &str) -> Self {
let lexer = Lexer::new(content);
let env = Environment::new();
Self{lexer, env, bytecodes: Vec::new()}
}
pub fn parse(mut self) -> Result<Vec<Bytecode>,()> {
while self.lexer.lookahead(0) != EOF {
self.parse_declaration()?;
}
Ok(self.bytecodes)
}
fn parse_declaration(&mut self) -> Result<(),()> {
let lookahead = self.lexer.lookahead(0);
match lookahead.kind {
TokenType::ForAll => self.parse_decl_forall(),
TokenType::Fun => self.parse_decl_fun(),
TokenType::RecFun => self.parse_decl_recfun(),
_ => {
self.parse_decl_assert()
}
}
}
fn parse_decl_assert(&mut self) -> Result<(),()> {
self.bytecodes.push(Bytecode::Assert);
self.parse_expr();
Ok(())
}
fn parse_decl_forall(&mut self) -> Result<(),()> {
self.lexer.expect(TokenType::ForAll);
let params = self.parse_decl_params()?;
self.env.alloc_vars(¶ms);
self.bytecodes.push(Bytecode::Assert);
self.parse_expr();
Ok(())
}
fn parse_decl_fun(&mut self) -> Result<(),()> {
self.lexer.expect(TokenType::Fun);
let id = self.lexer.expect(TokenType::Identifier);
let params = self.parse_decl_params()?;
self.env.alloc_vars(¶ms);
self.bytecodes.push(Bytecode::Fun(params.len()));
let body = self.parse_block()?;
let name = self.lexer.to_string(&id);
self.env.alloc_fn(&name, params.len());
Ok(())
}
fn parse_decl_recfun(&mut self) -> Result<(),()> {
self.lexer.expect(TokenType::RecFun);
let id = self.lexer.expect(TokenType::Identifier);
let params = self.parse_decl_params()?;
self.env.alloc_vars(¶ms);
let name = self.lexer.to_string(&id);
self.env.alloc_fn(&name, params.len());
self.bytecodes.push(Bytecode::Fun(params.len()));
let body = self.parse_block()?;
Ok(())
}
fn parse_decl_params(&mut self) -> Result<Vec<String>,()> {
let mut params = Vec::new();
self.lexer.expect(TokenType::LeftBrace);
let mut lookahead = self.lexer.lookahead(0);
while lookahead.kind != TokenType::RightBrace {
if !params.is_empty() { self.lexer.expect(TokenType::Comma); }
let var = self.parse_identifier()?;
params.push(var);
lookahead = self.lexer.lookahead(0);
}
self.lexer.expect(TokenType::RightBrace);
Ok(params)
}
fn parse_block(&mut self) -> Result<(),()> {
self.lexer.expect(TokenType::LeftCurly);
self.parse_expr()?;
self.lexer.expect(TokenType::RightCurly);
Ok(())
}
pub fn parse_expr(&mut self) -> Result<(),()> {
self.parse_expr_binary(3)
}
fn parse_expr_binary(&mut self, level: usize) -> Result<(),()> {
if level == 0 {
self.parse_expr_postfix()
} else {
let tokens = BINARY_CONNECTIVES[level-1];
let index = self.bytecodes.len();
self.parse_expr_binary(level-1)?;
match self.lexer.match_any(tokens) {
Some(t) => {
self.bytecodes.insert(index,Self::binop_from_token(t.kind));
let rhs = self.parse_expr_binary(level-1)?;
}
None => {}
};
Ok(())
}
}
fn parse_expr_braced(&mut self) -> Result<(),()> {
self.lexer.expect(TokenType::LeftBrace);
self.parse_expr()?;
self.lexer.expect(TokenType::RightBrace);
Ok(())
}
fn parse_expr_ifelse(&mut self) -> Result<(),()> {
self.lexer.expect(TokenType::If);
self.bytecodes.push(Bytecode::If);
self.parse_expr()?;
self.parse_block()?;
self.lexer.expect(TokenType::Else);
self.parse_block()?;
Ok(())
}
fn parse_expr_invoke(&mut self) -> Result<(),()> {
let index = self.bytecodes.len();
let id = self.lexer.expect(TokenType::Identifier);
let name = self.lexer.to_string(&id);
let (id,arity) = self.env.lookup_fn(&name).unwrap();
self.bytecodes.push(Bytecode::Invoke(0,0));
self.lexer.expect(TokenType::LeftBrace);
let n = self.parse_exprs_until(TokenType::RightBrace)?;
self.lexer.expect(TokenType::RightBrace);
assert_eq!(n, arity);
self.bytecodes[index] = Bytecode::Invoke(id,arity);
Ok(())
}
fn parse_expr_not(&mut self) -> Result<(),()> {
self.lexer.expect(TokenType::Shreak);
self.bytecodes.push(Bytecode::Not);
self.parse_expr()?;
Ok(())
}
fn parse_expr_postfix(&mut self) -> Result<(),()> {
let index = self.bytecodes.len();
self.parse_expr_unit()?;
if self.lexer.matches(TokenType::Colon) {
match self.lexer.match_any(TYPES) {
Some(t) => {
self.bytecodes.insert(index,Self::type_from_token(t.kind));
}
_ => { return Err(()); }
}
}
Ok(())
}
fn parse_expr_unit(&mut self) -> Result<(),()> {
let lookahead = self.lexer.lookahead(0);
match lookahead.kind {
TokenType::BoolLiteral(v) => self.parse_literal_bool(v),
TokenType::LeftBrace => self.parse_expr_braced(),
TokenType::Identifier => {
if self.lexer.lookahead(1).kind == TokenType::LeftBrace {
self.parse_expr_invoke()
} else {
self.parse_expr_varaccess()
}
}
TokenType::IntLiteral => self.parse_literal_int(),
TokenType::Shreak => self.parse_expr_not(),
TokenType::If => self.parse_expr_ifelse(),
_ => {
panic!("unexpected token {lookahead:?}");
}
}
}
fn parse_exprs_until(&mut self, end: TokenType) -> Result<usize,()> {
let mut lookahead = self.lexer.lookahead(0);
let mut n = 0;
while lookahead.kind != end {
if n != 0 {
self.lexer.expect(TokenType::Comma);
}
self.parse_expr()?;
lookahead = self.lexer.lookahead(0);
n += 1
}
Ok(n)
}
fn parse_expr_varaccess(&mut self) -> Result<(),()> {
let id = self.lexer.expect(TokenType::Identifier);
let name = self.lexer.to_string(&id);
let var = self.env.lookup_var(&name).unwrap();
self.bytecodes.push(Bytecode::Var(var));
Ok(())
}
fn parse_literal_bool(&mut self, val: bool) -> Result<(),()> {
self.lexer.expect(TokenType::BoolLiteral(val));
self.bytecodes.push(Bytecode::Bool(val));
Ok(())
}
fn parse_literal_int(&mut self) -> Result<(),()> {
let tok = self.lexer.expect(TokenType::IntLiteral);
let s = self.lexer.to_string(&tok);
let i = s.parse::<usize>().unwrap();
self.bytecodes.push(Bytecode::Int(i));
Ok(())
}
fn parse_identifier(&mut self) -> Result<String,()> {
let ith = self.lexer.expect(TokenType::Identifier);
Ok(self.lexer.to_string(&ith))
}
fn binop_from_token(token: TokenType) -> Bytecode {
let bop = match token {
TokenType::EqualsEquals => Bytecode::Eq,
TokenType::ShreakEquals => Bytecode::Neq,
TokenType::LeftAngle => Bytecode::Lt,
TokenType::LeftAngleEquals => Bytecode::LtEq,
TokenType::RightAngle => Bytecode::Gt,
TokenType::RightAngleEquals => Bytecode::GtEq,
TokenType::Minus => Bytecode::Sub,
TokenType::Percent => Bytecode::Rem,
TokenType::Plus => Bytecode::Add,
TokenType::RightSlash => Bytecode::Div,
TokenType::Star => Bytecode::Mul,
TokenType::AmpersandAmpersand => Bytecode::And,
TokenType::BarBar => Bytecode::Or,
TokenType::LongRightArrow => Bytecode::Implies,
_ => { unreachable!(); }
};
bop
}
fn type_from_token(token: TokenType) -> Bytecode {
match token {
TokenType::Uint => Bytecode::IsUint,
_ => { unreachable!(); }
}
}
}
struct Environment {
fn_bindings: HashMap<String,(usize,usize)>,
var_bindings: HashMap<String,usize>
}
impl Environment {
pub fn new() -> Self {
let fn_bindings = HashMap::new();
let var_bindings = HashMap::new();
Self{fn_bindings,var_bindings}
}
pub fn alloc_fn(&mut self, name: &str, arity: usize) {
let index = self.fn_bindings.len();
self.fn_bindings.insert(name.to_string(),(index,arity));
}
pub fn alloc_vars(&mut self, vars: &[String]) {
self.var_bindings.clear();
for (i,n) in vars.iter().enumerate() {
self.var_bindings.insert(n.to_string(),i);
}
}
pub fn lookup_fn(&self, name: &str) -> Option<(usize,usize)> {
self.fn_bindings.get(name).copied()
}
pub fn lookup_var(&self, name: &str) -> Option<usize> {
self.var_bindings.get(name).copied()
}
}