From fb1d42d910f5c0e4e557a05b4c77abbfd153fc0f Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Thu, 10 Dec 2020 20:51:49 -0700 Subject: [PATCH] More project cleanup --- build.rs | 5 +- src/codegen.rs | 56 +++++++--- src/lib.rs | 8 +- src/parse/combinators.rs | 66 +----------- src/parse/mod.rs | 222 ++++++++++++++++++++++----------------- 5 files changed, 177 insertions(+), 180 deletions(-) diff --git a/build.rs b/build.rs index 2381a9e..25c36ff 100644 --- a/build.rs +++ b/build.rs @@ -2,5 +2,8 @@ fn main() { println!("cargo:rerun-if-changed=test.js"); println!("cargo:rerun-if-changed=package.json"); println!("cargo:rerun-if-changed=package-lock.json"); - std::process::Command::new("npm").arg("install").output().expect("could not install npm dependencies"); + std::process::Command::new("npm") + .arg("install") + .output() + .expect("could not install npm dependencies"); } diff --git a/src/codegen.rs b/src/codegen.rs index e017116..cad51b5 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,14 +1,12 @@ -use ron::from_str; use crate::ast::{AstNode, AstNodeKind}; +use ron::from_str; pub struct SymbolGenerator { counter: usize, } impl SymbolGenerator { pub fn new() -> SymbolGenerator { - SymbolGenerator { - counter: 0, - } + SymbolGenerator { counter: 0 } } pub fn next(&mut self) -> usize { self.counter += 1; @@ -29,12 +27,36 @@ impl Wasm for AstNode { // Unary operators Not => format!("(i32.eq (i32.const 0) {})", self.subnodes[1].emit(s)), // Infix operators - NotEqual => format!("(i32.ne {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)), - Equal => format!("(i32.eq {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)), - Add => format!("(i32.add {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)), - Subtract => format!("(i32.sub {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)), - Multiply => format!("(i32.mul {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)), - Divide => format!("(i32.div_s {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)), + NotEqual => format!( + "(i32.ne {} {})", + self.subnodes[0].emit(s), + self.subnodes[1].emit(s) + ), + Equal => format!( + "(i32.eq {} {})", + self.subnodes[0].emit(s), + self.subnodes[1].emit(s) + ), + Add => format!( + "(i32.add {} {})", + self.subnodes[0].emit(s), + self.subnodes[1].emit(s) + ), + Subtract => format!( + "(i32.sub {} {})", + self.subnodes[0].emit(s), + self.subnodes[1].emit(s) + ), + Multiply => format!( + "(i32.mul {} {})", + self.subnodes[0].emit(s), + self.subnodes[1].emit(s) + ), + Divide => format!( + "(i32.div_s {} {})", + self.subnodes[0].emit(s), + self.subnodes[1].emit(s) + ), // Control flow Block => { let mut out = String::new(); @@ -46,7 +68,11 @@ impl Wasm for AstNode { } IfStatement => { let mut out = String::new(); - out += &format!("(if {} (then {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)); // Emit the conditional and consequence. + out += &format!( + "(if {} (then {})", + self.subnodes[0].emit(s), + self.subnodes[1].emit(s) + ); // Emit the conditional and consequence. if let Some(alternative) = self.subnodes.get(2) { out += &format!(" (else {})", alternative.emit(s)); // Emit the alternative. } @@ -59,7 +85,11 @@ impl Wasm for AstNode { out += &format!("(block ${}_wrapper", loop_symbol); out += &format!(" (loop ${}_loop", loop_symbol); out += &format!(" {}", self.subnodes[1].emit(s)); - out += &format!(" (br_if ${}_wrapper (i32.eq (i32.const 0) {}))", loop_symbol, self.subnodes[0].emit(s)); + out += &format!( + " (br_if ${}_wrapper (i32.eq (i32.const 0) {}))", + loop_symbol, + self.subnodes[0].emit(s) + ); out += &format!(" (br ${}_loop)", loop_symbol); out += "))"; out @@ -91,7 +121,7 @@ impl Wasm for AstNode { } out += ")"; out - }, + } FunctionReturn => format!("{} (return)", self.subnodes[0].emit(s)), FunctionDefinition => { let mut out = String::new(); diff --git a/src/lib.rs b/src/lib.rs index 874bb90..4fae7e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,10 @@ -#![allow(unused_variables)] -#![allow(non_snake_case)] -#![allow(dead_code)] - extern crate regex; extern crate wat; pub mod ast; -pub mod parse; pub mod codegen; -use codegen::{Wasm, SymbolGenerator}; +pub mod parse; +use codegen::{SymbolGenerator, Wasm}; pub fn compile>(src: T) -> Vec { wat::parse_str(compile_wat(src)).unwrap() diff --git a/src/parse/combinators.rs b/src/parse/combinators.rs index de28ddb..f042cce 100644 --- a/src/parse/combinators.rs +++ b/src/parse/combinators.rs @@ -4,15 +4,11 @@ use std::ops::Range; use std::rc::Rc; pub enum ParserKind { - Literal(String), Regex(Regex), - Constant(String), And, Ignore, Or, - Repeat(usize), RepeatRange(Range), - Error(String), Map(Rc Result>>), Custom(Rc Result<(String, String), String>>>), } @@ -25,15 +21,11 @@ impl std::fmt::Display for ParserKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use ParserKind::*; match self { - Literal(s) => write!(f, "Literal \"{}\"", s), Regex(r) => write!(f, "Regex /{}/", r.as_str()), - Constant(c) => write!(f, "Constant \"{}\"", c), And => write!(f, "And"), Ignore => write!(f, "Ignore"), Or => write!(f, "Or"), - Repeat(num) => write!(f, "Repeat {}", num), RepeatRange(range) => write!(f, "RepeatRange {:?}", range), - Error(msg) => write!(f, "Error \"{}\"", msg), Map(_) => write!(f, "Map"), Custom(_) => write!(f, "Custom"), } @@ -43,15 +35,11 @@ impl Clone for ParserKind { fn clone(&self) -> Self { use ParserKind::*; match self { - Literal(s) => Literal(s.clone()), Regex(r) => Regex(r.clone()), - Constant(c) => Constant(c.clone()), And => And, Ignore => Ignore, Or => Or, - Repeat(num) => Repeat(num.clone()), RepeatRange(range) => RepeatRange(range.clone()), - Error(msg) => Error(msg.clone()), Map(cfn) => Map(Rc::clone(cfn)), Custom(cfn) => Custom(Rc::clone(cfn)), } @@ -78,13 +66,6 @@ impl Parser { use ParserKind::*; let s: String = src.into(); match &self.kind { - Literal(literal) => { - if s.len() >= literal.len() && s[..literal.len()] == literal[..] { - Ok((s[..literal.len()].to_owned(), s[literal.len()..].to_owned())) - } else { - Err(s) - } - } Regex(re) => { if let Some(mat) = re.find(&s) { if mat.start() == 0 { @@ -99,10 +80,8 @@ impl Parser { Err(s) } } - Constant(constant) => Ok((constant.clone(), s)), And => { - if self.subparsers[0].kind == Ignore - && self.subparsers[1].kind == Ignore { + if self.subparsers[0].kind == Ignore && self.subparsers[1].kind == Ignore { Ok(("".into(), s)) } else if self.subparsers[0].kind == Ignore { let (_, rest) = self.subparsers[0].parse(s)?; @@ -123,9 +102,7 @@ impl Parser { )) } } - Ignore => { - Ok(("".into(), self.subparsers[0].parse(s)?.1)) - } + Ignore => Ok(("".into(), self.subparsers[0].parse(s)?.1)), Or => { if let Ok(lresult) = self.subparsers[0].parse(s.clone()) { Ok(lresult) @@ -133,16 +110,6 @@ impl Parser { self.subparsers[1].parse(s.clone()) } } - Repeat(num_repeats) => { - let mut matched = vec![]; - let mut rest = s.clone(); - for _ in 0..*num_repeats { - let (m, r) = self.subparsers[0].parse(rest)?; - matched.push(m); - rest = r; - } - Ok((to_string(&matched).unwrap(), rest)) - } RepeatRange(range) => { let mut matched = vec![]; let mut rest = s.clone(); @@ -169,7 +136,6 @@ impl Parser { Ok((to_string(&matched).unwrap(), rest)) } - Error(msg) => panic!(msg.clone()), Map(cfn) => { let (matched, rest) = self.subparsers[0].parse(s)?; if let Ok(m) = cfn(matched) { @@ -178,37 +144,17 @@ impl Parser { Err(rest) } } - Custom(cfn) => { - cfn(s) - } + Custom(cfn) => cfn(s), } } // Static - pub fn literal>(s: T) -> Parser { - Parser { - kind: ParserKind::Literal(s.into()), - subparsers: vec![], - } - } pub fn regex>(s: T) -> Parser { Parser { kind: ParserKind::Regex(Regex::new(&s.into()).expect("could not compile regex")), subparsers: vec![], } } - pub fn constant>(s: T) -> Parser { - Parser { - kind: ParserKind::Constant(s.into()), - subparsers: vec![], - } - } - pub fn error>(s: T) -> Parser { - Parser { - kind: ParserKind::Error(s.into()), - subparsers: vec![], - } - } pub fn custom(cfn: F) -> Parser where F: Fn(String) -> Result<(String, String), String>, @@ -238,12 +184,6 @@ impl Parser { subparsers: vec![self, r], } } - pub fn repeat(self, num_repeats: usize) -> Parser { - Parser { - kind: ParserKind::Repeat(num_repeats), - subparsers: vec![self], - } - } pub fn repeat_range(self, num_repeats: Range) -> Parser { Parser { kind: ParserKind::RepeatRange(num_repeats), diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 1d57617..55c3c3b 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -9,8 +9,12 @@ pub fn parse>(src: T) -> AstNode { let whitespace = Parser::regex(r"[ \n\r\t]+"); let comments = Parser::regex(r"[/][/].*").or(Parser::regex(r"[/][*].*[*][/]")); let ignored = whitespace.or(comments).repeat_range(0..usize::MAX); - let statement = ignored.optional().ignore().and(Parser::custom(parse_statement)); - let parse_program = statement.clone() + let statement = ignored + .optional() + .ignore() + .and(Parser::custom(parse_statement)); + let parse_program = statement + .clone() .repeat_range(0..usize::MAX) .map(|matched| { let data = from_str::>(&matched)?; @@ -30,44 +34,51 @@ fn parse_statement(src: String) -> Result<(String, String), String> { let i = ignored.clone(); let token = move |pattern: &str| i.clone().ignore().and(Parser::regex(pattern)); // Token helper parsers. - let FUNCTION = Parser::regex(r"function\b").or(ignored.clone()); - let RETURN = token(r"return\b"); - let SEMICOLON = token(r"[;]"); - let IF = token(r"if\b"); - let ELSE = token(r"else\b"); - let LEFT_PAREN = token(r"[(]"); - let RIGHT_PAREN = token(r"[)]"); - let LEFT_BRACE = token(r"[{]"); - let RIGHT_BRACE = token(r"[}]"); - let WHILE = token(r"while\b"); - let VAR = token(r"var\b"); - let IDENTIFIER = token(r"[a-zA-Z_][a-zA-Z0-9_]*") + let function = Parser::regex(r"function\b").or(ignored.clone()); + let return_token = token(r"return\b"); + let semicolon = token(r"[;]"); + let if_token = token(r"if\b"); + let else_token = token(r"else\b"); + let left_paren = token(r"[(]"); + let right_paren = token(r"[)]"); + let left_brace = token(r"[{]"); + let right_brace = token(r"[}]"); + let while_token = token(r"while\b"); + let var = token(r"var\b"); + let identifier = token(r"[a-zA-Z_][a-zA-Z0-9_]*") .map(|matched| Ok(to_string(&AstNode::identifier(matched))?)); - let ASSIGN = - token(r"=").map(|matched| Ok(to_string(&AstNode::assign("".into(), AstNode::null()))?)); - let COMMA = token(r"[,]"); + let assign = + token(r"=").map(|_matched| Ok(to_string(&AstNode::assign("".into(), AstNode::null()))?)); + let comma = token(r"[,]"); let expression = Parser::custom(parse_expression); let statement = Parser::custom(parse_statement); - let return_statement = RETURN.clone().ignore() + let return_statement = return_token + .clone() + .ignore() .and(expression.clone()) - .and(SEMICOLON.clone().ignore()) + .and(semicolon.clone().ignore()) .map(|matched| { let data = from_str::(&matched)?; Ok(to_string(&AstNode::function_return(data))?) }); - let expression_statement = expression.clone() - .and(SEMICOLON.clone().ignore()); - let if_statement = IF.clone().ignore() + let expression_statement = expression.clone().and(semicolon.clone().ignore()); + let if_statement = if_token + .clone() + .ignore() .and( - LEFT_PAREN.clone().ignore() - .and(expression.clone()) - .and(RIGHT_PAREN.clone().ignore()) + left_paren + .clone() + .ignore() + .and(expression.clone()) + .and(right_paren.clone().ignore()), ) .and(statement.clone()) .and( - ELSE.clone().ignore() - .and(statement.clone()) - .optional() + else_token + .clone() + .ignore() + .and(statement.clone()) + .optional(), ) .map(|matched| { let data = from_str::>(&matched)?; @@ -79,13 +90,21 @@ fn parse_statement(src: String) -> Result<(String, String), String> { let others = from_str::>(&data[0])?; let conditional = from_str::(&others[0])?; let consequence = from_str::(&others[1])?; - Ok(to_string(&AstNode::if_statement(conditional, consequence, alternative))?) + Ok(to_string(&AstNode::if_statement( + conditional, + consequence, + alternative, + ))?) }); - let while_statement = WHILE.clone().ignore() + let while_statement = while_token + .clone() + .ignore() .and( - LEFT_PAREN.clone().ignore() - .and(expression.clone()) - .and(RIGHT_PAREN.clone().ignore()) + left_paren + .clone() + .ignore() + .and(expression.clone()) + .and(right_paren.clone().ignore()), ) .and(statement.clone()) .map(|matched| { @@ -94,30 +113,35 @@ fn parse_statement(src: String) -> Result<(String, String), String> { let body = from_str::(&data[1])?; Ok(to_string(&AstNode::while_loop(conditional, body))?) }); - let var_statement = VAR.clone().ignore() - .and(IDENTIFIER.clone()) - .and(ASSIGN.clone().ignore()) + let var_statement = var + .clone() + .ignore() + .and(identifier.clone()) + .and(assign.clone().ignore()) .and(expression.clone()) - .and(SEMICOLON.clone().ignore()) + .and(semicolon.clone().ignore()) .map(|matched| { let data = from_str::>(&matched)?; let name = from_str::(&data[0])?.value; let value = from_str::(&data[1])?; Ok(to_string(&AstNode::variable_definition(name, value))?) }); - let assignment_statement = IDENTIFIER.clone() - .and(ASSIGN.clone().ignore()) + let assignment_statement = identifier + .clone() + .and(assign.clone().ignore()) .and(expression.clone()) - .and(SEMICOLON.clone().ignore()) + .and(semicolon.clone().ignore()) .map(|matched| { let data = from_str::>(&matched)?; let name = from_str::(&data[0])?.value; let value = from_str::(&data[1])?; Ok(to_string(&AstNode::assign(name, value))?) }); - let block_statement = LEFT_BRACE.clone().ignore() + let block_statement = left_brace + .clone() + .ignore() .and(statement.clone().repeat_range(0..usize::MAX)) - .and(RIGHT_BRACE.clone().ignore()) + .and(right_brace.clone().ignore()) .map(|matched| { let data = from_str::>(&matched)?; let mut statements = vec![]; @@ -126,10 +150,13 @@ fn parse_statement(src: String) -> Result<(String, String), String> { } Ok(to_string(&AstNode::block(statements))?) }); - let args = IDENTIFIER.clone() + let args = identifier + .clone() .and( - COMMA.clone().ignore() - .and(IDENTIFIER.clone()) + comma + .clone() + .ignore() + .and(identifier.clone()) .repeat_range(0..usize::MAX), ) .map(|matched| { @@ -142,12 +169,16 @@ fn parse_statement(src: String) -> Result<(String, String), String> { } Ok(to_string(&args)?) }); - let function_statement = FUNCTION.clone().ignore() - .and(IDENTIFIER.clone()) + let function_statement = function + .clone() + .ignore() + .and(identifier.clone()) .and( - LEFT_PAREN.clone().ignore() - .and(args.clone().optional()) - .and(RIGHT_PAREN.clone().ignore()) + left_paren + .clone() + .ignore() + .and(args.clone().optional()) + .and(right_paren.clone().ignore()), ) .and(block_statement.clone()) .map(|matched| { @@ -169,16 +200,22 @@ fn parse_statement(src: String) -> Result<(String, String), String> { match node.kind { AstNodeKind::VariableDefinition => { vars.push(AstNode::variable_declaration(node.value.clone())); - others.push(AstNode::assign(node.value.clone(), node.subnodes[0].clone())) - }, + others.push(AstNode::assign( + node.value.clone(), + node.subnodes[0].clone(), + )) + } _ => others.push(node.clone()), } } vars.append(&mut others); body.subnodes = vars; - Ok(to_string(&AstNode::function_definition(name, parameters, body))?) + Ok(to_string(&AstNode::function_definition( + name, parameters, body, + ))?) }); - return_statement.clone() + return_statement + .clone() .or(if_statement.clone()) .or(while_statement.clone()) .or(var_statement.clone()) @@ -196,55 +233,44 @@ fn parse_expression(src: String) -> Result<(String, String), String> { let i = ignored.clone(); let token = move |pattern: &str| i.clone().ignore().and(Parser::regex(pattern)); // Token helper parsers. - let FUNCTION = Parser::regex(r"function\b").or(ignored.clone()); - let IF = token(r"if\b"); - let ELSE = token(r"else\b"); - let RETURN = token(r"return\b"); - let VAR = token(r"var\b"); - let WHILE = token(r"while\b"); - let COMMA = token(r"[,]"); - let SEMICOLON = token(r"[;]"); - let LEFT_PAREN = token(r"[(]"); - let RIGHT_PAREN = token(r"[)]"); - let LEFT_BRACE = token(r"[{]"); - let RIGHT_BRACE = token(r"[}]"); - let NUMBER = token(r"[0-9]+").map(|matched| { + let comma = token(r"[,]"); + let left_paren = token(r"[(]"); + let right_paren = token(r"[)]"); + let number = token(r"[0-9]+").map(|matched| { Ok(to_string(&AstNode::integer( matched.parse::().unwrap(), ))?) }); - let IDENTIFIER = token(r"[a-zA-Z_][a-zA-Z0-9_]*") + let identifier = token(r"[a-zA-Z_][a-zA-Z0-9_]*") .map(|matched| Ok(to_string(&AstNode::identifier(matched))?)); - let NOT = token(r"!").map(|matched| Ok(to_string(&AstNode::not(AstNode::null()))?)); - let ASSIGN = - token(r"=").map(|matched| Ok(to_string(&AstNode::assign("".into(), AstNode::null()))?)); - let EQUAL = token(r"==").map(|matched| { + let not = token(r"!").map(|_matched| Ok(to_string(&AstNode::not(AstNode::null()))?)); + let equal = token(r"==").map(|_matched| { Ok(to_string(&AstNode::equal( AstNode::null(), AstNode::null(), ))?) }); - let NOT_EQUAL = token(r"!=").map(|matched| { + let not_equal = token(r"!=").map(|_matched| { Ok(to_string(&AstNode::not_equal( AstNode::null(), AstNode::null(), ))?) }); - let PLUS = token(r"[+]") - .map(|matched| Ok(to_string(&AstNode::add(AstNode::null(), AstNode::null()))?)); - let MINUS = token(r"[-]").map(|matched| { + let plus = token(r"[+]") + .map(|_matched| Ok(to_string(&AstNode::add(AstNode::null(), AstNode::null()))?)); + let minus = token(r"[-]").map(|_matched| { Ok(to_string(&AstNode::subtract( AstNode::null(), AstNode::null(), ))?) }); - let STAR = token(r"[*]").map(|matched| { + let star = token(r"[*]").map(|_matched| { Ok(to_string(&AstNode::multiply( AstNode::null(), AstNode::null(), ))?) }); - let SLASH = token(r"[/]").map(|matched| { + let slash = token(r"[/]").map(|_matched| { Ok(to_string(&AstNode::divide( AstNode::null(), AstNode::null(), @@ -253,9 +279,12 @@ fn parse_expression(src: String) -> Result<(String, String), String> { // Expression parser. let expression = Parser::custom(parse_expression); // Call parser. - let args = expression.clone() + let args = expression + .clone() .and( - COMMA.clone().ignore() + comma + .clone() + .ignore() .and(expression.clone()) .repeat_range(0..usize::MAX), ) @@ -269,10 +298,11 @@ fn parse_expression(src: String) -> Result<(String, String), String> { } Ok(to_string(&args)?) }); - let call = IDENTIFIER.clone() - .and(LEFT_PAREN.clone().ignore()) + let call = identifier + .clone() + .and(left_paren.clone().ignore()) .and(args.clone().optional()) - .and(RIGHT_PAREN.clone().ignore()) + .and(right_paren.clone().ignore()) .map(|matched| { let data = from_str::>(&matched)?; let callee = data[0].clone(); @@ -284,22 +314,20 @@ fn parse_expression(src: String) -> Result<(String, String), String> { ast_args.push(from_str::(arg)?); } } - Ok(to_string( - &AstNode::function_call(callee, ast_args), - )?) + Ok(to_string(&AstNode::function_call(callee, ast_args))?) }); // Atom parser. let atom = call .clone() - .or(IDENTIFIER.clone()) - .or(NUMBER.clone()) - .or( - LEFT_PAREN.clone().ignore() - .and(expression.clone()) - .and(RIGHT_PAREN.clone().ignore()) - ); + .or(identifier.clone()) + .or(number.clone()) + .or(left_paren + .clone() + .ignore() + .and(expression.clone()) + .and(right_paren.clone().ignore())); // Unary operator parsers. - let unary = NOT.clone().optional().and(atom.clone()).map(|matched| { + let unary = not.clone().optional().and(atom.clone()).map(|matched| { let data = from_str::>(&matched)?; let atom_data = from_str::(&data[1])?; Ok(to_string(&match &data[0][..] { @@ -331,8 +359,8 @@ fn parse_expression(src: String) -> Result<(String, String), String> { Ok(to_string(¤t)?) }) }; - let product = infix(STAR.clone().or(SLASH.clone()), unary.clone()); - let sum = infix(PLUS.clone().or(MINUS.clone()), product.clone()); - let comparison = infix(EQUAL.clone().or(NOT_EQUAL.clone()), sum.clone()); + let product = infix(star.clone().or(slash.clone()), unary.clone()); + let sum = infix(plus.clone().or(minus.clone()), product.clone()); + let comparison = infix(equal.clone().or(not_equal.clone()), sum.clone()); comparison.parse(src) }