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