feat(ir, parser): Support if/while/break/logical expr/cmp in parser and ir generator
This commit is contained in:
+107
-19
@@ -1,4 +1,4 @@
|
||||
use crate::{diagnostic::span::Span, frontend::types::{TokenValue, TypeIdent}};
|
||||
use crate::{diagnostic::span::Span, frontend::types::{Token, TokenValue, TypeIdent}};
|
||||
use std::fmt;
|
||||
|
||||
pub struct CompileUnit {
|
||||
@@ -11,12 +11,12 @@ pub enum GlobalDeclStmt {
|
||||
|
||||
pub struct VarDeclStmt {
|
||||
pub values: Vec<VarDeclStmtValue>,
|
||||
pub span: Span,
|
||||
pub data_type: Type,
|
||||
pub type_span: Span,
|
||||
}
|
||||
pub struct VarDeclStmtValue {
|
||||
pub name: String,
|
||||
pub var_type: Type,
|
||||
pub span: Span,
|
||||
pub name_span: Span,
|
||||
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ pub struct FuncDeclStmt {
|
||||
pub return_type: Type,
|
||||
pub params: Vec<Param>,
|
||||
pub body: BlockStmt,
|
||||
pub span: Span,
|
||||
pub ret_type_span: Span,
|
||||
pub name_span: Span,
|
||||
}
|
||||
pub struct BlockStmt {
|
||||
pub statements: Vec<Statement>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
pub enum Statement {
|
||||
@@ -37,16 +37,46 @@ pub enum Statement {
|
||||
Block(BlockStmt),
|
||||
Expr(Expr),
|
||||
VarDecl(VarDeclStmt),
|
||||
If(IfStmt),
|
||||
While(WhileStmt),
|
||||
Break(BreakStmt),
|
||||
Continue(ContinueStmt),
|
||||
}
|
||||
impl Statement {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
Statement::Return(s) => s.span,
|
||||
Statement::Block(s) => s.span,
|
||||
Statement::Expr(s) => s.span,
|
||||
Statement::VarDecl(s) => s.span,
|
||||
}
|
||||
}
|
||||
// impl Statement {
|
||||
// pub fn span(&self) -> Span {
|
||||
// match self {
|
||||
// Statement::Return(s) => s.span,
|
||||
// Statement::Block(s) => s.span,
|
||||
// Statement::Expr(s) => s.span,
|
||||
// Statement::VarDecl(s) => s.span,
|
||||
// Statement::If(s) => s.span,
|
||||
// Statement::While(s) => s.span,
|
||||
// Statement::Break(s) => s.span,
|
||||
// Statement::Continue(s) => s.span,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
pub struct IfStmt {
|
||||
pub condition: Expr,
|
||||
pub then_branch: BlockStmt,
|
||||
pub ifelse_branch: Vec<IfElseBranch>,
|
||||
pub else_branch: Option<BlockStmt>,
|
||||
// pub span: Span,
|
||||
}
|
||||
pub struct IfElseBranch {
|
||||
pub condition: Expr,
|
||||
pub then_branch: BlockStmt,
|
||||
}
|
||||
pub struct WhileStmt {
|
||||
pub condition: Expr,
|
||||
pub body: BlockStmt,
|
||||
// pub span: Span,
|
||||
}
|
||||
pub struct BreakStmt {
|
||||
pub span: Span,
|
||||
}
|
||||
pub struct ContinueStmt {
|
||||
pub span: Span,
|
||||
}
|
||||
pub struct ReturnStmt {
|
||||
pub value: Option<Expr>,
|
||||
@@ -64,6 +94,10 @@ pub enum ExprValue {
|
||||
op: BinaryOp,
|
||||
rhs: Box<Expr>
|
||||
},
|
||||
UnaryOp {
|
||||
op: UnaryOp,
|
||||
operand: Box<Expr>,
|
||||
},
|
||||
FuncCall(String, Vec<Expr>),
|
||||
Assign {
|
||||
lvalue: Box<Expr>,
|
||||
@@ -74,8 +108,13 @@ pub enum ExprValue {
|
||||
pub enum BinaryOp {
|
||||
Add, Sub, Mul, Div, Mod,
|
||||
Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual,
|
||||
And, Or,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum UnaryOp {
|
||||
Add, Sub, Not,
|
||||
}
|
||||
impl BinaryOp {
|
||||
pub fn from_token_value(token_value: &TokenValue) -> Option<Self> {
|
||||
match token_value {
|
||||
@@ -90,10 +129,20 @@ impl BinaryOp {
|
||||
TokenValue::LessEqual => Some(BinaryOp::LessEqual),
|
||||
TokenValue::Greater => Some(BinaryOp::Greater),
|
||||
TokenValue::GreaterEqual => Some(BinaryOp::GreaterEqual),
|
||||
TokenValue::And => Some(BinaryOp::And),
|
||||
TokenValue::Or => Some(BinaryOp::Or),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn is_logical(&self) -> bool {
|
||||
matches!(self, BinaryOp::And | BinaryOp::Or)
|
||||
}
|
||||
pub fn is_cmp(&self) -> bool {
|
||||
matches!(self, BinaryOp::Equal | BinaryOp::NotEqual | BinaryOp::Less | BinaryOp::LessEqual | BinaryOp::Greater | BinaryOp::GreaterEqual)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Type {
|
||||
Int,
|
||||
@@ -110,7 +159,8 @@ impl From<TypeIdent> for Type {
|
||||
pub struct Param {
|
||||
pub name: String,
|
||||
pub param_type: Type,
|
||||
pub span: Span,
|
||||
pub name_span: Span,
|
||||
pub type_span: Span,
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileUnit {
|
||||
@@ -136,7 +186,7 @@ impl fmt::Display for VarDeclStmt {
|
||||
|
||||
impl fmt::Display for VarDeclStmtValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{} {}", self.var_type, self.name)
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,16 +209,42 @@ impl fmt::Display for Statement {
|
||||
Statement::Block(_) => write!(f, "BlockStmt"),
|
||||
Statement::Expr(_) => write!(f, "ExprStmt"),
|
||||
Statement::VarDecl(_) => write!(f, "VarDeclStmt"),
|
||||
Statement::If(_) => write!(f, "IfStmt"),
|
||||
Statement::While(_) => write!(f, "WhileStmt"),
|
||||
Statement::Break(_) => write!(f, "BreakStmt"),
|
||||
Statement::Continue(_) => write!(f, "ContinueStmt"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for IfStmt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "IfStmt")
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ReturnStmt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ReturnStmt")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for WhileStmt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "WhileStmt")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BreakStmt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "BreakStmt")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ContinueStmt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ContinueStmt")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Expr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.value)
|
||||
@@ -183,6 +259,7 @@ impl fmt::Display for ExprValue {
|
||||
ExprValue::BinaryOp { op, .. } => write!(f, "BinaryOp({})", op),
|
||||
ExprValue::FuncCall(name, _) => write!(f, "FuncCall({})", name),
|
||||
ExprValue::Assign { .. } => write!(f, "Assign"),
|
||||
ExprValue::UnaryOp { op, .. } => write!(f, "UnaryOp({})", op),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,11 +284,22 @@ impl fmt::Display for BinaryOp {
|
||||
BinaryOp::LessEqual => "<=",
|
||||
BinaryOp::Greater => ">",
|
||||
BinaryOp::GreaterEqual => ">=",
|
||||
BinaryOp::And => "&&",
|
||||
BinaryOp::Or => "||",
|
||||
};
|
||||
write!(f, "{}", op)
|
||||
}
|
||||
}
|
||||
impl fmt::Display for UnaryOp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let op = match self {
|
||||
UnaryOp::Add => "+",
|
||||
UnaryOp::Sub => "-",
|
||||
UnaryOp::Not => "!",
|
||||
};
|
||||
write!(f, "{}", op)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
||||
Reference in New Issue
Block a user