Compare commits
5 Commits
323d3342a3
...
f338f07e7d
Author | SHA1 | Date | |
---|---|---|---|
f338f07e7d | |||
cb297bf75e | |||
d5f02cf1d5 | |||
b8728b8f8d | |||
d2b0e57ce6 |
|
@ -1,6 +1,4 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
|
||||
pub struct Loc {
|
||||
|
@ -9,6 +7,7 @@ pub struct Loc {
|
|||
col: usize,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Loc {
|
||||
pub fn new(s: impl ToString, line: usize, col: usize) -> Self {
|
||||
Self {
|
||||
|
@ -27,6 +26,28 @@ impl Loc {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocBox<T: Clone + Debug> {
|
||||
inner: T,
|
||||
loc: Loc
|
||||
}
|
||||
|
||||
impl<T: Clone + Debug> LocBox<T> {
|
||||
pub fn new(loc: &Loc, inner: T) -> Self {
|
||||
Self { loc: loc.clone(), inner }
|
||||
}
|
||||
pub fn inner(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
pub fn inner_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
pub fn loc(&self) -> &Loc {
|
||||
&self.loc
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Loc {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}:{}:{}", self.file, self.line, self.col)
|
||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -7,7 +7,7 @@ mod logger;
|
|||
|
||||
|
||||
|
||||
fn main() -> ExitCode {
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let cli = mclangc::cli::CliArgs::parse();
|
||||
cli.set_log_level();
|
||||
cli.validate();
|
||||
|
@ -15,25 +15,17 @@ fn main() -> ExitCode {
|
|||
let fp = PathBuf::from(file);
|
||||
if !fp.exists() {
|
||||
error!("File {fp:?} doesnt exits, exiting");
|
||||
return ExitCode::FAILURE;
|
||||
anyhow::bail!("")
|
||||
}
|
||||
|
||||
let data = std::fs::read_to_string(fp).unwrap();
|
||||
info!("Tokenising {file}");
|
||||
let Ok(tokens) = mclangc::tokeniser::tokenise(&data, &file) else {
|
||||
error!("Failed to tokenise file, exiting");
|
||||
return ExitCode::FAILURE;
|
||||
};
|
||||
let tokens = mclangc::tokeniser::tokenise(&data, &file)?;
|
||||
info!("Parsing {file}");
|
||||
let Ok(prog) = mclangc::parser::parse_program(tokens) else {
|
||||
error!("Failed to parse file, exiting");
|
||||
return ExitCode::FAILURE;
|
||||
};
|
||||
let mut prog = mclangc::parser::parse_program(tokens)?;
|
||||
info!("Validating {file}");
|
||||
let Ok(validated) = mclangc::validator::validate_code(&prog) else {
|
||||
error!("Failed to validate file, exiting");
|
||||
return ExitCode::FAILURE;
|
||||
};
|
||||
mclangc::validator::validate_code(&mut prog)?;
|
||||
dbg!(&prog);
|
||||
}
|
||||
ExitCode::SUCCESS
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,55 +1,55 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::tokeniser::tokentype::*;
|
||||
use crate::{common::loc::LocBox, tokeniser::tokentype::*};
|
||||
|
||||
use super::{typ::Type, Ast};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expr {
|
||||
// Comment(Comment),
|
||||
Group(Box<Expr>),
|
||||
Group(Box<LocBox<Expr>>),
|
||||
UnOp {
|
||||
typ: Punctuation,
|
||||
right: Box<Expr>,
|
||||
right: Box<LocBox<Expr>>,
|
||||
},
|
||||
BinOp {
|
||||
typ: Punctuation,
|
||||
left: Box<Expr>,
|
||||
right: Box<Expr>,
|
||||
left: Box<LocBox<Expr>>,
|
||||
right: Box<LocBox<Expr>>,
|
||||
},
|
||||
Literal(super::literal::Literal),
|
||||
ArrayIndex {
|
||||
name: Box<Expr>,
|
||||
index: Box<Expr>,
|
||||
name: Box<LocBox<Expr>>,
|
||||
index: Box<LocBox<Expr>>,
|
||||
},
|
||||
Path(Path),
|
||||
Call {
|
||||
path: Box<Expr>,
|
||||
params: CallParams, // Expr ~ (, Expr)*
|
||||
path: Box<LocBox<Expr>>,
|
||||
params: CallParams, // LocBox<Expr> ~ (, Expr)*
|
||||
},
|
||||
//MethodCall {
|
||||
// var_name: Box<Expr>,
|
||||
// var_name: Box<LocBox<Expr>>,
|
||||
// method_name: Ident,
|
||||
// params: CallParams,
|
||||
//},
|
||||
|
||||
/// the left side only exists on the /.|->/ chain
|
||||
FieldAccess {
|
||||
left: Box<Option<Expr>>,
|
||||
right: Box<Expr>,
|
||||
left: Box<Option<LocBox<Expr>>>,
|
||||
right: Box<LocBox<Expr>>,
|
||||
},
|
||||
PtrFieldAccess {
|
||||
left: Box<Option<Expr>>,
|
||||
right: Box<Expr>,
|
||||
left: Box<Option<LocBox<Expr>>>,
|
||||
right: Box<LocBox<Expr>>,
|
||||
},
|
||||
ForLoop {
|
||||
init: Box<Ast>,
|
||||
test: Box<Expr>,
|
||||
on_loop: Box<Expr>,
|
||||
test: Box<LocBox<Expr>>,
|
||||
on_loop: Box<LocBox<Expr>>,
|
||||
body: Block,
|
||||
},
|
||||
WhileLoop {
|
||||
test: Box<Expr>,
|
||||
test: Box<LocBox<Expr>>,
|
||||
body: Block,
|
||||
},
|
||||
InfLoop {
|
||||
|
@ -58,14 +58,14 @@ pub enum Expr {
|
|||
If(IfExpr),
|
||||
Struct {
|
||||
path: Path,
|
||||
fields: HashMap<Ident, Expr>,
|
||||
fields: HashMap<Ident, LocBox<Expr>>,
|
||||
},
|
||||
Return(Box<Option<Expr>>),
|
||||
Return(Box<Option<LocBox<Expr>>>),
|
||||
Break,
|
||||
Continue,
|
||||
Cast {
|
||||
left: Box<Expr>,
|
||||
right: Box<Type>
|
||||
left: Box<LocBox<Expr>>,
|
||||
right: Box<LocBox<Type>>
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ impl Expr {
|
|||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CallParams(pub Vec<Expr>);
|
||||
pub struct CallParams(pub Vec<LocBox<Expr>>);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Block(pub Vec<Ast>);
|
||||
|
@ -90,7 +90,7 @@ pub struct Path(pub Vec<Ident>);
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IfExpr {
|
||||
pub test: Box<Expr>,
|
||||
pub test: Box<LocBox<Expr>>,
|
||||
pub body: Block,
|
||||
pub else_if: Option<IfBranchExpr>
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::tokeniser::tokentype::*;
|
||||
use crate::{common::loc::LocBox, tokeniser::tokentype::*};
|
||||
|
||||
use super::{expr::Expr, typ::Type, Ast};
|
||||
|
||||
|
@ -10,10 +10,10 @@ pub enum Literal {
|
|||
Ident(Ident),
|
||||
String(TString),
|
||||
Char(Char),
|
||||
Array(Vec<Expr>),
|
||||
Array(Vec<LocBox<Expr>>),
|
||||
ArrayRepeat {
|
||||
typ: Box<Type>,
|
||||
count: Box<Expr>,
|
||||
typ: Box<LocBox<Type>>,
|
||||
count: Box<LocBox<Expr>>,
|
||||
},
|
||||
Struct {
|
||||
name: Ident,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use typ::Type;
|
||||
use statement::{Enum, Function, Struct};
|
||||
|
||||
use crate::{common::loc::LocBox, validator::predefined::TypeType};
|
||||
pub use crate::tokeniser::tokentype::*;
|
||||
|
||||
pub mod expr;
|
||||
|
@ -12,17 +13,17 @@ pub mod typ;
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Program {
|
||||
pub ast: expr::Block,
|
||||
pub structs: HashMap<Ident, HashMap<Ident, usize>>,
|
||||
pub enums: HashMap<Ident, usize>,
|
||||
pub types: HashMap<Type, Type>,
|
||||
pub functions: HashMap<Ident, (Vec<(Ident, Type)>, Type)>,
|
||||
pub member_functions: HashMap<Ident, HashMap<Ident, (Vec<(Ident, Type)>, Type)>>,
|
||||
pub structs: HashMap<Ident, LocBox<Struct>>,
|
||||
pub enums: HashMap<Ident, LocBox<Enum>>,
|
||||
pub types: HashMap<Ident, TypeType>,
|
||||
pub functions: HashMap<Ident, LocBox<Function>>,
|
||||
pub member_functions: HashMap<Ident, HashMap<Ident, LocBox<Function>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Ast {
|
||||
Expr(expr::Expr),
|
||||
Statement(statement::Statement),
|
||||
Expr(LocBox<expr::Expr>),
|
||||
Statement(LocBox<statement::Statement>),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,44 +1,56 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::common::{loc::LocBox, Loc};
|
||||
|
||||
use super::{expr::{Block, Expr}, typ::Type, Ident, TString};
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Statement {
|
||||
Fn {
|
||||
struct_name: Option<Ident>,
|
||||
name: Ident,
|
||||
params: Vec<(Ident, Type)>,
|
||||
ret_type: Option<Type>,
|
||||
qual_const: bool,
|
||||
qual_extern: Option<TString>, // abi
|
||||
body: Option<Block>, // If None then its a type declaration
|
||||
},
|
||||
TypeAlias {
|
||||
name: Ident,
|
||||
typ: Type,
|
||||
},
|
||||
Struct {
|
||||
name: Ident,
|
||||
fields: Vec<(Ident, Type)>,
|
||||
},
|
||||
Enum {
|
||||
name: Ident,
|
||||
fields: Vec<Ident>,
|
||||
},
|
||||
Fn(Function),
|
||||
TypeAlias(TypeAlias),
|
||||
Struct(Struct),
|
||||
Enum(Enum),
|
||||
ConstVar {
|
||||
name: Ident,
|
||||
typ: Type,
|
||||
val: Expr
|
||||
typ: LocBox<Type>,
|
||||
val: LocBox<Expr>
|
||||
},
|
||||
StaticVar {
|
||||
name: Ident,
|
||||
typ: Type,
|
||||
val: Expr,
|
||||
typ: LocBox<Type>,
|
||||
val: LocBox<Expr>,
|
||||
},
|
||||
Let {
|
||||
name: Ident,
|
||||
typ: Option<Type>,
|
||||
val: Option<Expr>,
|
||||
typ: Option<LocBox<Type>>,
|
||||
val: Option<LocBox<Expr>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeAlias {
|
||||
pub name: Ident,
|
||||
pub typ: LocBox<Type>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Struct {
|
||||
pub name: Ident,
|
||||
pub fields: Vec<(Ident, LocBox<Type>)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Enum {
|
||||
pub name: Ident,
|
||||
pub fields: Vec<Ident>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Function {
|
||||
pub struct_name: Option<Ident>,
|
||||
pub name: Ident,
|
||||
pub params: Vec<(Ident, LocBox<Type>)>,
|
||||
pub ret_type: Option<LocBox<Type>>,
|
||||
pub qual_const: bool,
|
||||
pub qual_extern: Option<TString>, // abi
|
||||
pub body: Option<Block>, // If None then its a type declaration
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use super::{expr::Expr, Ident, Number};
|
||||
use crate::common::{loc::LocBox, Loc};
|
||||
|
||||
use super::{expr::Expr, Ident};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Type {
|
||||
|
@ -11,7 +13,7 @@ pub enum Type {
|
|||
},
|
||||
ArrayRepeat {
|
||||
inner: Box<Type>,
|
||||
count: Expr,
|
||||
count: LocBox<Expr>,
|
||||
},
|
||||
Owned(Ident),
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
use crate::{debug, error, lerror, parser::{typ::parse_type, Punctuation}, tokeniser::Token};
|
||||
use crate::{common::loc::LocBox, debug, error, lerror, parser::{typ::parse_type, Punctuation}, tokeniser::Token};
|
||||
|
||||
use super::{ast::{expr::{Block, CallParams, Expr, IfBranchExpr, IfExpr, Path}, literal::Literal, TokenType}, parse_item, utils, Delimiter, Keyword};
|
||||
|
||||
|
@ -37,14 +37,14 @@ const BINOP_LIST: &[TokenType] = &[
|
|||
TokenType::Punct(Punctuation::Ge),
|
||||
];
|
||||
|
||||
pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool) -> Result<Option<Expr>> {
|
||||
pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool) -> Result<Option<LocBox<Expr>>> {
|
||||
let res = if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenL)) {
|
||||
Some(parse_group(tokens)?)
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::ident("")) {
|
||||
let p = parse_path(tokens)?;
|
||||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) {
|
||||
Some(parse_struct_literal(tokens, p.unwrap_path())?)
|
||||
Some(parse_struct_literal(tokens, p.inner().unwrap_path())?)
|
||||
} else {
|
||||
Some(p)
|
||||
}
|
||||
|
@ -73,37 +73,33 @@ pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool
|
|||
return Ok(Some(parse_inf_loop(tokens)?));
|
||||
} else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Return)) {
|
||||
return Ok(Some(parse_return(tokens)?));
|
||||
} else if let Some(_) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Break)) {
|
||||
return Ok(Some(Expr::Break));
|
||||
} else if let Some(_) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Continue)) {
|
||||
return Ok(Some(Expr::Continue));
|
||||
} else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::If)) {
|
||||
return Ok(Some(Expr::If(parse_if(tokens)?)));
|
||||
} else if let Some(kw) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Break)) {
|
||||
return Ok(Some(LocBox::new(kw.loc(), Expr::Break)));
|
||||
} else if let Some(kw) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Continue)) {
|
||||
return Ok(Some(LocBox::new(kw.loc(), Expr::Continue)));
|
||||
} else if let Some(kw) = utils::check(tokens, TokenType::Keyword(Keyword::If)) {
|
||||
return Ok(Some(LocBox::new(&kw.loc().clone(), Expr::If(parse_if(tokens)?))));
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
|
||||
if let Some(res) = res {
|
||||
// check for binop
|
||||
let res = match res {
|
||||
_ if utils::check(tokens, TokenType::Punct(Punctuation::Fieldaccess)).is_some() => {
|
||||
parse_field_access(tokens, res)?
|
||||
}
|
||||
_ if utils::check(tokens, TokenType::Punct(Punctuation::Arrow)).is_some() => {
|
||||
parse_ptr_field_access(tokens, res)?
|
||||
}
|
||||
_ if utils::check(tokens, TokenType::Delim(Delimiter::ParenL)).is_some() => {
|
||||
parse_fn_call(tokens, res)?
|
||||
}
|
||||
_ if utils::check(tokens, TokenType::Keyword(Keyword::As)).is_some() => {
|
||||
parse_cast(tokens, res)?
|
||||
}
|
||||
_ if utils::check(tokens, TokenType::Delim(Delimiter::SquareL)).is_some() => {
|
||||
parse_array_index(tokens, res)?
|
||||
}
|
||||
_ => res
|
||||
};
|
||||
if let Some(mut res) = res {
|
||||
if utils::check(tokens, TokenType::Punct(Punctuation::Fieldaccess)).is_some() {
|
||||
res = parse_field_access(tokens, res)?;
|
||||
}
|
||||
if utils::check(tokens, TokenType::Punct(Punctuation::Arrow)).is_some() {
|
||||
res =parse_ptr_field_access(tokens, res)?;
|
||||
}
|
||||
if utils::check(tokens, TokenType::Delim(Delimiter::ParenL)).is_some() {
|
||||
res = parse_fn_call(tokens, res)?;
|
||||
}
|
||||
if utils::check(tokens, TokenType::Keyword(Keyword::As)).is_some() {
|
||||
res = parse_cast(tokens, res)?;
|
||||
}
|
||||
if utils::check(tokens, TokenType::Delim(Delimiter::SquareL)).is_some() {
|
||||
res = parse_array_index(tokens, res)?;
|
||||
}
|
||||
|
||||
if let Some(_) = utils::check_from_many(tokens, BINOP_LIST) {
|
||||
return Ok(Some(parse_binop(tokens, res, precedence)?));
|
||||
|
@ -117,19 +113,19 @@ pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
fn parse_return(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Return));
|
||||
fn parse_return(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Return), "")?;
|
||||
let item = parse_expr(tokens, 0, true)?;
|
||||
Ok(Expr::Return(Box::new(item)))
|
||||
Ok(LocBox::new(kw.loc(), Expr::Return(Box::new(item))))
|
||||
}
|
||||
|
||||
fn parse_cast(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::As), "")?;
|
||||
fn parse_cast(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::As), "")?;
|
||||
let typ = parse_type(tokens)?;
|
||||
Ok(Expr::Cast {
|
||||
Ok(LocBox::new(kw.loc(), Expr::Cast {
|
||||
left: Box::new(left),
|
||||
right: Box::new(typ)
|
||||
})
|
||||
}))
|
||||
}
|
||||
fn parse_if(tokens: &mut Vec<Token>) -> Result<IfExpr> {
|
||||
let loc = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::If), "")?;
|
||||
|
@ -172,50 +168,50 @@ fn parse_if(tokens: &mut Vec<Token>) -> Result<IfExpr> {
|
|||
})
|
||||
}
|
||||
}
|
||||
fn parse_while_loop(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
let loc = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::While), "")?;
|
||||
fn parse_while_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::While), "")?;
|
||||
let Some(test) = parse_expr(tokens, 0, false)? else {
|
||||
lerror!(loc.loc(), "Expected test comparrison for while loop, got nothing");
|
||||
lerror!(kw.loc(), "Expected test comparrison for while loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
let block = parse_block(tokens)?;
|
||||
Ok(Expr::WhileLoop {
|
||||
Ok(LocBox::new(kw.loc(), Expr::WhileLoop {
|
||||
test: Box::new(test),
|
||||
body: block
|
||||
})
|
||||
}))
|
||||
}
|
||||
fn parse_for_loop(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
let loc = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::For), "")?;
|
||||
fn parse_for_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::For), "")?;
|
||||
let Some(pre) = parse_item(tokens)? else {
|
||||
lerror!(loc.loc(), "Expected init stat for a for loop, got nothing");
|
||||
lerror!(kw.loc(), "Expected init stat for a for loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
// Semicolon parsed out by parse_item above
|
||||
let Some(test) = parse_expr(tokens, 0, false)? else {
|
||||
lerror!(loc.loc(), "Expected test comparrison for a for loop, got nothing");
|
||||
lerror!(kw.loc(), "Expected test comparrison for a for loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "");
|
||||
let Some(post) = parse_expr(tokens, 0, false)? else {
|
||||
lerror!(loc.loc(), "Expected post expression (usually an index increment) for a for loop, got nothing");
|
||||
lerror!(kw.loc(), "Expected post expression (usually an index increment) for a for loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
let block = parse_block(tokens)?;
|
||||
|
||||
Ok(Expr::ForLoop {
|
||||
Ok(LocBox::new(kw.loc(), Expr::ForLoop {
|
||||
init: Box::new(pre),
|
||||
test: Box::new(test),
|
||||
on_loop: Box::new(post),
|
||||
body: block
|
||||
})
|
||||
}))
|
||||
}
|
||||
fn parse_inf_loop(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Loop), "");
|
||||
fn parse_inf_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Loop), "")?;
|
||||
let block = parse_block(tokens)?;
|
||||
Ok(Expr::InfLoop { body: block })
|
||||
Ok(LocBox::new(kw.loc(), Expr::InfLoop { body: block }))
|
||||
}
|
||||
fn parse_fn_call(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "");
|
||||
fn parse_fn_call(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
let mut params = Vec::new();
|
||||
|
||||
while !tokens.is_empty() {
|
||||
|
@ -232,23 +228,23 @@ fn parse_fn_call(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
|||
}
|
||||
}
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "");
|
||||
Ok(Expr::Call { path: Box::new(left), params: CallParams(params) })
|
||||
Ok(LocBox::new(start.loc(), Expr::Call { path: Box::new(left), params: CallParams(params) }))
|
||||
}
|
||||
fn parse_array_index(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
||||
let loc = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareL), "")?;
|
||||
fn parse_array_index(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareL), "")?;
|
||||
let Some(idx) = parse_expr(tokens, 0, false)? else {
|
||||
lerror!(loc.loc(), "Expected index for in array index but found nothing.");
|
||||
lerror!(start.loc(), "Expected index for in array index but found nothing.");
|
||||
bail!("")
|
||||
};
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareR), "");
|
||||
Ok(Expr::ArrayIndex {
|
||||
Ok(LocBox::new(start.loc(), Expr::ArrayIndex {
|
||||
name: Box::new(left),
|
||||
index: Box::new(idx)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_field_access(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Fieldaccess), "unreachable")?;
|
||||
fn parse_field_access(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Fieldaccess), "unreachable")?;
|
||||
|
||||
let right = if let Some(_) = utils::check_2_last(tokens, TokenType::Punct(Punctuation::Arrow)) {
|
||||
let right = parse_path(tokens)?;
|
||||
|
@ -259,14 +255,14 @@ fn parse_field_access(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
|||
} else {
|
||||
parse_path(tokens)?
|
||||
};
|
||||
Ok(Expr::FieldAccess {
|
||||
Ok(LocBox::new(start.loc(), Expr::FieldAccess {
|
||||
left: Box::new(Some(left)),
|
||||
right: Box::new(right)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_ptr_field_access(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Arrow), "unreachable")?;
|
||||
fn parse_ptr_field_access(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Arrow), "unreachable")?;
|
||||
let right = if let Some(_) = utils::check_2_last(tokens, TokenType::Punct(Punctuation::Arrow)) {
|
||||
let right = parse_path(tokens)?;
|
||||
parse_ptr_field_access(tokens, right)?
|
||||
|
@ -276,28 +272,28 @@ fn parse_ptr_field_access(tokens: &mut Vec<Token>, left: Expr) -> Result<Expr> {
|
|||
} else {
|
||||
parse_path(tokens)?
|
||||
};
|
||||
Ok(Expr::PtrFieldAccess {
|
||||
Ok(LocBox::new(start.loc(), Expr::PtrFieldAccess {
|
||||
left: Box::new(Some(left)),
|
||||
right: Box::new(right)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_literal(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
fn parse_literal(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
if let Some(tkn) = utils::check_consume(tokens, TokenType::string("", false)) {
|
||||
let TokenType::String(str) = tkn.tt() else {unreachable!()};
|
||||
return Ok(Expr::Literal(Literal::String(str.clone())));
|
||||
return Ok(LocBox::new(tkn.loc(), Expr::Literal(Literal::String(str.clone()))));
|
||||
} else
|
||||
if let Some(tkn) = utils::check_consume(tokens, TokenType::number(0, 0, false)) {
|
||||
let TokenType::Number(val) = tkn.tt() else {unreachable!()};
|
||||
return Ok(Expr::Literal(Literal::Number(val.clone())));
|
||||
return Ok(LocBox::new(tkn.loc(), Expr::Literal(Literal::Number(val.clone()))));
|
||||
} else
|
||||
if let Some(tkn) = utils::check_consume(tokens, TokenType::char('\0')) {
|
||||
let TokenType::Char(val) = tkn.tt() else {unreachable!()};
|
||||
return Ok(Expr::Literal(Literal::Char(val.clone())));
|
||||
return Ok(LocBox::new(tkn.loc(), Expr::Literal(Literal::Char(val.clone()))));
|
||||
} else
|
||||
if let Some(start) = utils::check_consume(tokens, TokenType::Delim(Delimiter::SquareL)) {
|
||||
if let Some(_) = utils::check_consume(tokens, TokenType::Delim(Delimiter::SquareR)) {
|
||||
return Ok(Expr::Literal(Literal::Array(Vec::new())));
|
||||
return Ok(LocBox::new(start.loc(), Expr::Literal(Literal::Array(Vec::new()))));
|
||||
}
|
||||
if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Comma) {
|
||||
let first = parse_expr(tokens, 0, false)?;
|
||||
|
@ -314,15 +310,15 @@ fn parse_literal(tokens: &mut Vec<Token>) -> Result<Expr> {
|
|||
}
|
||||
}
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareR), "")?;
|
||||
return Ok(Expr::Literal(Literal::Array(values)));
|
||||
return Ok(LocBox::new(start.loc(), Expr::Literal(Literal::Array(values))));
|
||||
} else if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Semi) {
|
||||
let typ = parse_type(tokens)?;
|
||||
let count = parse_expr(tokens, 0, false)?.unwrap();
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareR), "")?;
|
||||
return Ok(Expr::Literal(Literal::ArrayRepeat {
|
||||
return Ok(LocBox::new(start.loc(), Expr::Literal(Literal::ArrayRepeat {
|
||||
typ: Box::new(typ),
|
||||
count: Box::new(count)
|
||||
}));
|
||||
})));
|
||||
} else {
|
||||
if let Some(curr) = tokens.last() {
|
||||
lerror!(start.loc(), "Expected a , or ; as a separator in a literal array (normal, or repeating, respectively), but found {}", curr.tt());
|
||||
|
@ -335,8 +331,8 @@ fn parse_literal(tokens: &mut Vec<Token>) -> Result<Expr> {
|
|||
unreachable!()
|
||||
}
|
||||
|
||||
fn parse_struct_literal(tokens: &mut Vec<Token>, name: Path) -> Result<Expr> {
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyL), "")?;
|
||||
fn parse_struct_literal(tokens: &mut Vec<Token>, name: Path) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyL), "")?;
|
||||
let mut fields = HashMap::new();
|
||||
while !tokens.is_empty() {
|
||||
if let Some(_) = utils::check_consume(tokens, TokenType::Delim(Delimiter::CurlyR)) {
|
||||
|
@ -352,21 +348,21 @@ fn parse_struct_literal(tokens: &mut Vec<Token>, name: Path) -> Result<Expr> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
Ok(Expr::Struct { path: name, fields })
|
||||
Ok(LocBox::new(start.loc(), Expr::Struct { path: name, fields }))
|
||||
}
|
||||
|
||||
fn parse_group(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
let loc = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
fn parse_group(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
let Some(expr) = parse_expr(tokens, 0, false)? else {
|
||||
lerror!(loc.loc(), "Expected expr found nothing");
|
||||
lerror!(start.loc(), "Expected expr found nothing");
|
||||
bail!("")
|
||||
};
|
||||
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "")?;
|
||||
Ok(Expr::Group(Box::new(expr)))
|
||||
Ok(LocBox::new(start.loc(), Expr::Group(Box::new(expr))))
|
||||
}
|
||||
|
||||
fn parse_path(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
fn parse_path(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
let mut buf = Vec::new();
|
||||
let part = utils::check_consume(tokens, TokenType::ident("")).unwrap();
|
||||
|
||||
|
@ -379,10 +375,10 @@ fn parse_path(tokens: &mut Vec<Token>) -> Result<Expr> {
|
|||
buf.push(part.tt().unwrap_ident());
|
||||
}
|
||||
|
||||
Ok(Expr::Path(Path(buf)))
|
||||
Ok(LocBox::new(part.loc(), Expr::Path(Path(buf))))
|
||||
}
|
||||
|
||||
fn parse_unop(tokens: &mut Vec<Token>) -> Result<Expr> {
|
||||
fn parse_unop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
let typ = utils::check_consume_or_err_from_many(tokens, &[
|
||||
TokenType::Punct(Punctuation::Not),
|
||||
TokenType::Punct(Punctuation::Plus),
|
||||
|
@ -397,18 +393,20 @@ fn parse_unop(tokens: &mut Vec<Token>) -> Result<Expr> {
|
|||
lerror!(&loc, "Expected expression after unary token, found nothing");
|
||||
bail!("")
|
||||
};
|
||||
Ok(Expr::UnOp {
|
||||
Ok(LocBox::new(&loc, Expr::UnOp {
|
||||
typ,
|
||||
right: Box::new(right)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_binop(tokens: &mut Vec<Token>, mut lhs: Expr, precedence: usize) -> Result<Expr> {
|
||||
fn parse_binop(tokens: &mut Vec<Token>, mut lhs: LocBox<Expr>, precedence: usize) -> Result<LocBox<Expr>> {
|
||||
// TODO: https://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudocode
|
||||
|
||||
loop {
|
||||
let op_loc;
|
||||
let op = match tokens.last() {
|
||||
Some(op) if BINOP_LIST.contains(&op.tt()) => {
|
||||
op_loc = op.loc().clone();
|
||||
let TokenType::Punct(op) = op.tt() else {unreachable!()};
|
||||
op.clone()
|
||||
}
|
||||
|
@ -433,11 +431,11 @@ fn parse_binop(tokens: &mut Vec<Token>, mut lhs: Expr, precedence: usize) -> Res
|
|||
|
||||
_ = tokens.pop();
|
||||
let Some(rhs) = parse_expr(tokens, rp, false)? else {break;};
|
||||
lhs = Expr::BinOp {
|
||||
lhs = LocBox::new(&op_loc, Expr::BinOp {
|
||||
typ: op,
|
||||
left: Box::new(lhs),
|
||||
right: Box::new(rhs)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ pub mod ast;
|
|||
mod expr;
|
||||
mod stat;
|
||||
mod utils;
|
||||
mod typ;
|
||||
pub mod typ;
|
||||
|
||||
type Result<T> = anyhow::Result<T>;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use anyhow::bail;
|
||||
|
||||
use crate::common::loc::LocBox;
|
||||
use crate::lerror;
|
||||
use crate::parser::ast::TokenType;
|
||||
use crate::parser::expr::parse_expr;
|
||||
|
@ -9,11 +10,11 @@ use super::ast::typ::Type;
|
|||
use super::expr::parse_block;
|
||||
use super::typ::parse_type;
|
||||
use super::utils;
|
||||
use super::ast::statement::Statement;
|
||||
use super::ast::statement::{Enum, Function, Statement, Struct, TypeAlias};
|
||||
|
||||
type Result<T> = anyhow::Result<T>;
|
||||
|
||||
pub fn parse_statement(tokens: &mut Vec<Token>) -> Result<Option<Statement>> {
|
||||
pub fn parse_statement(tokens: &mut Vec<Token>) -> Result<Option<LocBox<Statement>>> {
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) {
|
||||
Ok(Some(parse_fn(tokens)?))
|
||||
} else
|
||||
|
@ -39,8 +40,8 @@ pub fn parse_statement(tokens: &mut Vec<Token>) -> Result<Option<Statement>> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_enum(tokens: &mut Vec<Token>) -> Result<Statement> {
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Enum));
|
||||
fn parse_enum(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Enum), "")?;
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
_ = utils::check_consume(tokens, TokenType::Delim(Delimiter::CurlyL));
|
||||
let mut fields = Vec::new();
|
||||
|
@ -60,11 +61,11 @@ fn parse_enum(tokens: &mut Vec<Token>) -> Result<Statement> {
|
|||
fields.push(field_name);
|
||||
}
|
||||
|
||||
Ok(Statement::Enum { name, fields })
|
||||
Ok(LocBox::new(kw.loc(), Statement::Enum(Enum { name, fields })))
|
||||
}
|
||||
|
||||
fn parse_struct(tokens: &mut Vec<Token>) -> Result<Statement> {
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Struct));
|
||||
fn parse_struct(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Struct), "")?;
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
_ = utils::check_consume(tokens, TokenType::Delim(Delimiter::CurlyL));
|
||||
let mut fields = Vec::new();
|
||||
|
@ -86,11 +87,11 @@ fn parse_struct(tokens: &mut Vec<Token>) -> Result<Statement> {
|
|||
fields.push((field_name, typ));
|
||||
}
|
||||
|
||||
Ok(Statement::Struct { name, fields })
|
||||
Ok(LocBox::new(kw.loc(), Statement::Struct(Struct { name, fields })))
|
||||
}
|
||||
|
||||
fn parse_static(tokens: &mut Vec<Token>) -> Result<Statement> {
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Static));
|
||||
fn parse_static(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Static), "")?;
|
||||
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "")?;
|
||||
|
@ -101,11 +102,11 @@ fn parse_static(tokens: &mut Vec<Token>) -> Result<Statement> {
|
|||
bail!("")
|
||||
};
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
Ok(Statement::StaticVar { name, typ, val })
|
||||
Ok(LocBox::new(kw.loc(), Statement::StaticVar { name, typ, val }))
|
||||
}
|
||||
|
||||
fn parse_let(tokens: &mut Vec<Token>) -> Result<Statement> {
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Let));
|
||||
fn parse_let(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Let), "")?;
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
let mut typ = None;
|
||||
let mut val = None;
|
||||
|
@ -120,10 +121,10 @@ fn parse_let(tokens: &mut Vec<Token>) -> Result<Statement> {
|
|||
val = Some(_val);
|
||||
}
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
Ok(Statement::Let { name, typ, val })
|
||||
Ok(LocBox::new(kw.loc(), Statement::Let { name, typ, val }))
|
||||
}
|
||||
fn parse_constant(tokens: &mut Vec<Token>) -> Result<Statement> {
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Const));
|
||||
fn parse_constant(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Const), "")?;
|
||||
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) {
|
||||
unimplemented!()
|
||||
|
@ -137,22 +138,22 @@ fn parse_constant(tokens: &mut Vec<Token>) -> Result<Statement> {
|
|||
bail!("")
|
||||
};
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
Ok(Statement::ConstVar { name, typ, val })
|
||||
Ok(LocBox::new(kw.loc(), Statement::ConstVar { name, typ, val }))
|
||||
}
|
||||
|
||||
fn parse_type_alias(tokens: &mut Vec<Token>) -> Result<Statement> {
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Type));
|
||||
fn parse_type_alias(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Type), "")?;
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Eq), "")?;
|
||||
let typ = parse_type(tokens)?;
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
|
||||
Ok(Statement::TypeAlias { name, typ })
|
||||
Ok(LocBox::new(kw.loc(), Statement::TypeAlias(TypeAlias { name, typ })))
|
||||
}
|
||||
|
||||
fn parse_fn(tokens: &mut Vec<Token>) -> Result<Statement> {
|
||||
fn parse_fn(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
// Just remove the kw since we checked it before
|
||||
_ = utils::check_consume(tokens, TokenType::Keyword(Keyword::Fn));
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Fn), "")?;
|
||||
|
||||
let mut struct_name = None;
|
||||
let mut name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
|
@ -176,7 +177,8 @@ fn parse_fn(tokens: &mut Vec<Token>) -> Result<Statement> {
|
|||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
body = None;
|
||||
}
|
||||
Ok(Statement::Fn {
|
||||
|
||||
Ok(LocBox::new(kw.loc(), Statement::Fn(Function{
|
||||
struct_name,
|
||||
name,
|
||||
params,
|
||||
|
@ -184,15 +186,18 @@ fn parse_fn(tokens: &mut Vec<Token>) -> Result<Statement> {
|
|||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body,
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn parse_fn_params(tokens: &mut Vec<Token>) -> Result<Vec<(Ident, Type)>> {
|
||||
fn parse_fn_params(tokens: &mut Vec<Token>) -> Result<Vec<(Ident, LocBox<Type>)>> {
|
||||
let mut args = Vec::new();
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
while !tokens.is_empty() {
|
||||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
||||
break;
|
||||
}
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?;
|
||||
utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "")?;
|
||||
//dbg!(&name);
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
use anyhow::Result;
|
||||
|
||||
use crate::{parser::Delimiter, tokeniser::Token};
|
||||
use crate::{common::loc::LocBox, parser::Delimiter, tokeniser::Token};
|
||||
|
||||
use super::{ast::{typ::Type, TokenType}, expr::parse_expr, utils, Keyword, Punctuation};
|
||||
|
||||
pub fn parse_type(tokens: &mut Vec<Token>) -> Result<Type> {
|
||||
pub fn parse_type(tokens: &mut Vec<Token>) -> Result<LocBox<Type>> {
|
||||
let mut ref_cnt = Vec::new();
|
||||
let mut loc = None;
|
||||
while let Some(tok) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Ampersand)) {
|
||||
if let None = loc {
|
||||
loc = Some(tok.loc().clone());
|
||||
}
|
||||
if let Some(tok) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Mut)) {
|
||||
ref_cnt.push(tok.clone());
|
||||
} else {
|
||||
|
@ -15,23 +19,29 @@ pub fn parse_type(tokens: &mut Vec<Token>) -> Result<Type> {
|
|||
}
|
||||
|
||||
let mut typ;
|
||||
if let Some(_) = utils::check_consume(tokens, TokenType::Delim(super::Delimiter::SquareL)) {
|
||||
if let Some(start) = utils::check_consume(tokens, TokenType::Delim(super::Delimiter::SquareL)) {
|
||||
if let None = loc {
|
||||
loc = Some(start.loc().clone());
|
||||
}
|
||||
let itm_typ = parse_type(tokens)?;
|
||||
if let Some(_) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Semi)) {
|
||||
let count = parse_expr(tokens, 0, false)?.unwrap();
|
||||
typ = Type::ArrayRepeat {
|
||||
inner: Box::new(itm_typ),
|
||||
inner: Box::new(itm_typ.inner().clone()),
|
||||
count
|
||||
}
|
||||
} else {
|
||||
typ = Type::Array {
|
||||
inner: Box::new(itm_typ),
|
||||
inner: Box::new(itm_typ.inner().clone()),
|
||||
}
|
||||
}
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareR), "")?;
|
||||
} else {
|
||||
let ident = utils::check_consume_or_err(tokens, TokenType::ident(""), "a")?;
|
||||
typ = Type::Owned(ident.tt().unwrap_ident());
|
||||
if let None = loc {
|
||||
loc = Some(ident.loc().clone());
|
||||
}
|
||||
}
|
||||
while let Some(reft) = ref_cnt.pop() {
|
||||
match reft.tt() {
|
||||
|
@ -50,5 +60,5 @@ pub fn parse_type(tokens: &mut Vec<Token>) -> Result<Type> {
|
|||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
Ok(typ)
|
||||
Ok(LocBox::new(&loc.unwrap(), typ))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,74 @@
|
|||
use crate::parser::ast::Program;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{common::loc::LocBox, parser::ast::{expr::Block, statement::{Statement, TypeAlias}, Ast, Program}};
|
||||
|
||||
pub mod predefined;
|
||||
|
||||
pub fn validate_code(prog: &mut Program) -> anyhow::Result<()> {
|
||||
let Block(items) = prog.ast.clone();
|
||||
predefined::load_builtin(prog);
|
||||
collect_types(prog, &items);
|
||||
//dbg!(&prog.types);
|
||||
//dbg!(&prog.structs);
|
||||
//dbg!(&prog.enums);
|
||||
//dbg!(&prog.member_functions);
|
||||
//dbg!(&prog.functions);
|
||||
for item in items {
|
||||
match item {
|
||||
Ast::Statement(stat) => {
|
||||
match stat.inner() {
|
||||
Statement::Fn(func) => {}
|
||||
Statement::Let { name, typ, val } => {}
|
||||
Statement::ConstVar { name, typ, val } => {}
|
||||
Statement::StaticVar { name, typ, val } => {}
|
||||
Statement::Enum(enm) => {}
|
||||
Statement::Struct(strct) => {}
|
||||
Statement::TypeAlias(alias) => {}
|
||||
}
|
||||
}
|
||||
Ast::Expr(_) => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_code(prog: &Program) -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn collect_types(prog: &mut Program, items: &Vec<Ast>) {
|
||||
for item in items {
|
||||
match item {
|
||||
Ast::Statement(stat) => {
|
||||
match stat.inner() {
|
||||
Statement::Fn(func)=> {
|
||||
if let Some(struct_name) = &func.struct_name {
|
||||
if let Some(v) = prog.member_functions.get_mut(&struct_name) {
|
||||
v.insert(func.name.clone(), LocBox::new(stat.loc(), func.clone()));
|
||||
} else {
|
||||
let mut v = HashMap::new();
|
||||
v.insert(func.name.clone(), LocBox::new(stat.loc(), func.clone()));
|
||||
prog.member_functions.insert(struct_name.clone(), v);
|
||||
}
|
||||
} else {
|
||||
prog.functions.insert(func.name.clone(), LocBox::new(stat.loc(), func.clone()));
|
||||
}
|
||||
}
|
||||
Statement::Enum(enm) => {
|
||||
prog.enums.insert(enm.name.clone(), LocBox::new(stat.loc(), enm.clone()));
|
||||
}
|
||||
Statement::Struct(strct) => {
|
||||
prog.structs.insert(strct.name.clone(), LocBox::new(stat.loc(), strct.clone()));
|
||||
}
|
||||
Statement::TypeAlias(alias) => {
|
||||
let typ = alias.clone().typ.inner().clone();
|
||||
prog.types.insert(alias.name.clone(), predefined::TypeType::Normal(LocBox::new(stat.loc(), typ)));
|
||||
}
|
||||
Statement::Let { .. } |
|
||||
Statement::ConstVar { .. } |
|
||||
Statement::StaticVar { .. } => (),
|
||||
}
|
||||
}
|
||||
Ast::Expr(_) => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
use std::collections::HashMap;
|
||||
use lazy_static::lazy_static;
|
||||
use crate::common::Loc;
|
||||
use crate::parser::typ::parse_type;
|
||||
use crate::{common::loc::LocBox, parser::ast::{statement::Function, typ::Type, Ident, Program}};
|
||||
|
||||
#[cfg(target_arch="x86_64")]
|
||||
const SIZE: usize = 8;
|
||||
#[cfg(target_arch="x86")]
|
||||
const SIZE: usize = 4;
|
||||
|
||||
lazy_static!(
|
||||
pub static ref TYPES_RAW: HashMap<&'static str, usize> = [
|
||||
("void", 0),
|
||||
("usize", SIZE),
|
||||
("isize", SIZE),
|
||||
("u8", 1),
|
||||
("u16", 2),
|
||||
("u32", 4),
|
||||
("u64", 8),
|
||||
("i8", 1),
|
||||
("i16", 2),
|
||||
("i32", 4),
|
||||
("i64", 8),
|
||||
].into();
|
||||
pub static ref FUNCTIONS: HashMap<&'static str, (Vec<(&'static str, &'static str)>, &'static str)> = [
|
||||
("syscall", (vec![
|
||||
("arg_count", "&u8"),
|
||||
("sc_num", "usize"),
|
||||
("args", "&[&void]")
|
||||
], "usize")),
|
||||
].into();
|
||||
);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TypeType {
|
||||
Normal(LocBox<Type>),
|
||||
Builtin(usize),
|
||||
}
|
||||
|
||||
pub fn load_builtin(prog: &mut Program) {
|
||||
for (name, size) in TYPES_RAW.iter() {
|
||||
prog.types.insert(Ident(name.to_string()), TypeType::Builtin(*size));
|
||||
}
|
||||
|
||||
for (name, (args, ret_typ)) in FUNCTIONS.iter() {
|
||||
let mut params = Vec::new();
|
||||
let mut ret_type = None;
|
||||
if ret_typ.len() > 0 {
|
||||
let mut ret_t_tokens = crate::tokeniser::tokenise(&ret_typ, "(internal)").unwrap();
|
||||
let typ = parse_type(&mut ret_t_tokens).unwrap();
|
||||
ret_type = Some(LocBox::new(&Loc::default(), typ.inner().clone()));
|
||||
}
|
||||
for (name, typ) in args {
|
||||
let mut tokens = crate::tokeniser::tokenise(&typ, "(internal)").unwrap();
|
||||
let typ = parse_type(&mut tokens).unwrap();
|
||||
params.push((Ident(name.to_string()), LocBox::new(&Loc::new("(internal)", 0, 0), typ.inner().clone())));
|
||||
}
|
||||
|
||||
let f = Function {
|
||||
struct_name: None,
|
||||
name: Ident(name.to_string()),
|
||||
params,
|
||||
ret_type,
|
||||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body: None
|
||||
};
|
||||
prog.functions.insert(Ident(name.to_string()), LocBox::new(&Loc::new("(internal)", 0, 0), f));
|
||||
}
|
||||
}
|
101
test.mcl
101
test.mcl
|
@ -1,86 +1,21 @@
|
|||
|
||||
enum Wah {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
}
|
||||
|
||||
struct Baz {
|
||||
owo: i32,
|
||||
uwu: usize
|
||||
}
|
||||
|
||||
/// Type definitions
|
||||
// type Rah = &Baz;
|
||||
|
||||
/// Different kinds of functions
|
||||
// Normal function
|
||||
// fn main(a: &Foo, b: Rah) -> Nya {
|
||||
/// General expressions (math)
|
||||
// Works
|
||||
// let a = 1 * 3 == 4;
|
||||
// let b = 3/4 == *a;
|
||||
// let c = (a->b.c->d) / 2;
|
||||
// let d = 2 / a->b.c->d;
|
||||
// let e = a->b.c->d / 2;
|
||||
// let f = a.b.c.d / 2;
|
||||
// let g = a.b[a.c] * 5;
|
||||
|
||||
// No worky
|
||||
// nothing! yay!
|
||||
|
||||
/// Struct literals
|
||||
// let a = Baz {
|
||||
// owo: a,
|
||||
// uwu: b + c / d
|
||||
// };
|
||||
|
||||
/// If statement
|
||||
// if 1 > 3 {
|
||||
// ";3"
|
||||
// } else
|
||||
// if *a == 3 {
|
||||
// ":0"
|
||||
// } else {
|
||||
// ">:("
|
||||
// }
|
||||
|
||||
|
||||
/// 3 kinds of loops all doing the same thing
|
||||
/// While loops
|
||||
// let iw = 0;
|
||||
// while iw < 10 {
|
||||
// println("Owo");
|
||||
// }
|
||||
|
||||
/// For loops
|
||||
// for let ifr = 0 ; ifr < 20 ; ifr += 1 {
|
||||
// println("nya");
|
||||
// }
|
||||
|
||||
/// Infinite loops
|
||||
// let il = 0;
|
||||
// loop {
|
||||
// if il > 10 {
|
||||
// break;
|
||||
// }
|
||||
// println("Rah");
|
||||
// }
|
||||
|
||||
/// Function Calls
|
||||
// println(":3");
|
||||
//type str = [u8];
|
||||
//
|
||||
//struct Foo {
|
||||
// a: usize,
|
||||
// b: &str
|
||||
//}
|
||||
//
|
||||
//fn Foo.new(a: usize, b: &str) -> Foo {
|
||||
// return Foo {
|
||||
// a: a,
|
||||
// b: b
|
||||
// };
|
||||
//}
|
||||
//
|
||||
//
|
||||
//fn main() {
|
||||
// let obj = Foo::new();
|
||||
//
|
||||
//}
|
||||
|
||||
// Struct member function with inner data
|
||||
//fn Baz.main(self: &mut Baz, a: &Foo, b: &mut Bar) -> &Nya;
|
||||
|
||||
// Struct member function without any data a.k.a a static member func
|
||||
//fn Baz.main(a: &Foo, b: &mut Bar) -> &Nya;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,29 +2,47 @@ Program {
|
|||
ast: Block(
|
||||
[
|
||||
Statement(
|
||||
Enum {
|
||||
name: Ident(
|
||||
"Foo",
|
||||
LocBox {
|
||||
inner: Enum(
|
||||
Enum {
|
||||
name: Ident(
|
||||
"Foo",
|
||||
),
|
||||
fields: [],
|
||||
},
|
||||
),
|
||||
fields: [],
|
||||
loc: Loc {
|
||||
file: "parser/enumerations.mcl",
|
||||
line: 1,
|
||||
col: 5,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
Enum {
|
||||
name: Ident(
|
||||
"Bar",
|
||||
LocBox {
|
||||
inner: Enum(
|
||||
Enum {
|
||||
name: Ident(
|
||||
"Bar",
|
||||
),
|
||||
fields: [
|
||||
Ident(
|
||||
"A",
|
||||
),
|
||||
Ident(
|
||||
"B",
|
||||
),
|
||||
Ident(
|
||||
"C",
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
fields: [
|
||||
Ident(
|
||||
"A",
|
||||
),
|
||||
Ident(
|
||||
"B",
|
||||
),
|
||||
Ident(
|
||||
"C",
|
||||
),
|
||||
],
|
||||
loc: Loc {
|
||||
file: "parser/enumerations.mcl",
|
||||
line: 3,
|
||||
col: 5,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,53 +1,900 @@
|
|||
Program {
|
||||
ast: Block(
|
||||
[
|
||||
Expr(
|
||||
BinOp {
|
||||
typ: Eq,
|
||||
left: UnOp {
|
||||
typ: Star,
|
||||
right: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"a",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: BinOp {
|
||||
typ: EqEq,
|
||||
left: LocBox {
|
||||
inner: BinOp {
|
||||
typ: Star,
|
||||
left: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 1,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 1,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 3,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 1,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 1,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 4,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 1,
|
||||
col: 18,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 1,
|
||||
col: 16,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
right: BinOp {
|
||||
typ: EqEq,
|
||||
left: BinOp {
|
||||
typ: Star,
|
||||
left: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 1,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
right: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 3,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
right: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 4,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 1,
|
||||
col: 4,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"b",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: BinOp {
|
||||
typ: EqEq,
|
||||
left: LocBox {
|
||||
inner: BinOp {
|
||||
typ: Div,
|
||||
left: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 3,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 2,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 4,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 2,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 2,
|
||||
col: 11,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: UnOp {
|
||||
typ: Star,
|
||||
right: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 2,
|
||||
col: 17,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 2,
|
||||
col: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 2,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 2,
|
||||
col: 4,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"c",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: BinOp {
|
||||
typ: Div,
|
||||
left: LocBox {
|
||||
inner: Group(
|
||||
LocBox {
|
||||
inner: PtrFieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 11,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 13,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: PtrFieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"c",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 15,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"d",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 17,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 2,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 22,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 20,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 3,
|
||||
col: 4,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"d",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: BinOp {
|
||||
typ: Div,
|
||||
left: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 2,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: PtrFieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 16,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: PtrFieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"c",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 18,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"d",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 19,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 17,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 4,
|
||||
col: 4,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"e",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: BinOp {
|
||||
typ: Div,
|
||||
left: LocBox {
|
||||
inner: PtrFieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: PtrFieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"c",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"d",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 13,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 11,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 2,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 18,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 5,
|
||||
col: 4,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"f",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: BinOp {
|
||||
typ: Div,
|
||||
left: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"c",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"d",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 13,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 11,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 2,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 18,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 6,
|
||||
col: 4,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"g",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: BinOp {
|
||||
typ: Star,
|
||||
left: LocBox {
|
||||
inner: ArrayIndex {
|
||||
name: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 11,
|
||||
},
|
||||
},
|
||||
index: LocBox {
|
||||
inner: UnOp {
|
||||
typ: Star,
|
||||
right: LocBox {
|
||||
inner: FieldAccess {
|
||||
left: Some(
|
||||
LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 15,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"c",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 17,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 13,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 5,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 22,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 20,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/expressions.mcl",
|
||||
line: 7,
|
||||
col: 4,
|
||||
},
|
||||
},
|
||||
),
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
*a = 1 * 3 == 4;
|
||||
b.c = 3/4 == *a;
|
||||
c->d = (a->b.c->d) / 2;
|
||||
*d->e.f = 2 / a->b.c->d;
|
||||
e = a->b.c->d / 2;
|
||||
f = a.b.c.d / 2;
|
||||
g = a.b[*a.c] * 5;
|
||||
let a = 1 * 3 == 4;
|
||||
let b = 3/4 == *a;
|
||||
let c = (a->b.c->d) / 2;
|
||||
let d = 2 / a->b.c->d;
|
||||
let e = a->b.c->d / 2;
|
||||
let f = a.b.c.d / 2;
|
||||
let g = a.b[*a.c] * 5;
|
||||
|
||||
|
|
|
@ -2,187 +2,298 @@ Program {
|
|||
ast: Block(
|
||||
[
|
||||
Statement(
|
||||
Fn {
|
||||
struct_name: None,
|
||||
name: Ident(
|
||||
"main",
|
||||
),
|
||||
params: [
|
||||
(
|
||||
Ident(
|
||||
"argc",
|
||||
LocBox {
|
||||
inner: Fn(
|
||||
Function {
|
||||
struct_name: None,
|
||||
name: Ident(
|
||||
"main",
|
||||
),
|
||||
Owned(
|
||||
Ident(
|
||||
"i32",
|
||||
),
|
||||
),
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"argv",
|
||||
),
|
||||
Ref {
|
||||
inner: Array {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Str",
|
||||
),
|
||||
params: [
|
||||
(
|
||||
Ident(
|
||||
"argc",
|
||||
),
|
||||
},
|
||||
mutable: false,
|
||||
},
|
||||
),
|
||||
],
|
||||
ret_type: Some(
|
||||
Owned(
|
||||
Ident(
|
||||
"i32",
|
||||
),
|
||||
),
|
||||
),
|
||||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body: Some(
|
||||
Block(
|
||||
[
|
||||
Expr(
|
||||
Return(
|
||||
Some(
|
||||
Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 0,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
LocBox {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"i32",
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 1,
|
||||
col: 18,
|
||||
},
|
||||
},
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"argv",
|
||||
),
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Array {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Str",
|
||||
),
|
||||
),
|
||||
},
|
||||
mutable: false,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 1,
|
||||
col: 27,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
ret_type: Some(
|
||||
LocBox {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"i32",
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 1,
|
||||
col: 39,
|
||||
},
|
||||
},
|
||||
),
|
||||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body: Some(
|
||||
Block(
|
||||
[
|
||||
Expr(
|
||||
LocBox {
|
||||
inner: Return(
|
||||
Some(
|
||||
LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 0,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 2,
|
||||
col: 13,
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 2,
|
||||
col: 11,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 1,
|
||||
col: 3,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
Fn {
|
||||
struct_name: Some(
|
||||
Ident(
|
||||
"Baz",
|
||||
),
|
||||
),
|
||||
name: Ident(
|
||||
"main",
|
||||
),
|
||||
params: [
|
||||
(
|
||||
Ident(
|
||||
"self",
|
||||
),
|
||||
Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Baz",
|
||||
),
|
||||
),
|
||||
mutable: true,
|
||||
},
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Foo",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
mutable: true,
|
||||
},
|
||||
),
|
||||
],
|
||||
ret_type: Some(
|
||||
Ref {
|
||||
inner: Owned(
|
||||
LocBox {
|
||||
inner: Fn(
|
||||
Function {
|
||||
struct_name: Some(
|
||||
Ident(
|
||||
"Nya",
|
||||
"Baz",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
name: Ident(
|
||||
"main",
|
||||
),
|
||||
params: [
|
||||
(
|
||||
Ident(
|
||||
"self",
|
||||
),
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Baz",
|
||||
),
|
||||
),
|
||||
mutable: true,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 4,
|
||||
col: 20,
|
||||
},
|
||||
},
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Foo",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 4,
|
||||
col: 33,
|
||||
},
|
||||
},
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
mutable: true,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 4,
|
||||
col: 42,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
ret_type: Some(
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Nya",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 4,
|
||||
col: 54,
|
||||
},
|
||||
},
|
||||
),
|
||||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body: None,
|
||||
},
|
||||
),
|
||||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body: None,
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 4,
|
||||
col: 3,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
Fn {
|
||||
struct_name: Some(
|
||||
Ident(
|
||||
"Baz",
|
||||
),
|
||||
),
|
||||
name: Ident(
|
||||
"main",
|
||||
),
|
||||
params: [
|
||||
(
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Foo",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
mutable: true,
|
||||
},
|
||||
),
|
||||
],
|
||||
ret_type: Some(
|
||||
Ref {
|
||||
inner: Owned(
|
||||
LocBox {
|
||||
inner: Fn(
|
||||
Function {
|
||||
struct_name: Some(
|
||||
Ident(
|
||||
"Nya",
|
||||
"Baz",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
name: Ident(
|
||||
"main",
|
||||
),
|
||||
params: [
|
||||
(
|
||||
Ident(
|
||||
"a",
|
||||
),
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Foo",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 5,
|
||||
col: 17,
|
||||
},
|
||||
},
|
||||
),
|
||||
(
|
||||
Ident(
|
||||
"b",
|
||||
),
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
mutable: true,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 5,
|
||||
col: 26,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
ret_type: Some(
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"Nya",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 5,
|
||||
col: 38,
|
||||
},
|
||||
},
|
||||
),
|
||||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body: None,
|
||||
},
|
||||
),
|
||||
qual_const: false,
|
||||
qual_extern: None,
|
||||
body: None,
|
||||
loc: Loc {
|
||||
file: "parser/functions.mcl",
|
||||
line: 5,
|
||||
col: 3,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
@ -2,35 +2,63 @@ Program {
|
|||
ast: Block(
|
||||
[
|
||||
Expr(
|
||||
If(
|
||||
IfExpr {
|
||||
test: BinOp {
|
||||
typ: Gt,
|
||||
left: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
LocBox {
|
||||
inner: If(
|
||||
IfExpr {
|
||||
test: LocBox {
|
||||
inner: BinOp {
|
||||
typ: Gt,
|
||||
left: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
right: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 3,
|
||||
base: 10,
|
||||
signed: false,
|
||||
loc: Loc {
|
||||
file: "parser/if-statements.mcl",
|
||||
line: 2,
|
||||
col: 5,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 3,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/if-statements.mcl",
|
||||
line: 2,
|
||||
col: 9,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/if-statements.mcl",
|
||||
line: 2,
|
||||
col: 7,
|
||||
},
|
||||
},
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
else_if: None,
|
||||
},
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
else_if: None,
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/if-statements.mcl",
|
||||
line: 2,
|
||||
col: 3,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -2,106 +2,204 @@ Program {
|
|||
ast: Block(
|
||||
[
|
||||
Expr(
|
||||
ForLoop {
|
||||
init: Statement(
|
||||
Let {
|
||||
name: Ident(
|
||||
"i",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 0,
|
||||
base: 10,
|
||||
signed: false,
|
||||
LocBox {
|
||||
inner: ForLoop {
|
||||
init: Statement(
|
||||
LocBox {
|
||||
inner: Let {
|
||||
name: Ident(
|
||||
"i",
|
||||
),
|
||||
typ: None,
|
||||
val: Some(
|
||||
LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 0,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 14,
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 8,
|
||||
},
|
||||
},
|
||||
),
|
||||
test: LocBox {
|
||||
inner: BinOp {
|
||||
typ: Lt,
|
||||
left: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 17,
|
||||
},
|
||||
},
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 10,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 22,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 19,
|
||||
},
|
||||
},
|
||||
),
|
||||
test: BinOp {
|
||||
typ: Lt,
|
||||
left: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
on_loop: LocBox {
|
||||
inner: BinOp {
|
||||
typ: AddEq,
|
||||
left: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
right: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 10,
|
||||
base: 10,
|
||||
signed: false,
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 25,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 1,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 29,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 27,
|
||||
},
|
||||
},
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
},
|
||||
on_loop: BinOp {
|
||||
typ: AddEq,
|
||||
left: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
right: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 1,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 1,
|
||||
col: 4,
|
||||
},
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
},
|
||||
),
|
||||
Expr(
|
||||
WhileLoop {
|
||||
test: BinOp {
|
||||
typ: Gt,
|
||||
left: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
LocBox {
|
||||
inner: WhileLoop {
|
||||
test: LocBox {
|
||||
inner: BinOp {
|
||||
typ: Gt,
|
||||
left: LocBox {
|
||||
inner: Path(
|
||||
Path(
|
||||
[
|
||||
Ident(
|
||||
"i",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
right: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 3,
|
||||
base: 10,
|
||||
signed: false,
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 2,
|
||||
col: 8,
|
||||
},
|
||||
},
|
||||
),
|
||||
right: LocBox {
|
||||
inner: Literal(
|
||||
Number(
|
||||
Number {
|
||||
val: 3,
|
||||
base: 10,
|
||||
signed: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 2,
|
||||
col: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 2,
|
||||
col: 10,
|
||||
},
|
||||
},
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
},
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 2,
|
||||
col: 6,
|
||||
},
|
||||
},
|
||||
),
|
||||
Expr(
|
||||
InfLoop {
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
LocBox {
|
||||
inner: InfLoop {
|
||||
body: Block(
|
||||
[],
|
||||
),
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/loops.mcl",
|
||||
line: 3,
|
||||
col: 5,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
@ -2,33 +2,58 @@ Program {
|
|||
ast: Block(
|
||||
[
|
||||
Statement(
|
||||
Struct {
|
||||
name: Ident(
|
||||
"foo_t",
|
||||
LocBox {
|
||||
inner: Struct(
|
||||
Struct {
|
||||
name: Ident(
|
||||
"foo_t",
|
||||
),
|
||||
fields: [],
|
||||
},
|
||||
),
|
||||
fields: [],
|
||||
loc: Loc {
|
||||
file: "parser/structs.mcl",
|
||||
line: 2,
|
||||
col: 7,
|
||||
},
|
||||
},
|
||||
),
|
||||
Statement(
|
||||
Struct {
|
||||
name: Ident(
|
||||
"bar_t",
|
||||
),
|
||||
fields: [
|
||||
(
|
||||
Ident(
|
||||
"a",
|
||||
LocBox {
|
||||
inner: Struct(
|
||||
Struct {
|
||||
name: Ident(
|
||||
"bar_t",
|
||||
),
|
||||
Ref {
|
||||
inner: Owned(
|
||||
fields: [
|
||||
(
|
||||
Ident(
|
||||
"bar_t",
|
||||
"a",
|
||||
),
|
||||
LocBox {
|
||||
inner: Ref {
|
||||
inner: Owned(
|
||||
Ident(
|
||||
"bar_t",
|
||||
),
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
loc: Loc {
|
||||
file: "parser/structs.mcl",
|
||||
line: 5,
|
||||
col: 9,
|
||||
},
|
||||
},
|
||||
),
|
||||
mutable: false,
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
},
|
||||
),
|
||||
loc: Loc {
|
||||
file: "parser/structs.mcl",
|
||||
line: 4,
|
||||
col: 7,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue
Block a user