Lines
0 %
Functions
use super::util::{get_tree, query_toplevel};
use crate::errors::EssenceParseError;
use crate::expression::parse_expression;
use crate::util::node_is_expression;
use conjure_cp_core::ast::{Expression, SymbolTable};
use std::cell::RefCell;
use std::rc::Rc;
#[allow(unused)]
use uniplate::Uniplate;
pub fn parse_expr(src: &str, symbol_table: &SymbolTable) -> Result<Expression, EssenceParseError> {
let exprs = parse_exprs(src, symbol_table)?;
if exprs.len() != 1 {
return Err(EssenceParseError::syntax_error(
"Expected a single expression".to_string(),
None,
));
}
Ok(exprs[0].clone())
pub fn parse_exprs(
src: &str,
symbol_table: &SymbolTable,
) -> Result<Vec<Expression>, EssenceParseError> {
let (tree, source_code) = get_tree(src).ok_or(EssenceParseError::TreeSitterError(
"Failed to parse Essence source code".to_string(),
))?;
let root = tree.root_node();
let mut ans = Vec::new();
let symbols_ptr = Rc::new(RefCell::new(symbol_table.clone()));
for expr in query_toplevel(&root, &node_is_expression) {
ans.push(parse_expression(
expr,
&source_code,
&root,
Some(symbols_ptr.clone()),
)?);
Ok(ans)
mod test {
use super::{parse_expr, parse_exprs};
use conjure_cp_core::ast::{
Atom, DeclarationPtr, Domain, Expression, Literal, Metadata, Moo, Name, SymbolTable,
};
use std::collections::HashMap;
use std::sync::Arc;
use std::{cell::RefCell, rc::Rc};
use tree_sitter::Range;
#[test]
pub fn test_parse_constant() {
let symbols = SymbolTable::new();
assert_eq!(
parse_expr("42", &symbols).unwrap(),
Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(42)))
);
parse_expr("true", &symbols).unwrap(),
Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(true)))
parse_expr("false", &symbols).unwrap(),
Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(false)))
)
pub fn test_parse_expressions() {
let src = "x >= 5, y = a / 2";
let mut symbols = SymbolTable::new();
let x = DeclarationPtr::new_var(
Name::User("x".into()),
Domain::int(vec![conjure_cp_core::ast::Range::Bounded(0, 10)]),
let y = DeclarationPtr::new_var(
Name::User("y".into()),
let a = DeclarationPtr::new_var(
Name::User("a".into()),
// Clone the Rc when inserting!
symbols
.insert(x.clone())
.expect("x should not exist in the symbol-table yet, so we should be able to add it");
.insert(y.clone())
.expect("y should not exist in the symbol-table yet, so we should be able to add it");
.insert(a.clone())
.expect("a should not exist in the symbol-table yet, so we should be able to add it");
let exprs = parse_exprs(src, &symbols).unwrap();
assert_eq!(exprs.len(), 2);
exprs[0],
Expression::Geq(
Metadata::new(),
Moo::new(Expression::Atomic(Metadata::new(), Atom::new_ref(x))),
Moo::new(Expression::Atomic(Metadata::new(), 5.into()))
exprs[1],
Expression::Eq(
Moo::new(Expression::Atomic(Metadata::new(), Atom::new_ref(y))),
Moo::new(Expression::UnsafeDiv(
Moo::new(Expression::Atomic(Metadata::new(), Atom::new_ref(a))),
Moo::new(Expression::Atomic(Metadata::new(), 2.into()))
))