Flatten values into expression grammar
This commit is contained in:
@@ -223,32 +223,44 @@ pub struct RuleBody<'db> {
|
||||
/// Parse an expression from the AST.
|
||||
#[salsa::tracked]
|
||||
pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
|
||||
use ir::ExprKind;
|
||||
use ir::{ExprKind::*, Value::*};
|
||||
|
||||
// parse the kind depending on which field is selected
|
||||
let kind = if let Some(tuple) = ast.get_field(db, "tuple") {
|
||||
let els = tuple.get_fields(db, "el").map(|el| expr(db, el)).collect();
|
||||
ExprKind::Extra(Arc::new(ExprExtra::Tuple(els)))
|
||||
} else if let Some(val) = ast.get_field(db, "hole") {
|
||||
ExprKind::Extra(Arc::new(ExprExtra::Hole))
|
||||
} else if let Some(val) = ast.get_field(db, "value") {
|
||||
ExprKind::Value(value(db, val))
|
||||
let kind = if let Some(val) = ast.get_field(db, "hole") {
|
||||
Extra(Arc::new(ExprExtra::Hole))
|
||||
} else if let Some(var) = ast.get_field(db, "variable") {
|
||||
let name = var.contents(db).to_string();
|
||||
ExprKind::Extra(Arc::new(ExprExtra::VariableName(name)))
|
||||
Extra(Arc::new(ExprExtra::VariableName(name)))
|
||||
} else if let Some(ast) = ast.get_field(db, "atom") {
|
||||
Extra(Arc::new(ExprExtra::Apply(apply(db, ast))))
|
||||
} else if let Some(tuple) = ast.get_field(db, "tuple") {
|
||||
let els = tuple.get_fields(db, "el").map(|el| expr(db, el)).collect();
|
||||
Extra(Arc::new(ExprExtra::Tuple(els)))
|
||||
} else if let Some(ast) = ast.get_field(db, "aggregate") {
|
||||
Extra(Arc::new(ExprExtra::Aggregate(aggregate(db, ast))))
|
||||
} else if ast.get_field(db, "true").is_some() {
|
||||
Value(Boolean(true))
|
||||
} else if ast.get_field(db, "false").is_some() {
|
||||
Value(Boolean(false))
|
||||
} else if let Some(sym) = ast.get_field(db, "symbol") {
|
||||
todo!()
|
||||
} else if let Some(int) = ast.get_field(db, "integer") {
|
||||
Value(match int.contents(db).to_string().parse() {
|
||||
Ok(val) => Integer(val),
|
||||
Err(_) => {
|
||||
diagnostic::SimpleError::new(int, "failed to parse integer literal").accumulate(db);
|
||||
Integer(0)
|
||||
}
|
||||
})
|
||||
} else if let Some(unary) = ast.get_field(db, "unary") {
|
||||
let op = unary.expect_field(db, "op").expect_parse(db);
|
||||
let term = Arc::new(expr(db, unary.expect_field(db, "term")));
|
||||
UnaryOp { op, term }
|
||||
} else if let Some(binary) = ast.get_field(db, "binary") {
|
||||
let op = binary.expect_field(db, "op").expect_parse(db);
|
||||
let lhs = Arc::new(expr(db, binary.expect_field(db, "lhs")));
|
||||
let rhs = Arc::new(expr(db, binary.expect_field(db, "rhs")));
|
||||
ExprKind::BinaryOp { op, lhs, rhs }
|
||||
} else if let Some(unary) = ast.get_field(db, "unary") {
|
||||
let op = unary.expect_field(db, "op").expect_parse(db);
|
||||
let term = Arc::new(expr(db, unary.expect_field(db, "term")));
|
||||
ExprKind::UnaryOp { op, term }
|
||||
} else if let Some(ast) = ast.get_field(db, "atom") {
|
||||
ExprKind::Extra(Arc::new(ExprExtra::Apply(apply(db, ast))))
|
||||
} else if let Some(ast) = ast.get_field(db, "aggregate") {
|
||||
ExprKind::Extra(Arc::new(ExprExtra::Aggregate(aggregate(db, ast))))
|
||||
BinaryOp { op, lhs, rhs }
|
||||
} else if let Some(parens) = ast.get_field(db, "parens") {
|
||||
return expr(db, parens);
|
||||
} else {
|
||||
@@ -259,27 +271,6 @@ pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
|
||||
Expr { meta: ast, kind }
|
||||
}
|
||||
|
||||
/// Parses a value from an AST.
|
||||
fn value(db: &dyn Database, ast: AstNode) -> ir::Value {
|
||||
use ir::Value::*;
|
||||
if ast.get_field(db, "true").is_some() {
|
||||
Boolean(true)
|
||||
} else if ast.get_field(db, "false").is_some() {
|
||||
Boolean(false)
|
||||
} else if let Some(sym) = ast.get_field(db, "symbol") {
|
||||
todo!()
|
||||
} else {
|
||||
let int = ast.expect_field(db, "integer");
|
||||
match int.contents(db).to_string().parse() {
|
||||
Ok(val) => Integer(val),
|
||||
Err(_) => {
|
||||
diagnostic::SimpleError::new(int, "failed to parse integer literal").accumulate(db);
|
||||
Integer(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses an aggregate operator.
|
||||
pub fn aggregate(db: &dyn Database, ast: AstNode) -> Aggregate {
|
||||
let kind = ast.expect_field(db, "op").with_contents(db);
|
||||
|
||||
Reference in New Issue
Block a user