Skip to content

Commit

Permalink
[YCC] implemented more of the parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Nov 10, 2024
1 parent b2ac92f commit b0a3772
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 24 deletions.
40 changes: 23 additions & 17 deletions tools/ycc/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub enum Visibility {

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AstTypeMeta {
Void,

Bool,
Char,
Short,
Expand Down Expand Up @@ -37,40 +39,41 @@ pub enum TopLevelStmt {

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FuncStmt {
name: String,
visibility: Visibility,
return_type: AstType,
args: Vec<(String, AstType)>,
body: Vec<Stmt>,
pub name: String,
pub visibility: Visibility,
pub return_type: AstType,
pub args: Vec<(String, AstType)>,
pub body: Vec<Stmt>,
pub only_ty_indector: bool,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GlobalStmt {
name: String,
visibility: Visibility,
ty: AstType,
initializer: Option<Expr>,
pub name: String,
pub visibility: Visibility,
pub ty: AstType,
pub initializer: Option<Expr>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstStmt {
name: String,
visibility: Visibility,
ty: AstType,
initializer: Expr,
pub name: String,
pub visibility: Visibility,
pub ty: AstType,
pub initializer: Expr,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumStmt {
name: String,
values: Vec<(String, Option<Expr>)>,
pub name: String,
pub values: Vec<(String, Option<Expr>)>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructStmt {
name: String,
pub name: String,

fields: Vec<(String, AstType)>,
pub fields: Vec<(String, AstType)>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -106,6 +109,9 @@ pub enum Stmt {
Return {
value: Expr,
},
Block {
body: Vec<Stmt>
}
}

impl PartialEq for Expr {
Expand Down
228 changes: 221 additions & 7 deletions tools/ycc/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ impl<'a> Parser<'a> {

pub fn parse(&mut self) -> Option<()> {
while self.tokens.len() != 0 {
match self.advance().ty {
let cur = self.current()?.to_owned();

match cur.ty {
TokenType::Unsigned => self.parse_func_or_global(),
TokenType::Signed => self.parse_func_or_global(),
TokenType::Char => self.parse_func_or_global(),
Expand All @@ -52,7 +54,7 @@ impl<'a> Parser<'a> {
TokenType::Volatile => todo!("volatiles are currently unsupported"),
_ => {
self.errors.push(YccError {
loc: self.pos(),
loc: cur.pos,
head: "unexpected token",
where_string: format!("unexpected token"),
});
Expand All @@ -70,14 +72,222 @@ impl<'a> Parser<'a> {
}

fn parse_func_or_global(&mut self) -> Option<()> {
todo!()
let ty = self.parse_type()?;
let name = self.get_ident()?;

let tok = self.advance().to_owned();

match tok.ty {
TokenType::Equal => self.parse_global(ty, name),
TokenType::LeftParan => self.parse_func(ty, name, false),
_ => {
self.errors.push(YccError {
loc: tok.pos,
head: "expected either `=` or `(`",
where_string: "expected either `=` or `(`".into()
});
None
}
}
}

fn parse_func(&mut self) -> Option<()> {
todo!()
fn parse_type(&mut self) -> Option<AstType> {
let current = self.advance().to_owned();

let mut out_ty = AstType {
meta: AstTypeMeta::Int,
signed: false,
unsigned: false,
};

match current.ty {
TokenType::Unsigned => {out_ty.signed = false; out_ty.unsigned = true},
TokenType::Signed => {out_ty.signed = true; out_ty.unsigned = false},
TokenType::Char => out_ty.meta = AstTypeMeta::Char,
TokenType::Bool => out_ty.meta = AstTypeMeta::Bool,
TokenType::Short => out_ty.meta = AstTypeMeta::Short,
TokenType::Int => out_ty.meta = AstTypeMeta::Int,
TokenType::Long => out_ty.meta = AstTypeMeta::Long,
TokenType::Float => out_ty.meta = AstTypeMeta::Float,
TokenType::Double => out_ty.meta = AstTypeMeta::Double,
TokenType::Void => out_ty.meta = AstTypeMeta::Void,
TokenType::Struct => out_ty.meta = AstTypeMeta::Struct,
TokenType::Enum => out_ty.meta = AstTypeMeta::Enum,

_ => {
self.errors.push(YccError {
loc: self.pos(),
head: "expected valid token for types",
where_string: "unexpected token".into(),
});
}
}

if out_ty.signed {
let current = self.advance().to_owned();
match current.ty {
TokenType::Char => out_ty.meta = AstTypeMeta::Char,
TokenType::Bool => out_ty.meta = AstTypeMeta::Bool,
TokenType::Short => out_ty.meta = AstTypeMeta::Short,
TokenType::Int => out_ty.meta = AstTypeMeta::Int,
TokenType::Long => out_ty.meta = AstTypeMeta::Long,
TokenType::Float => out_ty.meta = AstTypeMeta::Float,
TokenType::Double => out_ty.meta = AstTypeMeta::Double,
TokenType::Void => out_ty.meta = AstTypeMeta::Void,
TokenType::Struct => out_ty.meta = AstTypeMeta::Struct,
TokenType::Enum => out_ty.meta = AstTypeMeta::Enum,

_ => {
self.errors.push(YccError {
loc: self.pos(),
head: "expected valid token for types",
where_string: "unexpected token".into(),
});
}
}
}

if !out_ty.unsigned { out_ty.signed = true; }

Some(out_ty)
}

fn parse_global(&mut self) -> Option<()> {
fn parse_return(&mut self) -> Option<Stmt> {
let stmt = Stmt::Return {
value: self.parse_expr()?
};

if let TokenType::Semicolon = self.advance().ty {} else {
self.errors.push(YccError {
loc: self.pos(),
head: "expected semicolon after return",
where_string: "expected `;`".into(),
});
return None;
}

Some(stmt)
}

fn parse_stmt(&mut self) -> Option<Stmt> {
let current = self.advance().to_owned();

let stmt = match current.ty {
TokenType::Return => self.parse_return()?,
_ => {
self.errors.push(YccError {
loc: self.pos(),
head: "unimplemented",
where_string: format!("this statment is still unimplemented: {:?}", current.ty)
});
self.critical_error = true;
return None;
}
};

Some(stmt)
}

fn parse_block(&mut self) -> Option<Vec<Stmt>> {
if let TokenType::LeftBracket = self.advance().ty {} else {
self.errors.push(YccError {
loc: self.pos(),
head: "expected left bracket",
where_string: "expected `{`".into(),
});
self.critical_error = true;
return None;
}

let mut stmts = Vec::new();

loop {
if let TokenType::RightBracket = self.current()?.ty {
self.advance(); // }
break;
}

stmts.push(self.parse_stmt()?);
}

Some(stmts)
}

fn get_ident(&mut self) -> Option<String> {
let current = self.advance().to_owned().to_owned();

if let TokenType::Ident(ident) = current.ty {
return Some(ident)
}

self.errors.push(YccError {
loc: self.pos(),
head: "expected ident",
where_string: "expected ident".into(),
});

None
}

fn parse_func(&mut self, ty: AstType, name: String, extrn: bool) -> Option<()> {
let mut args = Vec::new();

let mut first = true;

loop {
if !first {
let current = self.advance();

if let TokenType::Comma = current.ty {} else {
self.errors.push(YccError {
loc: self.pos(),
head: "expected comma",
where_string: "expected `,`".to_owned()
});
}
}

let arg_ty = self.parse_type()?;
let arg_name = self.get_ident()?;

args.push((arg_name, arg_ty));

first = false;

if let TokenType::RightParan = self.current()?.ty {
self.advance(); // )
break;
}
}

if let TokenType::Semicolon = self.current()?.ty {
self.out.push(TopLevelStmt::Func(FuncStmt {
name: name,
visibility: if extrn { Visibility::Extern } else { Visibility::Private },
return_type: ty,
args: args,
body: Vec::new(),
only_ty_indector: true,
}));

return Some(())
}

let body = self.parse_block()?;

self.out.push(TopLevelStmt::Func(FuncStmt {
name: name,
visibility: if extrn { Visibility::Extern } else { Visibility::Private },
return_type: ty,
args: args,
body: body,
only_ty_indector: false,
}));

Some(())
}

fn parse_global(&mut self, ty: AstType, name: String) -> Option<()> {
todo!()
}

Expand Down Expand Up @@ -113,6 +323,10 @@ impl<'a> Parser<'a> {

#[inline]
fn current(&self) -> Option<&&Token> {
self.tokens.back()
self.tokens.front()
}

fn parse_expr(&mut self) -> Option<Expr> {
todo!()
}
}

0 comments on commit b0a3772

Please sign in to comment.