working transpiler

This commit is contained in:
2024-07-14 18:13:08 +02:00
parent 9e5079151b
commit 023ada1506
7 changed files with 108 additions and 347 deletions
+1 -1
View File
@@ -14,5 +14,5 @@ lsp-types = "0.97.0"
zip = "2.1.3" zip = "2.1.3"
dirs = "5.0.1" dirs = "5.0.1"
pest = "2" pest = "2"
pest_derive = "2" pest_derive = "2.1"
clap = "3" clap = "3"
+16 -16
View File
@@ -2,7 +2,7 @@ use std::{fs, path::Path, process::Command};
use crate::{ use crate::{
transpiler::{State, Transpiler}, 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 { 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 { let mut trsp = Transpiler {
..Default::default() ..Default::default()
}; };
let mut vars = Variables::new();
if let Ok(file_contents) = fs::read_to_string(input_file) { 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 { if is_main {
output_code += "fn main() {"; // output_code += "fn main() {";
output_code += vars // output_code += vars
.get_var( // .get_var(
"main".to_string(), // "main".to_string(),
&mut trsp, // &mut trsp,
State { // State {
line: 0, // line: 0,
column: 0, // column: 0,
file: None, // file: None,
}, // },
) // )
.as_str(); // .as_str();
output_code += "();}"; // output_code += "();}";
} }
if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) {} if let Ok(_) = fs::write(Path::new("build").join(output_file), output_code) {}
} else { } else {
+1 -1
View File
@@ -1,9 +1,9 @@
use std::{fs, process}; use std::{fs, process};
mod compiler; mod compiler;
mod parser;
mod transpiler; mod transpiler;
mod utils; mod utils;
use clap::{App, Arg}; use clap::{App, Arg};
use compiler::{compile_rust, transpile}; use compiler::{compile_rust, transpile};
-22
View File
@@ -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
View File
@@ -1,9 +1,14 @@
use crate::{ use pest::iterators::{Pair, Pairs};
parser::{self, Rule}, use crate::utils::{ProblemCap};
utils::{ProblemCap, Variables},
};
use serde::{Deserialize, Serialize}; 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)] #[derive(Deserialize, Serialize, Debug, Clone)]
pub struct State { pub struct State {
pub line: u32, pub line: u32,
@@ -13,7 +18,6 @@ pub struct State {
#[derive(Deserialize, Serialize, Debug, Clone)] #[derive(Deserialize, Serialize, Debug, Clone)]
pub struct Transpiler { pub struct Transpiler {
pub matched_vars: Variables,
pub problems: Vec<ProblemCap>, pub problems: Vec<ProblemCap>,
pub state: State, pub state: State,
pub inject: Inject, pub inject: Inject,
@@ -40,7 +44,6 @@ impl Default for Inject {
impl Default for Transpiler { impl Default for Transpiler {
fn default() -> Self { fn default() -> Self {
Transpiler { Transpiler {
matched_vars: Variables::new(),
inject: Inject::default(), inject: Inject::default(),
problems: Vec::new(), problems: Vec::new(),
state: State { 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 { impl Transpiler {
pub fn transpile(&mut self, code: String, indent: usize, vars: &mut Variables) -> String { pub fn transpile_pairs(&mut self, pairs: Pairs<Rule>) -> String {
// args: code, vars, &mut self.state.clone(), self
let ast = parser::parse(code, Rule::top_expr);
let mut res = String::new(); 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 { if indent > 0 {
res += " ".repeat(indent * 2).as_str(); 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 { if indent > 0 {
res += "\n"; res += "\n";
res += " ".repeat((indent - 1) * 2).as_str(); res += " ".repeat((indent - 1) * 2).as_str();
-226
View File
@@ -1,8 +1,5 @@
use crate::transpiler::State; use crate::transpiler::State;
use crate::transpiler::Transpiler;
use rand::Rng;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ProblemType { pub enum ProblemType {
@@ -23,226 +20,3 @@ pub struct Problem {
pub problem_msg: String, pub problem_msg: String,
pub state: State, 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
View File
@@ -1,18 +1,20 @@
WHITESPACE = _{ " " | "\t" | "\n" } WHITESPACE = _{ " " | "\t" | "\n" }
// [chars]
comma = {","}
semicolon = {";"}
// [literals] // [literals]
filepath = { ("/" | identifier | "-" | "." )+ } filepath = { ("/"|('a'..'z' | 'a'..'z' | '0'..'9' | "_" | "-" | "."))+ }
include = { "#" ~ "include" ~ "\"" ~ filepath ~ "\"" } include = { "#" ~ "include" ~ "\"" ~ filepath ~ "\"" }
include_global = { "#" ~ "include" ~ "<" ~ filepath ~ ">" } include_global = { "#" ~ "include" ~ "<" ~ filepath ~ ">" }
round = { "(" ~ (expr)* ~ ")" } round = { "(" ~ ((expr ~ comma)* ~ expr?) ~ ")" }
curly = { "{" ~ (code_expr)* ~ "}" } curly = { "{" ~ (code_expr)* ~ "}" }
escape = { "\\" ~ ANY } escape = { "\\" ~ ANY }
raw_string = { (!("\\" | "\"") ~ ANY)+ } raw_string = { (!("\\" | "\"") ~ ANY)+ }
string = { "\"" ~ (raw_string | escape )* ~ "\"" } string = { "\"" ~ (raw_string | escape )* ~ "\"" }
char = { "'" ~ (escape | ANY) ~ "'" } char = { "'" ~ (escape | ANY) ~ "'" }
bool = @{"true" | "false"} bool = @{"true" | "false"}
semicolon = {";"}
// [numbers] // [numbers]
hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*} hex = @{ "0" ~ ("x"|"X") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')*}
@@ -20,14 +22,18 @@ float = @{ ('0'..'9')* ~ "." ~ ('0'..'9')+ }
int = @{ '0'..'9'+ } int = @{ '0'..'9'+ }
// [identifiers] // [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] // [definitions]
var_def = { identifier ~ identifier } round_def = { "(" ~ ((var_def ~ comma)* ~ var_def?) ~ ")" }
var_def_set = { var_def ~ "=" ~ expr ~ semicolon } var_def = { def_identifier ~ identifier }
func_def = { identifier ~ identifier ~ round ~ curly } var_def_set = { var_def ~ "=" ~ expr }
var_set = { def_identifier ~ "=" ~ expr }
func_def = { def_identifier ~ identifier ~ round_def ~ curly }
expr = { expr = {
(identifier ~ round) |
round | round |
curly | curly |
char | char |
@@ -40,14 +46,16 @@ expr = {
} }
code_expr = { code_expr = {
var_def_set | (var_def_set ~ semicolon) |
(var_def ~ semicolon) (var_def ~ semicolon) |
(var_set ~ semicolon) |
(expr ~ semicolon)
} }
top_expr = { top_expr = {
( (
func_def |
include | include |
include_global include_global |
func_def
)+ )+
} }