working transpiler
This commit is contained in:
+16
-16
@@ -2,7 +2,7 @@ use std::{fs, path::Path, process::Command};
|
||||
|
||||
use crate::{
|
||||
transpiler::{State, Transpiler},
|
||||
utils::{Problem, ProblemCap, ProblemType, Variables},
|
||||
utils::{Problem, ProblemCap, ProblemType},
|
||||
};
|
||||
|
||||
pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 {
|
||||
@@ -10,23 +10,23 @@ pub fn transpile(input_file: String, output_file: String, is_main: bool) -> u8 {
|
||||
let mut trsp = Transpiler {
|
||||
..Default::default()
|
||||
};
|
||||
let mut vars = Variables::new();
|
||||
if let Ok(file_contents) = fs::read_to_string(input_file) {
|
||||
let mut output_code = trsp.transpile(file_contents, 0, &mut vars);
|
||||
let output_code = trsp.transpile_code(file_contents, 0);
|
||||
println!("{output_code}");
|
||||
if is_main {
|
||||
output_code += "fn main() {";
|
||||
output_code += vars
|
||||
.get_var(
|
||||
"main".to_string(),
|
||||
&mut trsp,
|
||||
State {
|
||||
line: 0,
|
||||
column: 0,
|
||||
file: None,
|
||||
},
|
||||
)
|
||||
.as_str();
|
||||
output_code += "();}";
|
||||
// output_code += "fn main() {";
|
||||
// output_code += vars
|
||||
// .get_var(
|
||||
// "main".to_string(),
|
||||
// &mut trsp,
|
||||
// State {
|
||||
// line: 0,
|
||||
// column: 0,
|
||||
// file: None,
|
||||
// },
|
||||
// )
|
||||
// .as_str();
|
||||
// output_code += "();}";
|
||||
}
|
||||
if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) {}
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
use std::{fs, process};
|
||||
|
||||
mod compiler;
|
||||
mod parser;
|
||||
mod transpiler;
|
||||
mod utils;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use compiler::{compile_rust, transpile};
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
use pest::Parser;
|
||||
use pest_derive::Parser;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[grammar = "wyst.pest"]
|
||||
pub struct WystParser;
|
||||
|
||||
pub fn parse(input: String, rule: Rule) {
|
||||
match WystParser::parse(rule, &input) {
|
||||
Ok(parsed) => {
|
||||
for pair in parsed {
|
||||
println!("---------START--------");
|
||||
println!("{:?}", pair);
|
||||
println!("---------END--------");
|
||||
}
|
||||
// println!("{:#?}", parsed);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Ok: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
-69
@@ -1,9 +1,14 @@
|
||||
use crate::{
|
||||
parser::{self, Rule},
|
||||
utils::{ProblemCap, Variables},
|
||||
};
|
||||
use pest::iterators::{Pair, Pairs};
|
||||
use crate::utils::{ProblemCap};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// The Parser
|
||||
use pest::Parser;
|
||||
use pest_derive::Parser;
|
||||
#[derive(Parser)]
|
||||
#[grammar = "wyst.pest"]
|
||||
pub struct WystParser;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct State {
|
||||
pub line: u32,
|
||||
@@ -13,7 +18,6 @@ pub struct State {
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct Transpiler {
|
||||
pub matched_vars: Variables,
|
||||
pub problems: Vec<ProblemCap>,
|
||||
pub state: State,
|
||||
pub inject: Inject,
|
||||
@@ -40,7 +44,6 @@ impl Default for Inject {
|
||||
impl Default for Transpiler {
|
||||
fn default() -> Self {
|
||||
Transpiler {
|
||||
matched_vars: Variables::new(),
|
||||
inject: Inject::default(),
|
||||
problems: Vec::new(),
|
||||
state: State {
|
||||
@@ -52,74 +55,72 @@ impl Default for Transpiler {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_indexable(pairs: Pairs<Rule>) -> Vec<Pair<Rule>> {
|
||||
let mut arr: Vec<Pair<Rule>> = Vec::new();
|
||||
for pair in pairs {arr.push(pair)}
|
||||
arr
|
||||
|
||||
}
|
||||
|
||||
impl Transpiler {
|
||||
pub fn transpile(&mut self, code: String, indent: usize, vars: &mut Variables) -> String {
|
||||
// args: code, vars, &mut self.state.clone(), self
|
||||
let ast = parser::parse(code, Rule::top_expr);
|
||||
pub fn transpile_pairs(&mut self, pairs: Pairs<Rule>) -> String {
|
||||
let mut res = String::new();
|
||||
for pair in pairs {
|
||||
res+=self.transpile(pair).as_str();
|
||||
}
|
||||
res
|
||||
}
|
||||
pub fn transpile(&mut self, pair: Pair<Rule>) -> String {
|
||||
let mut res = String::new();
|
||||
let tokens = to_indexable(pair.clone().into_inner());
|
||||
match pair.as_rule() {
|
||||
Rule::func_def => {
|
||||
res += format!("fn {}({}) -> {} {}", tokens[1].as_str(),
|
||||
self.transpile_pairs(tokens[2].clone().into_inner()).as_str(),
|
||||
tokens[0].as_str(),
|
||||
self.transpile(tokens[3].clone())
|
||||
).as_str();
|
||||
}
|
||||
Rule::var_def => {
|
||||
res += format!("let mut {}: {}", tokens[1].as_str(), tokens[0].as_str()).as_str();
|
||||
}
|
||||
Rule::curly => {
|
||||
res += "{";
|
||||
res += &self.transpile_pairs(pair.clone().into_inner());
|
||||
res += "}";
|
||||
}
|
||||
Rule::code_expr => {
|
||||
res += &self.transpile_pairs(pair.clone().into_inner());
|
||||
}
|
||||
//TODO: use LibManager to manage the includes
|
||||
Rule::include_global => {}
|
||||
Rule::include => {}
|
||||
|
||||
_ => {
|
||||
res += " ";
|
||||
res += pair.as_str();
|
||||
res += " ";
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
pub fn transpile_code(&mut self, code: String, indent: usize) -> String {
|
||||
let mut res = String::new();
|
||||
match WystParser::parse(Rule::top_expr, &code) {
|
||||
Ok(parsed) => {
|
||||
for pair in parsed {
|
||||
res += self.transpile_pairs(pair.into_inner()).as_str();
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// println!("err: {}", e.line());
|
||||
println!("{}", e);
|
||||
}
|
||||
}
|
||||
if indent > 0 {
|
||||
res += " ".repeat(indent * 2).as_str();
|
||||
}
|
||||
// for a in ast {
|
||||
// let astval = extract_ast(a.clone());
|
||||
// if self.inject.inject {
|
||||
// for val in astval {
|
||||
// if val.contains("list_vx") {
|
||||
// for (name, var) in vars.clone().iter_mut() {
|
||||
// if self.inject.state.line > var.state.line
|
||||
// || var.vtype != VariableType::Var
|
||||
// {
|
||||
// self.matched_vars.vars.insert(name.clone(), var.clone());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// match a {
|
||||
// Ast::Variable(var_type, var_name) => {
|
||||
// res += format!("let mut {}: {}", var_name, var_type).as_str();
|
||||
// }
|
||||
// Ast::Function(var_type, var_name, round, curly) => {
|
||||
// res += format!(
|
||||
// "fn {}({}) -> {} {}\n{}{}\n",
|
||||
// var_name,
|
||||
// round,
|
||||
// var_type,
|
||||
// "{",
|
||||
// self.transpile(curly, indent + 1, &mut vars.clone()),
|
||||
// "}"
|
||||
// )
|
||||
// .as_str();
|
||||
// }
|
||||
// Ast::Struct(name, curly) => {
|
||||
// res += format!(
|
||||
// "struct {} {}\n{}{}\n",
|
||||
// name,
|
||||
// "{",
|
||||
// self.transpile(curly, indent + 1, &mut vars.clone()),
|
||||
// "}"
|
||||
// )
|
||||
// .as_str()
|
||||
// }
|
||||
// Ast::Rust(rs) => {
|
||||
// res += "{";
|
||||
// res += rs.as_str();
|
||||
// res += "}";
|
||||
// }
|
||||
// Ast::Single(x) => {
|
||||
// println!("{:?}", x);
|
||||
// let vals = extract_values(x);
|
||||
// match vals.0 {
|
||||
// 2 => res += vars.get_var(vals.1, self, vals.2).as_str(),
|
||||
// 3 => res += format!("({})", vals.1).as_str(),
|
||||
// 8 => res += vals.1.as_str(),
|
||||
// _ => {
|
||||
// res += vals.1.as_str();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if indent > 0 {
|
||||
res += "\n";
|
||||
res += " ".repeat((indent - 1) * 2).as_str();
|
||||
|
||||
+1
-227
@@ -1,8 +1,5 @@
|
||||
use crate::transpiler::State;
|
||||
use crate::transpiler::Transpiler;
|
||||
use rand::Rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ProblemType {
|
||||
@@ -22,227 +19,4 @@ pub struct Problem {
|
||||
pub problem_type: ProblemType,
|
||||
pub problem_msg: String,
|
||||
pub state: State,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum VariableType {
|
||||
Var,
|
||||
Func,
|
||||
Keyword,
|
||||
Struct,
|
||||
Namespace,
|
||||
Enum,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Variable {
|
||||
pub vtype: VariableType,
|
||||
pub desc: String,
|
||||
pub state: State,
|
||||
pub params: Variables,
|
||||
pub rname: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Variables {
|
||||
pub vars: HashMap<String, Variable>,
|
||||
}
|
||||
|
||||
impl Variables {
|
||||
pub fn new() -> Variables {
|
||||
Variables {
|
||||
vars: HashMap::from([
|
||||
(
|
||||
"void".to_string(),
|
||||
Variable {
|
||||
vtype: VariableType::Keyword,
|
||||
desc: "".to_string(),
|
||||
state: State {
|
||||
line: 0,
|
||||
column: 0,
|
||||
file: None,
|
||||
},
|
||||
params: Variables {
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
rname: "".to_string(),
|
||||
},
|
||||
),
|
||||
(
|
||||
"println".to_string(),
|
||||
Variable {
|
||||
vtype: VariableType::Keyword,
|
||||
desc: "".to_string(),
|
||||
state: State {
|
||||
line: 0,
|
||||
column: 0,
|
||||
file: None,
|
||||
},
|
||||
params: Variables {
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
rname: "println".to_string(),
|
||||
},
|
||||
),
|
||||
]),
|
||||
}
|
||||
}
|
||||
pub fn new_var(&mut self, name: String, state: State, desc: String) -> String {
|
||||
let rname = generate_varname();
|
||||
self.vars.insert(
|
||||
name,
|
||||
Variable {
|
||||
vtype: VariableType::Var,
|
||||
desc,
|
||||
state,
|
||||
params: Variables {
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
rname: rname.clone(),
|
||||
},
|
||||
);
|
||||
rname
|
||||
}
|
||||
|
||||
pub fn new_namespace(&mut self, name: String, state: State, desc: String) -> String {
|
||||
let rname = generate_varname();
|
||||
self.vars.insert(
|
||||
name,
|
||||
Variable {
|
||||
vtype: VariableType::Namespace,
|
||||
desc,
|
||||
state,
|
||||
params: Variables {
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
rname: rname.clone(),
|
||||
},
|
||||
);
|
||||
rname
|
||||
}
|
||||
|
||||
pub fn new_struct(&mut self, name: String, state: State, desc: String) -> String {
|
||||
let rname = generate_varname();
|
||||
self.vars.insert(
|
||||
name,
|
||||
Variable {
|
||||
vtype: VariableType::Struct,
|
||||
desc,
|
||||
state,
|
||||
params: Variables {
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
rname: rname.clone(),
|
||||
},
|
||||
);
|
||||
rname
|
||||
}
|
||||
pub fn new_enum(&mut self, name: String, state: State, desc: String) -> String {
|
||||
let rname = generate_varname();
|
||||
self.vars.insert(
|
||||
name,
|
||||
Variable {
|
||||
vtype: VariableType::Enum,
|
||||
desc,
|
||||
state,
|
||||
params: Variables {
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
rname: rname.clone(),
|
||||
},
|
||||
);
|
||||
rname
|
||||
}
|
||||
|
||||
// pub fn new_keyword(&mut self, name: String, state: State, desc: String) {
|
||||
// self.vars.insert(
|
||||
// name,
|
||||
// Variable {
|
||||
// vtype: VariableType::Keyword,
|
||||
// desc,
|
||||
// state,
|
||||
// params: Variables {
|
||||
// vars: HashMap::new(),
|
||||
// },
|
||||
// rname: generate_varname(),
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
|
||||
pub fn new_func(&mut self, name: String, state: State, desc: String) -> String {
|
||||
let rname = generate_varname();
|
||||
self.vars.insert(
|
||||
name,
|
||||
Variable {
|
||||
vtype: VariableType::Func,
|
||||
desc,
|
||||
state,
|
||||
params: Variables {
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
rname: rname.clone(),
|
||||
},
|
||||
);
|
||||
rname
|
||||
}
|
||||
pub fn get_var(&mut self, name: String, root: &mut Transpiler, state: State) -> String {
|
||||
if let Some(x) = self.get_mut(name.clone()) {
|
||||
return x.rname.clone();
|
||||
} else {
|
||||
root.problems.push(ProblemCap::Error(Problem {
|
||||
problem_type: ProblemType::VariableNotFound,
|
||||
problem_msg: format!("'{}' doesn't exist", &name),
|
||||
state: state,
|
||||
}));
|
||||
return name;
|
||||
}
|
||||
}
|
||||
pub fn iter_mut(
|
||||
&mut self,
|
||||
) -> std::collections::hash_map::IterMut<'_, std::string::String, Variable> {
|
||||
self.vars.iter_mut()
|
||||
}
|
||||
pub fn get_mut(&mut self, name: String) -> Option<&mut Variable> {
|
||||
if !name.contains("::") {
|
||||
return self.vars.get_mut(&name);
|
||||
}
|
||||
if let Some((x, _)) = name.split_once("::") {
|
||||
println!("{x}");
|
||||
if let Some(v) = self.vars.get_mut(x) {
|
||||
println!("{:?}", v);
|
||||
let mut var = v;
|
||||
for a in name.split("::") {
|
||||
if let Some(b) = var.params.vars.get_mut(a) {
|
||||
var = b;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
return Some(var);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn expand(&mut self, vars: Variables) {
|
||||
for (x, y) in vars.vars {
|
||||
self.vars.insert(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_varname() -> String {
|
||||
let mut rng = rand::thread_rng();
|
||||
let charset: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
||||
abcdefghijklmnopqrstuvwxyz\
|
||||
0123456789";
|
||||
let mut result = String::with_capacity(19);
|
||||
result.push('_');
|
||||
result.push('0');
|
||||
result.push('x');
|
||||
for _ in 0..14 {
|
||||
let random_char = charset[rng.gen_range(0..charset.len())] as char;
|
||||
result.push(random_char);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
+19
-11
@@ -1,18 +1,20 @@
|
||||
WHITESPACE = _{ " " | "\t" | "\n" }
|
||||
|
||||
// [chars]
|
||||
comma = {","}
|
||||
semicolon = {";"}
|
||||
|
||||
// [literals]
|
||||
filepath = { ("/" | identifier | "-" | "." )+ }
|
||||
filepath = { ("/"|('a'..'z' | 'a'..'z' | '0'..'9' | "_" | "-" | "."))+ }
|
||||
include = { "#" ~ "include" ~ "\"" ~ filepath ~ "\"" }
|
||||
include_global = { "#" ~ "include" ~ "<" ~ filepath ~ ">" }
|
||||
round = { "(" ~ (expr)* ~ ")" }
|
||||
round = { "(" ~ ((expr ~ comma)* ~ expr?) ~ ")" }
|
||||
curly = { "{" ~ (code_expr)* ~ "}" }
|
||||
escape = { "\\" ~ ANY }
|
||||
raw_string = { (!("\\" | "\"") ~ ANY)+ }
|
||||
string = { "\"" ~ (raw_string | escape )* ~ "\"" }
|
||||
char = { "'" ~ (escape | ANY) ~ "'" }
|
||||
bool = @{"true" | "false"}
|
||||
semicolon = {";"}
|
||||
|
||||
// [numbers]
|
||||
hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*}
|
||||
@@ -20,14 +22,18 @@ float = @{ ('0'..'9')* ~ "." ~ ('0'..'9')+ }
|
||||
int = @{ '0'..'9'+ }
|
||||
|
||||
// [identifiers]
|
||||
identifier = @{ !(hex|float|int) ~ ("_" | 'a'..'z' | 'a'..'z') ~ ( "_" | 'a'..'z' | 'a'..'z' | int )* }
|
||||
identifier = @{ !(hex|float|int) ~ ("." | "::" | "_" | 'a'..'z' | 'A'..'Z') ~ ( "." | "::" | "_" | 'a'..'z' | 'A'..'Z' | int )*}
|
||||
def_identifier = {identifier ~ ("<" ~ ((def_identifier ~ comma)* ~ def_identifier?) ~ ">")?}
|
||||
|
||||
// [definitions]
|
||||
var_def = { identifier ~ identifier }
|
||||
var_def_set = { var_def ~ "=" ~ expr ~ semicolon }
|
||||
func_def = { identifier ~ identifier ~ round ~ curly }
|
||||
round_def = { "(" ~ ((var_def ~ comma)* ~ var_def?) ~ ")" }
|
||||
var_def = { def_identifier ~ identifier }
|
||||
var_def_set = { var_def ~ "=" ~ expr }
|
||||
var_set = { def_identifier ~ "=" ~ expr }
|
||||
func_def = { def_identifier ~ identifier ~ round_def ~ curly }
|
||||
|
||||
expr = {
|
||||
(identifier ~ round) |
|
||||
round |
|
||||
curly |
|
||||
char |
|
||||
@@ -40,14 +46,16 @@ expr = {
|
||||
}
|
||||
|
||||
code_expr = {
|
||||
var_def_set |
|
||||
(var_def ~ semicolon)
|
||||
(var_def_set ~ semicolon) |
|
||||
(var_def ~ semicolon) |
|
||||
(var_set ~ semicolon) |
|
||||
(expr ~ semicolon)
|
||||
}
|
||||
|
||||
top_expr = {
|
||||
(
|
||||
func_def |
|
||||
include |
|
||||
include_global
|
||||
include_global |
|
||||
func_def
|
||||
)+
|
||||
}
|
||||
Reference in New Issue
Block a user