Skip to content

Commit

Permalink
Add infix operators
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcosAndradeV committed Dec 31, 2024
1 parent 6228ea0 commit 7b44093
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 169 deletions.
114 changes: 10 additions & 104 deletions chs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,109 +1,15 @@
use chs_ast::{types::{infer, InferEnv}, Parser};
use std::{env, fs};

use chs_ast::Parser;
use chs_lexer::Lexer;
use std::{
env::{self, Args},
fs,
path::PathBuf,
process::exit,
};

fn main() {
let mut args = env::args();
let program_path = args.next().expect("program_path");

if let Some(cmd) = args.next() {
match cmd.as_str() {
"lex" => {
let (fpath, bytes) = get_file(&mut args);
let mut lex = Lexer::new(fpath, bytes);
loop {
let token = lex.next_token();
if token.kind.is_eof() {
break;
}
println!("{token}")
}
}
"parse" => {
let (fpath, bytes) = get_file(&mut args);
let lex = Lexer::new(fpath, bytes);
let parser = Parser::new(lex);
match parser.parse() {
Ok(ok) => {
println!("{:?}", ok);
}
Err(err) => {
eprintln!("{err}");
exit(1)
}
}
}
"eval" => {
let (fpath, bytes) = get_file(&mut args);
let lex = Lexer::new(fpath, bytes);
let parser = Parser::new(lex);
match parser.parse() {
Ok(ok) => {
let mut env = InferEnv::default();
for expr in &ok.top_level {
match infer(&mut env, expr, 0) {
Err(err) => {
eprintln!("{err}");
exit(1)
}
_ => ()
}
}
}
Err(err) => {
eprintln!("{err}");
exit(1)
}
}
}
"version" => {
println!("Version: 0.0.1");
}
"help" => {
usage(&program_path);
}
_ => {
println!("Unknow command.");
usage(&program_path);
}
}
} else {
println!("No command provided.");
usage(&program_path);
}
}

fn usage(program_path: &String) {
println!("Usage {program_path} <command> [options] file...");
println!("Command:");
println!(" version Display compiler version information.");
println!(" lex Dump tokens from a file.");
println!(" parse Dump AST from a file.");
println!(" eval Evaluate a file.");
println!(" help Show this message.");
}

fn get_file(args: &mut Args) -> (PathBuf, Vec<u8>) {
if let Some(filepath) = args.next() {
let fpath = PathBuf::from(filepath);
if !fpath.exists() {
println!("File not found.");
exit(1)
}
match fs::read(fpath.as_path()) {
Ok(ok) => (fpath, ok),
Err(err) => {
eprintln!("Cannot read file {err}");
exit(1)
}
}
} else {
println!("No file provided.");
exit(1)
}
let _program = args.next().expect("Expect program");
let file = args.next().expect("Expect file");
let src = fs::read(&file)
.expect("Failed to read file");
let lex = Lexer::new(file.into(), src);
let module = Parser::new(lex).parse().expect("Parsing falied");
println!("{}", module)
}
90 changes: 60 additions & 30 deletions chs_ast/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use chs_lexer::{Lexer, Token, TokenKind};
use chs_util::{chs_error, CHSError};
use nodes::{Call, Expression, FnDecl, Module, Var, VarDecl};
use nodes::{
Binop, Call, Expression, FnDecl, Module, Operator, Precedence, TopLevelExpression, Var, VarDecl,
};
use types::{CHSType, CHSBOOL, CHSCHAR, CHSINT, CHSSTRING, CHSVOID};

pub mod nodes;
pub mod types;

// [Token] -> Module

/// [Token] -> [Module]
#[derive(Default)]
pub struct Parser {
lexer: Lexer,
Expand Down Expand Up @@ -77,7 +78,7 @@ impl Parser {
self.expect_kind(ParenOpen)?;
let (args, ret_type) = self.parse_fn_type()?;
let body = self.parse_expr_list(|tk| tk.val_eq("end"))?;
let expr = Expression::FnDecl(Box::new(FnDecl {
let expr = TopLevelExpression::FnDecl(Box::new(FnDecl {
loc: token.loc,
name,
args,
Expand All @@ -88,24 +89,17 @@ impl Parser {
Ok(())
}
_ => {
self.peeked = Some(token);
let expr = self.parse_expression()?;
self.module.push(expr);
Ok(())
} /*
_ => {
chs_error!(
"{} Invalid Expression on top level {}('{}')",
token.loc,
token.kind,
token.value
)
}
*/
chs_error!(
"{} Invalid Expression on top level {}('{}')",
token.loc,
token.kind,
token.value
)
}
}
}

fn parse_expression(&mut self) -> Result<Expression, CHSError> {
fn parse_expression(&mut self, precedence: Precedence) -> Result<Expression, CHSError> {
use chs_lexer::TokenKind::*;
let token = self.next();
let mut left: Expression = match token.kind {
Expand All @@ -115,7 +109,7 @@ impl Parser {
if ttype.is_some() {
self.expect_kind(Assign)?;
}
let value = self.parse_expression()?;
let value = self.parse_expression(Precedence::Lowest)?;
let name = token.value;
Expression::VarDecl(Box::new(VarDecl {
loc: token.loc,
Expand All @@ -129,18 +123,23 @@ impl Parser {
Expression::from_literal_token(token)?
}
Ampersand => {
let expr = self.parse_expression()?;
let expr = self.parse_expression(Precedence::Prefix)?;
Expression::Ref(expr.into())
}
Asterisk => {
let expr = self.parse_expression()?;
let expr = self.parse_expression(Precedence::Prefix)?;
Expression::Deref(expr.into())
}
Ident => Expression::Var(Var {
loc: token.loc,
name: token.value,
}),
String => Expression::from_literal_token(token)?,
ParenOpen => {
let expr = self.parse_expression(Precedence::Lowest)?;
self.expect_kind(ParenClose)?;
Expression::Group(expr.into())
}
_ => chs_error!(
"{} Unexpected token {}('{}')",
token.loc,
Expand All @@ -154,20 +153,51 @@ impl Parser {
ParenOpen => {
let ptoken = self.next();
let args = self.parse_expr_list(|tk| tk.kind == ParenClose)?;
let call = Expression::Call(Call {
loc: ptoken.loc,
caller: left,
args,
}.into());
let call = Expression::Call(
Call {
loc: ptoken.loc,
caller: left,
args,
}
.into(),
);
left = call;
return Ok(left);
}
Plus | Asterisk | Slash | Minus | Eq | NotEq => {
if precedence < Operator::from_token(&ptoken)?.precedence() {
let token = self.next();
let infix = self.parse_infix_expression(token, left)?;
left = infix
} else {
return Ok(left);
}
}
_ => return Ok(left),
}
}
}

fn parse_expr_list<F>(&mut self, pred: F) -> Result<Expression, CHSError> where
F: Fn(&Token) -> bool
fn parse_infix_expression(
&mut self,
token: Token,
left: Expression,
) -> Result<Expression, CHSError> {
let right = self.parse_expression(Operator::from_token(&token)?.precedence())?;
Ok(Expression::Binop(
Binop {
op: Operator::from_token(&token)?,
loc: token.loc,
right,
left,
}
.into(),
))
}

fn parse_expr_list<F>(&mut self, pred: F) -> Result<Expression, CHSError>
where
F: Fn(&Token) -> bool,
{
use chs_lexer::TokenKind::*;
let mut args = vec![];
Expand All @@ -183,7 +213,7 @@ impl Parser {
continue;
}
_ => {
let value = self.parse_expression()?;
let value = self.parse_expression(Precedence::Lowest)?;
args.push(value);
}
}
Expand Down
Loading

0 comments on commit 7b44093

Please sign in to comment.