Skip to content

Commit

Permalink
feat(ast): var and const declarations in stmt
Browse files Browse the repository at this point in the history
Co-authored-by: ishwar00 <ishwargowda100@gmail.com>
  • Loading branch information
Samyak2 and ishwar00 committed Sep 30, 2023
1 parent b3c1ea0 commit 4268258
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 26 deletions.
195 changes: 170 additions & 25 deletions compiler/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub struct FnDecl<'i> {
pub name: Ident<'i>,
pub params: Vec<FnParameterDecl<'i>>,
pub result_kind: Option<Kind<'i>>,
pub body: Vec<Statement<'i>>,
pub body: StatementList<'i>,
pub span: Span<'i>,
}

Expand Down Expand Up @@ -125,11 +125,7 @@ impl<'i> Node<'i> for FnDecl<'i> {
params = param_decls.into_iter().map(|p| p.into()).collect();
}

let body = body_pair
.into_inner()
.filter(|p| p.as_rule() != Rule::Semicolon)
.map(Statement::parse)
.collect::<Result<_, _>>()?;
let body = StatementList::parse(body_pair)?;

Ok(Self {
name,
Expand Down Expand Up @@ -183,10 +179,13 @@ impl<'i> Node<'i> for ParameterList<'i> {
});
}
}
_ => {
invalid_rule => {
return Err(BakugoParsingError::new(
first.as_span(),
"Expected only types and identifiers in parameters".to_owned(),
format!(
"Expected only types and identifiers in parameters. Got {:?}",
invalid_rule
),
BakugoParsingErrorKind::InternalError,
))
}
Expand Down Expand Up @@ -237,7 +236,7 @@ impl<'i> From<ParameterDecl<'i>> for FnParameterDecl<'i> {
}
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Kind<'i> {
Simple {
name: String,
Expand Down Expand Up @@ -272,20 +271,26 @@ impl<'i> Node<'i> for Kind<'i> {
kinds.push(Kind::parse(inner)?);
}
}
_ => {
invalid_rule => {
return Err(BakugoParsingError::new(
span,
"expected type but got something else".to_owned(),
format!(
"expected type but got something else. got: {:?}.",
invalid_rule
),
BakugoParsingErrorKind::InternalError,
))
}
}
Ok(Self::Tuple { kinds, span })
}
_ => {
invalid_rule => {
return Err(BakugoParsingError::new(
inner.as_span(),
"expected type but got something else".to_owned(),
format!(
"expected type but got something else. got: {:?}.",
invalid_rule
),
BakugoParsingErrorKind::InternalError,
))
}
Expand Down Expand Up @@ -350,9 +355,9 @@ impl<'i> Node<'i> for Expr<'i> {
span: pair.as_span(),
}),
Rule::FunctionCall => Ok(Self::parse_expr(pair.into_inner())?),
_ => Err(BakugoParsingError::new(
invalid_rule => Err(BakugoParsingError::new(
pair.as_span(),
"got a non expression".to_owned(),
format!("expected an expression. got {:?}", invalid_rule),
BakugoParsingErrorKind::InternalError,
)),
}
Expand Down Expand Up @@ -397,9 +402,9 @@ impl<'i> Expr<'i> {
.map_primary(|primary| match primary.as_rule() {
// TODO: check if this match is needed
Rule::IntLit | Rule::Ident | Rule::FunctionCall => Expr::parse(primary),
_ => Err(BakugoParsingError::new(
invalid_rule => Err(BakugoParsingError::new(
primary.as_span(),
"got a non expression".to_owned(),
format!("expected an expresion. got {:?}", invalid_rule),
BakugoParsingErrorKind::InternalError,
)),
})
Expand All @@ -415,9 +420,11 @@ impl<'i> Expr<'i> {
_ => {
return Err(BakugoParsingError::new(
op.as_span(),
// TODO: use a general function to result this kinds of errors.
// also include the Rule that was found here in the error message.
"got a non operator".to_owned(),
BakugoParsingErrorKind::InternalError,
))
));
}
};
Ok(Expr::BinaryExpr {
Expand Down Expand Up @@ -504,21 +511,159 @@ impl<'i> Expr<'i> {
#[derive(Debug)]
pub enum Statement<'i> {
Return, // TODO: add expression list
Declaration(Decl<'i>),
Expression(Expr<'i>),
}

impl<'i> Node<'i> for Statement<'i> {
#[derive(Debug)]
pub struct StatementList<'i>(Vec<Statement<'i>>);

#[derive(Debug)]
pub enum Decl<'i> {
Var(VarConstDecl<'i>),
Const(VarConstDecl<'i>),
Kind(KindDecl<'i>),
}

#[derive(Debug)]
pub struct VarConstDecl<'i> {
pub name: Ident<'i>,
pub kind: Option<Kind<'i>>,
pub expr: Expr<'i>,
}

#[derive(Debug)]
pub struct KindDecl<'i> {
pub name: Ident<'i>,
pub kind: Kind<'i>,
}

impl<'i> StatementList<'i> {
fn parse_decl(
parsed_stmts: &mut Vec<Statement<'i>>,
pair: Pair<'i, Rule>,
) -> Result<(), BakugoParsingError<'i>> {
match pair.as_rule() {
Rule::VarDecl | Rule::ConstDecl => {
let is_var = pair.as_rule() == Rule::VarDecl;
let var_specs = pair.into_inner().filter(|p| p.as_rule() != Rule::Semicolon);

for var_spec in var_specs {
let var_spec_span = var_spec.as_span();

if !matches!(var_spec.as_rule(), Rule::VarSpec | Rule::ConstSpec) {
return Err(BakugoParsingError::new(
var_spec.as_span(),
format!(
"expected a var or const decl. got {:?}.",
var_spec.as_rule()
),
BakugoParsingErrorKind::InternalError,
));
}

let mut var_spec_inner = var_spec.into_inner();
let idents = var_spec_inner.next().unwrap();

let maybe_kind = var_spec_inner.next().unwrap();
let exprs;
let kind = if maybe_kind.as_rule() == Rule::Type {
exprs = var_spec_inner.next().unwrap();
Some(Kind::parse(maybe_kind)?)
} else {
exprs = maybe_kind;
None
};

let idents = idents
.into_inner()
.map(Ident::parse)
.collect::<Result<Vec<Ident>, _>>()?;
let exprs = exprs
.into_inner()
.filter(|p| p.as_rule() != Rule::Comma)
.map(Expr::parse)
.collect::<Result<Vec<Expr>, _>>()?;

if idents.len() != exprs.len() {
return Err(BakugoParsingError::new(
var_spec_span,
format!(
"Number of expressions ({}) does not match number of identifers ({})",
exprs.len(),
idents.len()
),
BakugoParsingErrorKind::SyntaxError,
));
}

for (ident, expr) in idents.into_iter().zip(exprs.into_iter()) {
let decl = VarConstDecl {
name: ident,
kind: kind.clone(),
expr,
};
parsed_stmts.push(Statement::Declaration(if is_var {
Decl::Var(decl)
} else {
Decl::Const(decl)
}))
}
}
}

Rule::TypeDecl => {}

invalid_rule => {
return Err(BakugoParsingError::new(
pair.as_span(),
format!("expected a declaration. got {:?}", invalid_rule),
BakugoParsingErrorKind::InternalError,
))
}
}

Ok(())
}
}

impl<'i> Node<'i> for StatementList<'i> {
fn parse(pair: Pair<'i, Rule>) -> Result<Self, BakugoParsingError> {
match pair.as_rule() {
Rule::ExpressionStmt => {
let expr = Expr::parse_expr(pair.into_inner())?;
Ok(Statement::Expression(expr))
Rule::StatementList => {
let mut parsed_stmts = Vec::new();

for pair in pair.into_inner() {
match pair.as_rule() {
Rule::ExpressionStmt => {
let expr = Expr::parse_expr(pair.into_inner())?;
parsed_stmts.push(Statement::Expression(expr))
}

Rule::ReturnStmt => parsed_stmts.push(Statement::Return),

Rule::Semicolon => {}

Rule::Declaration => {
Self::parse_decl(&mut parsed_stmts, pair.into_inner().next().unwrap())?
}

invalid_rule => {
return Err(BakugoParsingError::new(
pair.as_span(),
format!("expected a statement. got {:?}.", invalid_rule),
BakugoParsingErrorKind::InternalError,
))
}
}
}

Ok(Self(parsed_stmts))
}
Rule::ReturnStmt => Ok(Statement::Return),
_ => {
invalid_rule => {
return Err(BakugoParsingError::new(
pair.as_span(),
"got a statement".to_owned(),
format!("expected a statement list. got {:?}.", invalid_rule),
BakugoParsingErrorKind::InternalError,
))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/bakugo.pest
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ TypeSpec = { TypeDef }
TypeDef = { Ident ~ Type }

// Variable declaration
VarDecl = { "var" ~ (VarSpec | "(" ~ (VarSpec ~ Semicolon)* ~ ")") }
VarDecl = { "var" ~ (VarSpec | "(" ~ (VarSpec ~ Semicolon)+ ~ ")") }
VarSpec = { IdentifierList ~ ((Type ~ ("=" ~ ExpressionList)?) | ("=" ~ ExpressionList)) }

// Function declaration
Expand Down
11 changes: 11 additions & 0 deletions compiler/tests/examples/06_var_decl.bakugo
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
func abc() {
var a = 10;
var (
b = 10;
c int = 20;
c, d, e int = 30, 40, 50;
// f, g, h = 40;
i, j, k = 50, 60, 70;
// i, j, k = 60, 70;
);
};

0 comments on commit 4268258

Please sign in to comment.