start parsing DDL

main
Ziyang Hu 2 years ago
parent f2b85e5a0c
commit bfe66025ca

@ -8,7 +8,8 @@ use crate::ast::eval_op::*;
use crate::ast::Expr::{Apply, Const};
use crate::ast::op::Op;
use crate::error::CozoError;
use crate::typing::Typing;
use crate::error::CozoError::ReservedIdent;
use crate::typing::{PrimitiveType, Typing};
use crate::value::Value;
mod eval_op;
@ -33,19 +34,23 @@ lazy_static! {
};
}
#[derive(Debug, PartialEq)]
pub struct Col {
pub name: String,
pub typ: Typing,
pub default: Option<Value<'static>>,
}
#[derive(Debug, PartialEq)]
pub enum TableDef {
Node {
is_local: bool,
name: String,
keys: Vec<Col>,
cols: Vec<Col>,
},
Edge {
is_local: bool,
src: String,
dst: String,
name: String,
@ -53,10 +58,17 @@ pub enum TableDef {
cols: Vec<Col>,
},
Columns {
is_local: bool,
attached: String,
name: String,
cols: Vec<Col>,
},
Index {
is_local: bool,
name: String,
attached: String,
cols: Vec<String>,
},
}
@ -128,12 +140,13 @@ fn parse_int(s: &str, radix: u32) -> i64 {
}
#[inline]
fn parse_raw_string(pairs: Pairs<Rule>) -> Result<String, CozoError> {
Ok(pairs.into_iter().next().unwrap().as_str().to_string())
fn parse_raw_string(pair: Pair<Rule>) -> Result<String, CozoError> {
Ok(pair.into_inner().into_iter().next().unwrap().as_str().to_string())
}
#[inline]
fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String, CozoError> {
fn parse_quoted_string(pair: Pair<Rule>) -> Result<String, CozoError> {
let pairs = pair.into_inner().next().unwrap().into_inner();
let mut ret = String::with_capacity(pairs.as_str().len());
for pair in pairs {
let s = pair.as_str();
@ -160,7 +173,8 @@ fn parse_quoted_string(pairs: Pairs<Rule>) -> Result<String, CozoError> {
#[inline]
fn parse_s_quoted_string(pairs: Pairs<Rule>) -> Result<String, CozoError> {
fn parse_s_quoted_string(pair: Pair<Rule>) -> Result<String, CozoError> {
let pairs = pair.into_inner().next().unwrap().into_inner();
let mut ret = String::with_capacity(pairs.as_str().len());
for pair in pairs {
let s = pair.as_str();
@ -209,9 +223,9 @@ fn build_expr_primary(pair: Pair<Rule>) -> Result<Expr, CozoError> {
Rule::dot_float | Rule::sci_float => Ok(Const(Value::Float(pair.as_str().replace('_', "").parse::<f64>()?))),
Rule::null => Ok(Const(Value::Null)),
Rule::boolean => Ok(Const(Value::Bool(pair.as_str() == "true"))),
Rule::quoted_string => Ok(Const(Value::OwnString(Box::new(parse_quoted_string(pair.into_inner().next().unwrap().into_inner())?)))),
Rule::s_quoted_string => Ok(Const(Value::OwnString(Box::new(parse_s_quoted_string(pair.into_inner().next().unwrap().into_inner())?)))),
Rule::raw_string => Ok(Const(Value::OwnString(Box::new(parse_raw_string(pair.into_inner())?)))),
Rule::quoted_string => Ok(Const(Value::OwnString(Box::new(parse_quoted_string(pair)?)))),
Rule::s_quoted_string => Ok(Const(Value::OwnString(Box::new(parse_s_quoted_string(pair)?)))),
Rule::raw_string => Ok(Const(Value::OwnString(Box::new(parse_raw_string(pair)?)))),
_ => {
println!("{:#?}", pair);
unimplemented!()
@ -228,6 +242,102 @@ pub fn parse_expr_from_str(inp: &str) -> Result<Expr, CozoError> {
build_expr(expr_tree)
}
fn parse_ident(pair: Pair<Rule>) -> String {
pair.as_str().to_string()
}
fn build_name_in_def(pair: Pair<Rule>, forbid_underscore: bool) -> Result<String, CozoError> {
let inner = pair.into_inner().next().unwrap();
let name = match inner.as_rule() {
Rule::ident => parse_ident(inner),
Rule::raw_string => parse_raw_string(inner)?,
Rule::s_quoted_string => parse_s_quoted_string(inner)?,
Rule::quoted_string => parse_quoted_string(inner)?,
_ => unreachable!()
};
if forbid_underscore && name.starts_with('_') {
Err(ReservedIdent)
} else {
Ok(name)
}
}
fn parse_col_name(pair: Pair<Rule>) -> Result<(String, bool), CozoError> {
let mut pairs = pair.into_inner();
let mut is_key = false;
let mut nxt_pair = pairs.next().unwrap();
if nxt_pair.as_rule() == Rule::key_marker {
is_key = true;
nxt_pair = pairs.next().unwrap();
}
Ok((build_name_in_def(nxt_pair, true)?, is_key))
}
fn build_col_entry(pair: Pair<Rule>) -> Result<(Col, bool), CozoError> {
let mut pairs = pair.into_inner();
let (name, is_key) = parse_col_name(pairs.next().unwrap())?;
Ok((Col {
name,
typ: Typing::Primitive(PrimitiveType::Int),
default: None
}, is_key))
}
fn build_col_defs(pair: Pair<Rule>) -> Result<(Vec<Col>, Vec<Col>), CozoError> {
let mut keys = vec![];
let mut cols = vec![];
for pair in pair.into_inner() {
let (col, is_key) = build_col_entry(pair)?;
if is_key {
keys.push(col)
} else {
cols.push(col)
}
}
Ok((keys, cols))
}
fn build_node_def(pair: Pair<Rule>, is_local: bool) -> Result<TableDef, CozoError> {
let mut inner = pair.into_inner();
let name = build_name_in_def(inner.next().unwrap(), true)?;
let (keys, cols) = build_col_defs(inner.next().unwrap())?;
Ok(TableDef::Node {
is_local,
name,
keys,
cols,
})
}
pub fn build_statements(pairs: Pairs<Rule>) -> Result<Vec<TableDef>, CozoError> {
let mut ret = vec![];
for pair in pairs {
match pair.as_rule() {
r @ (Rule::global_def | Rule::local_def) => {
let inner = pair.into_inner().next().unwrap();
let is_local = r == Rule::local_def;
// println!("{:?} {:?}", r, inner.as_rule());
match inner.as_rule() {
Rule::node_def => {
ret.push(build_node_def(inner, is_local)?);
}
_ => todo!()
}
}
Rule::EOI => {}
_ => unreachable!()
}
}
Ok(ret)
}
pub fn build_statements_from_str(inp: &str) -> Result<Vec<TableDef>, CozoError> {
let expr_tree = Parser::parse(Rule::file, inp)?;
build_statements(expr_tree)
}
#[cfg(test)]
mod tests {
use super::*;
@ -269,4 +379,16 @@ mod tests {
println!("{:#?}", parse_expr_from_str("null || true").unwrap().eval().unwrap());
println!("{:#?}", parse_expr_from_str("true && null").unwrap().eval().unwrap());
}
#[test]
fn definitions() {
println!("{:#?}", build_statements_from_str(r#"
local node "Person" {
*id: Int,
name: String,
email: ?String,
habits: [String]
}
"#).unwrap());
}
}

@ -12,6 +12,9 @@ pub enum CozoError {
#[error("Type mismatch")]
TypeError,
#[error("Reserved identifier")]
ReservedIdent,
#[error(transparent)]
ParseInt(#[from] std::num::ParseIntError),

@ -1,4 +1,4 @@
file = {SOI ~ ident ~ EOI}
file = _{SOI ~ statement* ~ EOI}
// whitespace
@ -125,4 +125,33 @@ dict_entry = _{ spreading | dict_accessor | dict_pair }
dict_accessor = { ident? ~ ("." ~ ident)+ }
dict_pair = {(ident | string) ~ ":" ~ expr}
scoped_dict = { ident ~ dict }
scoped_dict = { ident ~ dict }
name_in_def = {(ident | string)}
col_entry = { col_name ~ ":" ~ typing ~ ("=" ~ expr)? }
col_name = { key_marker? ~ name_in_def }
key_marker = { "*" }
typing = { nullable_marker? ~ (simple_type | tuple_type | list_type ) }
nullable_marker = {"?"}
simple_type = {ident}
tuple_type = {"("~ (typing ~ ",")+ ~")"}
list_type = {"[" ~ typing ~ "]"}
cols_def = { "{" ~ col_entry ~ ("," ~ col_entry)* ~ ","? ~ "}" }
col_list = {"(" ~ name_in_def ~ ("," ~ name_in_def)* ~ ","? ~ ")"}
node_def = { "node" ~ name_in_def ~ cols_def }
columns_def = { "columns" ~ name_in_def ~ ":" ~ name_in_def ~ cols_def }
edge_def = { "edge" ~
"[" ~ name_in_def ~ "]" ~ "-" ~ "(" ~ name_in_def ~ ")" ~ "->" ~ "[" ~ name_in_def ~ "]"
~ cols_def? }
index_def = { "index" ~ (name_in_def ~ ":")? ~ name_in_def ~ col_list }
struct_def = { "struct" ~ name_in_def ~ cols_def }
definition = _{ node_def | columns_def | edge_def | struct_def | index_def }
global_def = { "create" ~ definition }
local_def = { "local" ~ definition }
statement = _{ global_def | local_def }
Loading…
Cancel
Save