├── .gitignore ├── Cargo.lock ├── Cargo.toml └── src ├── codegen.rs ├── emit.rs ├── error.rs ├── lex.rs ├── main.rs ├── parse.rs ├── rand.rs └── span.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /ripc-target 3 | out 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ripc" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ripc" 3 | license = "MIT" 4 | version = "0.1.0" 5 | edition = "2018" 6 | authors = ["ibraheemdev "] 7 | description = "..." 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /src/codegen.rs: -------------------------------------------------------------------------------- 1 | use crate::parse::{Ast, BinaryExpr, BinaryOp, Call, Expr, ExprKind, Lit}; 2 | use crate::{Report, Reporter, Span, Spanned, WithSpan}; 3 | 4 | use std::io::Write; 5 | 6 | pub struct Codegen { 7 | out: W, 8 | } 9 | 10 | impl Codegen 11 | where 12 | W: Write, 13 | { 14 | pub fn new(out: W) -> Self { 15 | Self { out } 16 | } 17 | 18 | pub fn write(mut self, ast: &Ast) -> Result<(), Error> { 19 | self.entry(); 20 | self.start_main(); 21 | 22 | for expr in &ast.exprs { 23 | self.expr(expr)?; 24 | } 25 | 26 | self.end_main(); 27 | 28 | Ok(()) 29 | } 30 | 31 | fn entry(&mut self) { 32 | asm!(self, ".text\n\t"); 33 | asm!(self, ".global _start\n"); 34 | 35 | asm!(self, "_start:\n\t"); 36 | asm!(self, "xor %ebp, %ebp\n\t"); 37 | asm!(self, "call main\n\t"); 38 | asm!(self, "mov $1, %edi\n\t"); 39 | asm!(self, "call exit\n"); 40 | } 41 | 42 | fn start_main(&mut self) { 43 | asm!(self, "main:\n\t"); 44 | asm!(self, "push %rbp\n\t"); 45 | asm!(self, "mov %rsp, %rbp\n\t"); 46 | } 47 | 48 | fn end_main(&mut self) { 49 | asm!(self, "mov %rbp, %rsp\n\t"); 50 | asm!(self, "pop %rbp\n\t"); 51 | asm!(self, "ret\n"); 52 | } 53 | 54 | fn expr(&mut self, expr: &Expr) -> Result<(), Error> { 55 | match expr.kind { 56 | ExprKind::Lit(WithSpan { 57 | value: Lit::Num(num), 58 | .. 59 | }) => asm!(self, "mov ${}, %eax\n\t", num), 60 | ExprKind::Lit(..) => unimplemented!(), 61 | ExprKind::Var(i) => asm!(self, "mov -{}(%rbp), %eax\n\t", (i + 1) * 4), 62 | ExprKind::Binary(ref expr) => self.binary_op(expr)?, 63 | ExprKind::Call(ref call) => self.call(call)?, 64 | } 65 | 66 | Ok(()) 67 | } 68 | 69 | fn call(&mut self, call: &Call) -> Result<(), Error> { 70 | const REGISTERS: [&str; 6] = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"]; 71 | 72 | for i in 1..call.args.len() { 73 | asm!(self, "push %{}\n\t", REGISTERS[i]); 74 | } 75 | 76 | for arg in &call.args { 77 | self.expr(arg)?; 78 | asm!(self, "push %rax\n\t"); 79 | } 80 | 81 | for i in 0..call.args.len() { 82 | asm!(self, "pop %{}\n\t", REGISTERS[i]); 83 | } 84 | 85 | asm!(self, "mov $0, %eax\n\t"); 86 | asm!(self, "call {}\n\t", call.name); 87 | 88 | for i in 1..call.args.len() { 89 | asm!(self, "pop %{}\n\t", REGISTERS[i]); 90 | } 91 | 92 | Ok(()) 93 | } 94 | 95 | fn binary_op(&mut self, expr: &BinaryExpr) -> Result<(), Error> { 96 | if let BinaryOp::Assign = expr.op.value { 97 | self.expr(&expr.right)?; 98 | 99 | match expr.left.kind { 100 | ExprKind::Var(i) => { 101 | asm!(self, "mov %eax, -{}(%rbp)\n\t", (i + 1) * 4) 102 | } 103 | _ => { 104 | return Err(Error::new(ErrorKind::ExpectedIdent, expr.left.span)); 105 | } 106 | } 107 | 108 | return Ok(()); 109 | } 110 | 111 | let op = match expr.op.value { 112 | BinaryOp::Sub => "sub", 113 | BinaryOp::Add => "add", 114 | BinaryOp::Mul => "imul", 115 | BinaryOp::Div => "idiv", 116 | _ => return Err(Error::new(ErrorKind::InvalidOperator, expr.op.span)), 117 | }; 118 | 119 | self.expr(&expr.left)?; 120 | asm!(self, "push %rax\n\t"); 121 | self.expr(&expr.right)?; 122 | 123 | match expr.op.value { 124 | BinaryOp::Div => { 125 | asm!(self, "mov %eax, %ebx\n\t"); 126 | asm!(self, "pop %rax\n\t"); 127 | asm!(self, "mov $0, %edx\n\t"); 128 | asm!(self, "idiv %ebx\n\t"); 129 | } 130 | _ => { 131 | asm!(self, "pop %rbx\n\t"); 132 | asm!(self, "{} %ebx, %eax\n\t", op); 133 | } 134 | } 135 | 136 | Ok(()) 137 | } 138 | 139 | // fn string(&mut self, str: &str) -> Result<(), Error> { 140 | // asm!(self, "\t.data\n"); 141 | // asm!(self, ".mydata:\n\nt"); 142 | // asm!(self, ".string \""); 143 | 144 | // asm!(self, "{}", str); 145 | 146 | // asm!(self, "\"\n\t"); 147 | // asm!(self, ".text\n\t"); 148 | // asm!(self, ".global stringfn\n"); 149 | // asm!(self, "stringfn:\n\t"); 150 | // asm!(self, "lea .mydata(%rip), %rax\n\t"); 151 | // asm!(self, "ret\n"); 152 | 153 | // Ok(()) 154 | // } 155 | } 156 | 157 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 158 | pub struct Error { 159 | pub kind: ErrorKind, 160 | pub span: Span, 161 | } 162 | 163 | impl Error { 164 | fn new(kind: ErrorKind, span: Span) -> Self { 165 | Self { kind, span } 166 | } 167 | } 168 | 169 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 170 | pub enum ErrorKind { 171 | ExpectedIntExpr, 172 | ExpectedIdent, 173 | InvalidOperator, 174 | } 175 | 176 | impl Spanned for Error { 177 | fn span(&self) -> Span { 178 | self.span 179 | } 180 | } 181 | 182 | impl Report for Error { 183 | fn report(&self, f: &mut Reporter<'_, W>) -> std::io::Result<()> { 184 | match self.kind { 185 | ErrorKind::ExpectedIntExpr => write!(f.out, "Expected integer expression"), 186 | ErrorKind::ExpectedIdent => write!(f.out, "Expected identifier"), 187 | ErrorKind::InvalidOperator => write!(f.out, "Invalid operator"), 188 | } 189 | } 190 | } 191 | 192 | macro_rules! _asm { 193 | ($self:ident, $($tt:tt)*) => { 194 | std::write!($self.out, $($tt)*).expect("failed to write output") 195 | } 196 | } 197 | 198 | pub(self) use _asm as asm; 199 | -------------------------------------------------------------------------------- /src/emit.rs: -------------------------------------------------------------------------------- 1 | use crate::codegen::{self, Codegen}; 2 | use crate::parse::Ast; 3 | use crate::rand; 4 | 5 | use std::collections::hash_map::DefaultHasher; 6 | use std::hash::Hasher; 7 | use std::io::{self, Write}; 8 | 9 | pub fn emit(ast: &Ast) -> Result<(), codegen::Error> { 10 | let mut out = Vec::new(); 11 | Codegen::new(&mut out).write(&ast)?; 12 | 13 | match std::fs::create_dir("./ripc-target") { 14 | Err(err) if err.kind() != io::ErrorKind::AlreadyExists => { 15 | panic!("failed to create target directory: {}", err) 16 | } 17 | _ => {} 18 | }; 19 | 20 | let hash = { 21 | let mut hasher = DefaultHasher::new(); 22 | hasher.write_u64(rand::rand()); 23 | hasher.finish() 24 | }; 25 | 26 | let asm_file = format!("./ripc-target/{}.s", hash); 27 | let out_file = format!("./ripc-target/{}.o", hash); 28 | 29 | std::fs::File::create(&asm_file) 30 | .expect("failed to open output file") 31 | .write_all(&out) 32 | .expect("failed to write output"); 33 | 34 | std::process::Command::new("as") 35 | .arg(&asm_file) 36 | .arg("-g") 37 | .arg("-o") 38 | .arg(&out_file) 39 | .status() 40 | .expect("failed to assemble output"); 41 | 42 | std::process::Command::new("ld") 43 | .arg("-o") 44 | .arg("out") 45 | .arg("--dynamic-linker") 46 | .arg("/lib64/ld-linux-x86-64.so.2") 47 | .arg(&out_file) 48 | .arg("-lc") 49 | .status() 50 | .expect("linking failed"); 51 | 52 | Ok(()) 53 | } 54 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use crate::{Span, Spanned}; 2 | 3 | use std::fmt; 4 | use std::io::{self, Write}; 5 | 6 | pub trait Report: Spanned { 7 | fn report(&self, reporter: &mut Reporter<'_, W>) -> io::Result<()>; 8 | } 9 | 10 | pub struct Reporter<'a, W> { 11 | pub out: W, 12 | pub source: &'a str, 13 | } 14 | 15 | impl<'a, W> Reporter<'a, W> 16 | where 17 | W: Write, 18 | { 19 | pub fn new(out: W, source: &'a str) -> Self { 20 | Self { out, source } 21 | } 22 | 23 | fn report(&mut self, err: impl Report) -> Result<(), io::Error> { 24 | write!(self.out, "[error]: ")?; 25 | err.report(self)?; 26 | writeln!(self.out, "\n{}", self.source)?; 27 | 28 | let pad = if err.span() == Span::EOF { 29 | self.source.len() 30 | } else { 31 | err.span().start 32 | }; 33 | 34 | write!(self.out, "{:pad$}^ \n", "") 35 | } 36 | 37 | pub fn exit(&mut self, err: impl Report) -> ! { 38 | self.report(err).expect("failed to write to stdout"); 39 | std::process::exit(1) 40 | } 41 | } 42 | 43 | impl From for Box> 44 | where 45 | E: Report + fmt::Debug + 'static, 46 | { 47 | fn from(err: E) -> Self { 48 | Box::new(err) 49 | } 50 | } 51 | 52 | impl Spanned for Box> { 53 | fn span(&self) -> Span { 54 | (**self).span() 55 | } 56 | } 57 | 58 | impl Report for Box> { 59 | fn report(&self, reporter: &mut Reporter<'_, W>) -> io::Result<()> { 60 | (**self).report(reporter) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/lex.rs: -------------------------------------------------------------------------------- 1 | use crate::{Report, Reporter, Span, Spanned}; 2 | 3 | use std::fmt; 4 | use std::io::Write; 5 | use std::iter::Peekable; 6 | use std::str::Chars; 7 | 8 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 9 | pub struct Token<'a> { 10 | pub kind: TokenKind<'a>, 11 | pub span: Span, 12 | } 13 | 14 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 15 | pub enum TokenKind<'a> { 16 | Add, 17 | Sub, 18 | Mul, 19 | Div, 20 | Semi, 21 | Assign, 22 | Num(usize), 23 | Str(&'a str), 24 | Ident(&'a str), 25 | Whitespace, 26 | OpenParen, 27 | CloseParen, 28 | Comma, 29 | } 30 | 31 | pub struct Lexer<'a> { 32 | chars: Peekable>, 33 | source: &'a str, 34 | span: Span, 35 | eof: bool, 36 | } 37 | 38 | impl<'a> Lexer<'a> { 39 | pub fn new(source: &'a str) -> Self { 40 | Self { 41 | chars: source.chars().peekable(), 42 | source, 43 | span: Span::default(), 44 | eof: false, 45 | } 46 | } 47 | 48 | fn peek(&mut self) -> Option { 49 | self.chars.peek().copied() 50 | } 51 | 52 | fn peek_n(&self, n: usize) -> Option { 53 | self.chars.clone().nth(n) 54 | } 55 | 56 | fn chomp(&mut self) -> Option { 57 | self.chars.next().map(|x| { 58 | self.span.end += 1; 59 | x 60 | }) 61 | } 62 | 63 | fn slice(&self) -> &'a str { 64 | &self.source[self.span.range().unwrap()] 65 | } 66 | 67 | fn reset(&mut self) { 68 | self.span.start = self.span.end; 69 | } 70 | 71 | fn chomp_while(&mut self, f: impl Fn(&char) -> bool + Copy) { 72 | while self.peek().map(|x| f(&x)).unwrap_or(false) { 73 | self.chomp(); 74 | } 75 | } 76 | 77 | pub fn current_span(&self) -> Span { 78 | if self.eof { 79 | Span::EOF 80 | } else { 81 | self.span 82 | } 83 | } 84 | } 85 | 86 | impl<'a> Iterator for Lexer<'a> { 87 | type Item = Result, Error>; 88 | 89 | fn next(&mut self) -> Option { 90 | use ErrorKind::*; 91 | use TokenKind::*; 92 | 93 | self.reset(); 94 | if let Some(ch) = self.chomp() { 95 | let kind = match ch { 96 | '+' => Add, 97 | '-' => Sub, 98 | '/' => Div, 99 | '*' => Mul, 100 | '0'..='9' => { 101 | self.chomp_while(char::is_ascii_digit); 102 | Num(self.slice().parse().unwrap()) 103 | } 104 | ch if ch.is_ascii_whitespace() => { 105 | self.chomp_while(char::is_ascii_whitespace); 106 | Whitespace 107 | } 108 | '"' => loop { 109 | match self.peek() { 110 | Some('"') => { 111 | self.chomp(); 112 | let str = self.slice(); 113 | break TokenKind::Str(&str[1..str.len() - 1]); 114 | } 115 | Some('\\') if matches!(self.peek_n(1), Some('\\') | Some('"')) => { 116 | self.chomp(); 117 | } 118 | Some(_) => {} 119 | None => { 120 | self.eof = true; 121 | return Some(Err(Error::new(UnexpectedEof, self.span))); 122 | } 123 | } 124 | 125 | self.chomp(); 126 | }, 127 | ';' => TokenKind::Semi, 128 | '=' => TokenKind::Assign, 129 | '(' => TokenKind::OpenParen, 130 | ')' => TokenKind::CloseParen, 131 | ',' => TokenKind::Comma, 132 | ch if ch.is_alphabetic() => { 133 | self.chomp_while(|c| c.is_alphanumeric()); 134 | TokenKind::Ident(self.slice()) 135 | } 136 | ch => return Some(Err(Error::new(InvalidCharacter(ch), self.span))), 137 | }; 138 | 139 | if self.peek().is_none() { 140 | self.eof = true; 141 | } 142 | 143 | let token = Token { 144 | kind, 145 | span: self.span, 146 | }; 147 | 148 | return Some(Ok(token)); 149 | } 150 | 151 | self.eof = true; 152 | None 153 | } 154 | } 155 | 156 | impl<'a> fmt::Display for TokenKind<'a> { 157 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 158 | let x = match *self { 159 | TokenKind::Add => "+", 160 | TokenKind::Sub => "+", 161 | TokenKind::Mul => "*", 162 | TokenKind::Div => "/", 163 | TokenKind::Whitespace => " ", 164 | TokenKind::Semi => ";", 165 | TokenKind::Assign => "=", 166 | TokenKind::OpenParen => "(", 167 | TokenKind::CloseParen => ")", 168 | TokenKind::Comma => ",", 169 | TokenKind::Str(str) => str, 170 | TokenKind::Num(num) => return write!(f, "{}", num), 171 | TokenKind::Ident(_) => todo!(), 172 | }; 173 | 174 | write!(f, "{}", x) 175 | } 176 | } 177 | 178 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 179 | pub struct Error { 180 | pub kind: ErrorKind, 181 | pub span: Span, 182 | } 183 | 184 | impl Error { 185 | fn new(kind: ErrorKind, span: Span) -> Self { 186 | Self { kind, span } 187 | } 188 | } 189 | 190 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] 191 | pub enum ErrorKind { 192 | UnexpectedEof, 193 | InvalidCharacter(char), 194 | } 195 | 196 | impl Spanned for Error { 197 | fn span(&self) -> Span { 198 | self.span 199 | } 200 | } 201 | 202 | impl Report for Error { 203 | fn report(&self, f: &mut Reporter<'_, W>) -> std::io::Result<()> { 204 | match self.kind { 205 | ErrorKind::InvalidCharacter(ch) => write!(f.out, "Invalid character '{}'", ch), 206 | ErrorKind::UnexpectedEof => write!(f.out, "Found unexpected EOF"), 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(rust_2018_idioms)] 2 | 3 | mod codegen; 4 | mod emit; 5 | mod error; 6 | mod lex; 7 | mod parse; 8 | mod rand; 9 | mod span; 10 | 11 | pub use codegen::Codegen; 12 | pub use error::{Report, Reporter}; 13 | pub use lex::Lexer; 14 | pub use parse::Parser; 15 | pub use span::{Span, Spanned, WithSpan}; 16 | 17 | fn main() { 18 | let input = std::env::args().nth(1).unwrap_or_else(|| { 19 | eprintln!("invalid arguments"); 20 | std::process::exit(1) 21 | }); 22 | 23 | let mut reporter = Reporter::new(std::io::stderr(), &input); 24 | 25 | match run(&input) { 26 | Ok(()) => {} 27 | Err(e) => reporter.exit(e), 28 | } 29 | } 30 | 31 | fn run(input: &str) -> Result<(), Box>> { 32 | let lexer = Lexer::new(input); 33 | let expr = Parser::new(lexer).parse()?; 34 | emit::emit(&expr)?; 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /src/parse.rs: -------------------------------------------------------------------------------- 1 | use crate::lex::{self, Lexer, Token, TokenKind}; 2 | use crate::{Report, Reporter, Span, Spanned, WithSpan}; 3 | 4 | use std::io::Write; 5 | use std::mem; 6 | 7 | pub struct Parser<'a> { 8 | tokens: Tokens<'a>, 9 | vars: Vec, 10 | } 11 | 12 | impl<'a> Parser<'a> { 13 | pub fn new(lexer: Lexer<'a>) -> Self { 14 | Self { 15 | tokens: Tokens { 16 | lexer, 17 | peeked: None, 18 | }, 19 | vars: Vec::new(), 20 | } 21 | } 22 | 23 | fn peek(&mut self) -> Result>, lex::Error> { 24 | self.tokens.peek().copied().transpose() 25 | } 26 | 27 | fn next(&mut self) -> Result>, lex::Error> { 28 | self.tokens.next().transpose() 29 | } 30 | 31 | fn chomp(&mut self) { 32 | let _ = self.next().unwrap(); 33 | } 34 | 35 | pub fn parse(&mut self) -> Result { 36 | let mut exprs = Vec::new(); 37 | 38 | while let Some(expr) = self.expr(0)? { 39 | let token = self.next()?; 40 | 41 | if !matches!( 42 | token, 43 | Some(Token { 44 | kind: TokenKind::Semi, 45 | .. 46 | }), 47 | ) { 48 | return Err(Error::new( 49 | ErrorKind::UnterminatedExpression, 50 | token.map(|t| t.span).unwrap_or(Span::EOF), 51 | )); 52 | } 53 | 54 | exprs.push(expr); 55 | } 56 | 57 | Ok(Ast { 58 | exprs, 59 | vars: mem::take(&mut self.vars), 60 | }) 61 | } 62 | 63 | pub fn expr(&mut self, precedence: usize) -> Result, Error> { 64 | let mut expr = match self.primary()? { 65 | Some(e) => e, 66 | None => return Ok(None), 67 | }; 68 | 69 | loop { 70 | let token = match self.peek()? { 71 | Some(t) => t, 72 | None => return Ok(Some(expr)), 73 | }; 74 | 75 | let op = match token.kind { 76 | TokenKind::Add => BinaryOp::Add, 77 | TokenKind::Sub => BinaryOp::Sub, 78 | TokenKind::Mul => BinaryOp::Mul, 79 | TokenKind::Div => BinaryOp::Div, 80 | TokenKind::Assign => BinaryOp::Assign, 81 | TokenKind::Semi | TokenKind::CloseParen => return Ok(Some(expr)), 82 | _ => return Err(Error::new(ErrorKind::ExpectedOperator, token.span)), 83 | }; 84 | 85 | if op.precedence() < precedence { 86 | return Ok(Some(expr)); 87 | } 88 | 89 | self.chomp(); 90 | 91 | let right = self.expr(op.precedence() + 1)?.ok_or(Error::EOF)?; 92 | 93 | expr = Expr { 94 | span: expr.span + right.span, 95 | kind: ExprKind::Binary(BinaryExpr { 96 | op: WithSpan::new(op, token.span), 97 | left: Box::new(expr), 98 | right: Box::new(right), 99 | }), 100 | }; 101 | } 102 | } 103 | 104 | fn primary(&mut self) -> Result, Error> { 105 | let token = match self.next()? { 106 | Some(t) => t, 107 | None => { 108 | return Ok(None); 109 | } 110 | }; 111 | 112 | let kind = match token.kind { 113 | TokenKind::Num(num) => ExprKind::Lit(WithSpan::new(Lit::Num(num), token.span)), 114 | TokenKind::Str(lit) => { 115 | ExprKind::Lit(WithSpan::new(Lit::String(lit.to_owned()), token.span)) 116 | } 117 | TokenKind::Ident(var) => { 118 | if self.peek()?.map(|t| t.kind) == Some(TokenKind::OpenParen) { 119 | self.chomp(); 120 | return self.func_call(var, token.span); 121 | } 122 | 123 | let i = self 124 | .vars 125 | .iter() 126 | .position(|v| v.name == var) 127 | .unwrap_or_else(|| { 128 | self.vars.push(Var { 129 | name: var.to_owned(), 130 | }); 131 | self.vars.len() - 1 132 | }); 133 | 134 | ExprKind::Var(i) 135 | } 136 | _ => return Err(Error::new(ErrorKind::ExpectedExpression, token.span)), 137 | }; 138 | 139 | Ok(Some(Expr { 140 | kind, 141 | span: token.span, 142 | })) 143 | } 144 | 145 | fn func_call(&mut self, ident: &str, span: Span) -> Result, Error> { 146 | let mut args = Vec::new(); 147 | 148 | let end = loop { 149 | match self.peek() { 150 | Ok(Some(token)) if token.kind == TokenKind::CloseParen => { 151 | break token; 152 | } 153 | _ => {} 154 | } 155 | 156 | let arg = self.expr(0)?.ok_or(Error::EOF)?; 157 | args.push(arg); 158 | 159 | let token = self.next()?.ok_or(Error::EOF)?; 160 | match token.kind { 161 | TokenKind::CloseParen => break token, 162 | TokenKind::Comma => continue, 163 | _ => return Err(Error::new(ErrorKind::ExpectedExpression, token.span)), 164 | } 165 | }; 166 | 167 | Ok(Some(Expr { 168 | kind: ExprKind::Call(Call { 169 | name: ident.to_owned(), 170 | args, 171 | }), 172 | span: span + end.span, 173 | })) 174 | } 175 | } 176 | 177 | pub struct Ast { 178 | pub exprs: Vec, 179 | pub vars: Vec, 180 | } 181 | 182 | pub struct Var { 183 | name: String, 184 | } 185 | 186 | pub struct Expr { 187 | pub kind: ExprKind, 188 | pub span: Span, 189 | } 190 | 191 | pub enum ExprKind { 192 | Lit(WithSpan), 193 | Binary(BinaryExpr), 194 | Call(Call), 195 | Var(usize), 196 | } 197 | 198 | pub struct Call { 199 | pub name: String, 200 | pub args: Vec, 201 | } 202 | 203 | pub enum Lit { 204 | Num(usize), 205 | String(String), 206 | } 207 | 208 | pub enum BinaryOp { 209 | Sub, 210 | Add, 211 | Mul, 212 | Div, 213 | Assign, 214 | } 215 | 216 | impl BinaryOp { 217 | fn precedence(&self) -> usize { 218 | match self { 219 | BinaryOp::Assign => 1, 220 | BinaryOp::Sub | BinaryOp::Add => 2, 221 | BinaryOp::Mul | BinaryOp::Div => 3, 222 | } 223 | } 224 | } 225 | 226 | pub struct BinaryExpr { 227 | pub left: Box, 228 | pub op: WithSpan, 229 | pub right: Box, 230 | } 231 | 232 | #[derive(Debug, PartialEq, Eq, Clone)] 233 | pub struct Error { 234 | pub kind: ErrorKind, 235 | pub span: Span, 236 | } 237 | 238 | #[derive(Debug, PartialEq, Eq, Clone)] 239 | pub enum ErrorKind { 240 | ExpectedNumber, 241 | ExpectedOperator, 242 | ExpectedExpression, 243 | UnexpectedEof, 244 | UnterminatedExpression, 245 | Lex(lex::Error), 246 | } 247 | 248 | impl Error { 249 | const EOF: Error = Error { 250 | kind: ErrorKind::UnexpectedEof, 251 | span: Span::EOF, 252 | }; 253 | 254 | fn new(kind: ErrorKind, span: Span) -> Self { 255 | Self { kind, span } 256 | } 257 | } 258 | 259 | impl Report for Error { 260 | fn report(&self, f: &mut Reporter<'_, W>) -> std::io::Result<()> { 261 | use ErrorKind::*; 262 | 263 | match self.kind { 264 | ExpectedExpression => write!( 265 | f.out, 266 | "Expected expression, found '{}'", 267 | self.span.range().map(|x| &f.source[x]).unwrap_or("EOF") 268 | ), 269 | ExpectedOperator => write!( 270 | f.out, 271 | "Expected binary operator, found '{}'", 272 | self.span.range().map(|x| &f.source[x]).unwrap_or("EOF") 273 | ), 274 | ExpectedNumber => write!(f.out, "Expected number"), 275 | UnexpectedEof => write!(f.out, "Unexpected EOF"), 276 | UnterminatedExpression => write!(f.out, "Unterminated expression"), 277 | Lex(ref err) => err.report(f), 278 | } 279 | } 280 | } 281 | 282 | impl From for Error { 283 | fn from(err: lex::Error) -> Self { 284 | Self { 285 | kind: ErrorKind::Lex(err), 286 | span: err.span, 287 | } 288 | } 289 | } 290 | 291 | impl Spanned for Error { 292 | fn span(&self) -> Span { 293 | self.span 294 | } 295 | } 296 | 297 | pub struct Tokens<'a> { 298 | lexer: Lexer<'a>, 299 | peeked: Option, lex::Error>>>, 300 | } 301 | 302 | impl<'a> Tokens<'a> { 303 | pub fn peek(&mut self) -> Option<&Result, lex::Error>> { 304 | if let Some(ref token) = self.peeked { 305 | return token.as_ref(); 306 | } 307 | 308 | loop { 309 | match self.lexer.next() { 310 | Some(Ok(Token { 311 | kind: TokenKind::Whitespace, 312 | .. 313 | })) => continue, 314 | t => { 315 | self.peeked.replace(t); 316 | break self.peeked.as_ref().unwrap().as_ref(); 317 | } 318 | } 319 | } 320 | } 321 | } 322 | 323 | impl<'a> Iterator for Tokens<'a> { 324 | type Item = Result, lex::Error>; 325 | 326 | fn next(&mut self) -> Option { 327 | loop { 328 | let token = match self.peeked.take() { 329 | Some(v) => v, 330 | None => self.lexer.next(), 331 | }; 332 | 333 | match token { 334 | Some(Ok(Token { 335 | kind: TokenKind::Whitespace, 336 | .. 337 | })) => continue, 338 | t => break t, 339 | } 340 | } 341 | } 342 | } 343 | 344 | impl<'a> std::ops::Deref for Tokens<'a> { 345 | type Target = Lexer<'a>; 346 | 347 | fn deref(&self) -> &Self::Target { 348 | &self.lexer 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /src/rand.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | use std::collections::hash_map::DefaultHasher; 3 | use std::hash::{Hash, Hasher}; 4 | use std::thread; 5 | use std::time::Instant; 6 | 7 | pub fn rand() -> u64 { 8 | pub struct FastRng(Cell); 9 | 10 | thread_local! { 11 | static RNG: FastRng = FastRng(Cell::new({ 12 | let mut hasher = DefaultHasher::new(); 13 | Instant::now().hash(&mut hasher); 14 | thread::current().id().hash(&mut hasher); 15 | (hasher.finish() << 1) | 1 16 | })); 17 | } 18 | 19 | RNG.with(|rng| { 20 | let mut x = rng.0.get(); 21 | x ^= x >> 12; 22 | x ^= x << 25; 23 | x ^= x >> 27; 24 | rng.0.set(x); 25 | x.wrapping_mul(0x2545_f491_4f6c_dd1d) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /src/span.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Add, Range}; 2 | 3 | #[derive(Default, Clone, Copy, PartialEq, Eq, Debug)] 4 | pub struct Span { 5 | pub start: usize, 6 | pub end: usize, 7 | } 8 | 9 | impl Span { 10 | pub const EOF: Span = Span { start: 0, end: 0 }; 11 | 12 | pub fn new(Range { start, end }: Range) -> Self { 13 | Self { start, end } 14 | } 15 | 16 | pub fn range(&self) -> Option> { 17 | (*self != Self::EOF).then(|| self.start..self.end) 18 | } 19 | } 20 | 21 | impl Add for Span { 22 | type Output = Span; 23 | 24 | fn add(self, rhs: Span) -> Self::Output { 25 | Span::new(self.start..rhs.end) 26 | } 27 | } 28 | 29 | pub trait Spanned { 30 | fn span(&self) -> Span; 31 | } 32 | 33 | pub struct WithSpan { 34 | pub value: T, 35 | pub span: Span, 36 | } 37 | 38 | impl WithSpan { 39 | pub fn new(value: T, span: Span) -> Self { 40 | Self { value, span } 41 | } 42 | } 43 | 44 | impl Spanned for WithSpan { 45 | fn span(&self) -> Span { 46 | self.span 47 | } 48 | } 49 | --------------------------------------------------------------------------------