diff --git a/README.md b/README.md
index 89fe6c2..d2fc3bc 100644
--- a/README.md
+++ b/README.md
@@ -7,5 +7,8 @@
Wyst is a programing language that has similar syntax to C and transpiles to Rust
+# Re Write
+We are re-writing the parser and transpiler due to the messy code that is very hard to expand
+
# Alpha
We are on pure alpha. if you would like to contribute please open a new issue.
diff --git a/src/lexer.rs b/src/lexer.rs
index 8f98af3..76df225 100644
--- a/src/lexer.rs
+++ b/src/lexer.rs
@@ -85,7 +85,8 @@ const SYNTAX: [Node; 17] = [
Node {
token_type: TokenType::Keyword,
token_regex: Lazy::new(|| {
- Regex::new(r"^(pub|mut|try|catch|return|fn|let|use|cb|struct|impl|in|as)\b").unwrap()
+ Regex::new(r"^(pub|mut|try|catch|return|fn|let|use|cb|enum|struct|impl|in|as)\b")
+ .unwrap()
}),
},
Node {
diff --git a/src/main.rs b/src/main.rs
index 494d6d3..a7b7897 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,120 +1,255 @@
-mod compile;
-mod dllmgr;
-mod file_writer;
-mod lexer;
-mod lsp;
-mod lspcom;
-mod parser;
-mod transpiler;
-mod variable;
-use clap::Parser;
-use std::{fs, path::Path};
-use transpiler::Transpiler;
-use variable::{Variable, VariableType, Variables};
-
-use crate::lsp::run_lsp_server;
-
-// Arguments for Wyst (short and long version)
-#[derive(Parser)]
-struct Args {
- //#[clap(short, long)]
- //rust: Option,
- #[clap(short, long)]
- compile: Option,
-
- #[clap(short, long)]
- dll: Option,
-
- #[clap(long)]
- stdio: bool,
+#[derive(Debug, PartialEq, Clone)]
+enum Token {
+ Plus,
+ Minus,
+ Star,
+ Slash,
+ Equals,
+ Semicolon,
+ LParen,
+ RParen,
+ Identifier(String),
+ Number(i64),
+ EOF,
}
-fn main() {
- let args = Args::parse();
- match args.stdio {
- true => {
- run_lsp_server();
- }
- false => {
- match args.compile {
- Some(ref exe_name) => {
- let file_content = fs::read_to_string("main.wt").expect("Error reading file");
- if Path::new("build").exists() {
- fs::remove_dir_all("build").expect("err rm build");
- }
- fs::create_dir("build").expect("error making build");
- let mut trsp = Transpiler::default();
- let mut vars = Variables::new();
- let mut transpiled_code = trsp.transpile(file_content, 0, &mut vars);
- transpiled_code += "\nfn main() {";
- transpiled_code += "std::process::exit(";
- transpiled_code += vars.get_var("main".to_string(), &mut trsp).as_str();
- transpiled_code += "())}";
- for problem in &trsp.problems {
- println!("{:?}: {}", problem.problem_type, problem.problem_msg)
- }
- if trsp.problems.len() > 0 {
- return;
- }
- trsp.writer.write();
+fn tokenize(input: &str) -> Vec {
+ let mut tokens = Vec::new();
+ let chars: Vec = input.chars().collect();
+ let mut i = 0;
- compile::write_to_rust_file(&transpiled_code, "build/main.rs")
- .expect("Error writing to temporary Rust file");
- std::env::set_current_dir("build").expect("setDir err: ");
- compile::compile_to_executable(exe_name)
- .expect("Error compiling to executable");
- std::env::set_current_dir("..").expect("setDir0 err: ");
- fs::rename(Path::new("build").join(exe_name).as_path(), exe_name)
- .expect("RenameErrBuld: ");
- fs::remove_dir_all("build").expect("err rm build");
- }
- None => {}
+ while i < chars.len() {
+ match chars[i] {
+ ' ' | '\t' | '\n' | '\r' => i += 1,
+ '+' => {
+ tokens.push(Token::Plus);
+ i += 1;
}
- match args.dll {
- Some(ref dll_path) => {
- let file_content = fs::read_to_string("lib.wt").expect("Error reading file");
- if Path::new("build").exists() {
- fs::remove_dir_all("build").expect("err rm build");
- }
- fs::create_dir("build").expect("error making build");
- let mut trsp = Transpiler::default();
- let mut vars = Variables::new();
- let transpiled_code = trsp.transpile(file_content, 0, &mut vars);
- for problem in trsp.problems {
- println!("{}", problem.problem_msg)
- }
- trsp.writer.write();
- let mut dll_main = String::from(
- "mod wslib;use wslib::*;\nfn call_fn(fn_name: &str, params: Vec)->i32{match fn_name {",
- );
- for (name, var) in vars.vars.clone() {
- if var.vtype != VariableType::Func {
- continue;
- }
- let mut dparams = String::new();
- println!("{:?}", var.params.vars);
- for i in 0..var.params.vars.len() {
- dparams += format!("params.get({}).expect(\"Err_prms\"),", i).as_str();
- }
- dll_main += format!(
- "\"{}\" => {}return {}({dparams});{}",
- name, "{", var.rname, "}"
- )
- .as_str();
- }
- dll_main += "}}\nfn main(){}";
- //dll_main = "fn main(){}".to_string();
- compile::write_to_rust_file(&transpiled_code, "build/wslib.rs")
- .expect("Error writing to temporary Rust file");
- compile::write_to_rust_file(&dll_main, "build/main.rs")
- .expect("Error writing to main dll");
- std::env::set_current_dir("build").expect("setDir err: ");
- compile::compile_to_executable("run").expect("Error compiling to executable");
- dllmgr::write_dll(vars, "run".to_string(), dll_path.to_string());
- // fs::remove_dir_all("build").expect("err rm build");
+ '-' => {
+ tokens.push(Token::Minus);
+ i += 1;
+ }
+ '*' => {
+ tokens.push(Token::Star);
+ i += 1;
+ }
+ '/' => {
+ tokens.push(Token::Slash);
+ i += 1;
+ }
+ '=' => {
+ tokens.push(Token::Equals);
+ i += 1;
+ }
+ ';' => {
+ tokens.push(Token::Semicolon);
+ i += 1;
+ }
+ '(' => {
+ tokens.push(Token::LParen);
+ i += 1;
+ }
+ ')' => {
+ tokens.push(Token::RParen);
+ i += 1;
+ }
+ '0'..='9' => {
+ let mut num = 0;
+ while i < chars.len() && chars[i].is_digit(10) {
+ num = num * 10 + chars[i].to_digit(10).unwrap() as i64;
+ i += 1;
}
- None => {}
+ tokens.push(Token::Number(num));
+ }
+ 'a'..='z' | 'A'..='Z' => {
+ let mut id = String::new();
+ while i < chars.len() && (chars[i].is_alphanumeric() || chars[i] == '_') {
+ id.push(chars[i]);
+ i += 1;
+ }
+ match id.as_str() {
+ _ => tokens.push(Token::Identifier(id)),
+ }
+ }
+ _ => panic!("Unexpected character: {}", chars[i]),
+ }
+ }
+
+ tokens.push(Token::EOF);
+ tokens
+}
+
+#[derive(Debug)]
+enum ASTNode {
+ Number(i64),
+ Identifier(String),
+ BinaryOp(Box, Token, Box),
+ Assignment(String, Box),
+ Print(Box),
+ Let(String, Box),
+ Sequence(Vec),
+}
+
+struct Parser {
+ tokens: Vec,
+ current_token: Token,
+ pos: usize,
+}
+
+impl Parser {
+ fn new(tokens: Vec) -> Self {
+ Self {
+ tokens: tokens.clone(),
+ current_token: tokens[0].clone(),
+ pos: 0,
+ }
+ }
+
+ fn eat(&mut self, token: Token) {
+ if self.current_token == token {
+ self.pos += 1;
+ self.current_token = self.tokens[self.pos].clone();
+ } else {
+ panic!("Unexpected token: {:?}", self.current_token);
+ }
+ }
+
+ fn factor(&mut self) -> ASTNode {
+ match self.current_token.clone() {
+ Token::Number(value) => {
+ self.eat(Token::Number(value));
+ ASTNode::Number(value)
+ }
+ Token::Identifier(name) => {
+ self.eat(Token::Identifier(name.clone()));
+ ASTNode::Identifier(name)
+ }
+ Token::LParen => {
+ self.eat(Token::LParen);
+ let expr = self.expression();
+ self.eat(Token::RParen);
+ expr
+ }
+ _ => panic!("Unexpected token: {:?}", self.current_token),
+ }
+ }
+
+ fn term(&mut self) -> ASTNode {
+ let mut node = self.factor();
+
+ while self.current_token == Token::Star || self.current_token == Token::Slash {
+ let token = self.current_token.clone();
+ self.eat(token.clone());
+ node = ASTNode::BinaryOp(Box::new(node), token, Box::new(self.factor()));
+ }
+
+ node
+ }
+
+ fn expression(&mut self) -> ASTNode {
+ let mut node = self.term();
+
+ while self.current_token == Token::Plus || self.current_token == Token::Minus {
+ let token = self.current_token.clone();
+ self.eat(token.clone());
+ node = ASTNode::BinaryOp(Box::new(node), token, Box::new(self.term()));
+ }
+
+ node
+ }
+
+ fn statement(&mut self) -> ASTNode {
+ match self.current_token.clone() {
+ Token::Identifier(name) => {
+ self.eat(Token::Identifier(name.clone()));
+ self.eat(Token::Equals);
+ let expr = self.expression();
+ self.eat(Token::Semicolon);
+ ASTNode::Assignment(name, Box::new(expr))
+ }
+ _ => panic!("Unexpected token: {:?}", self.current_token),
+ }
+ }
+
+ fn parse(&mut self) -> ASTNode {
+ let mut statements = Vec::new();
+
+ while self.current_token != Token::EOF {
+ statements.push(self.statement());
+ }
+
+ ASTNode::Sequence(statements)
+ }
+}
+
+use std::collections::HashMap;
+
+struct Interpreter {
+ symbol_table: HashMap,
+}
+
+impl Interpreter {
+ fn new() -> Self {
+ Self {
+ symbol_table: HashMap::new(),
+ }
+ }
+
+ fn evaluate(&mut self, node: &ASTNode) -> i64 {
+ match node {
+ ASTNode::Number(value) => *value,
+ ASTNode::Identifier(name) => *self.symbol_table.get(name).expect("Undefined variable"),
+ ASTNode::BinaryOp(left, token, right) => {
+ let left_val = self.evaluate(left);
+ let right_val = self.evaluate(right);
+ match token {
+ Token::Plus => left_val + right_val,
+ Token::Minus => left_val - right_val,
+ Token::Star => left_val * right_val,
+ Token::Slash => left_val / right_val,
+ _ => panic!("Unexpected binary operator"),
+ }
+ }
+ ASTNode::Assignment(name, expr) => {
+ let value = self.evaluate(expr);
+ self.symbol_table.insert(name.clone(), value);
+ value
+ }
+ ASTNode::Let(name, expr) => {
+ let value = self.evaluate(expr);
+ self.symbol_table.insert(name.clone(), value);
+ value
+ }
+ ASTNode::Print(expr) => {
+ let value = self.evaluate(expr);
+ println!("{}", value);
+ value
+ }
+ ASTNode::Sequence(statements) => {
+ for statement in statements {
+ self.evaluate(statement);
+ }
+ 0
}
}
}
}
+
+fn main() {
+ let input = "
+ let x = 5;
+ let y = x + 3;
+ print y;
+ x = y * 2;
+ print x;
+ ";
+ let tokens = tokenize(input);
+ println!("Tokens: {:?}", tokens);
+
+ let mut parser = Parser::new(tokens);
+ let ast = parser.parse();
+ println!("AST: {:?}", ast);
+
+ let mut interpreter = Interpreter::new();
+ interpreter.evaluate(&ast);
+}
diff --git a/src/parser.rs b/src/parser.rs
index 2ab67dc..6583f59 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -26,6 +26,7 @@ pub enum AstType {
Json,
Impl,
StaticExecution,
+ EnumDeceleration,
Other,
}
@@ -119,6 +120,27 @@ impl Parser {
ast_res.tokens.push(self.tokens[index + 1].clone());
ast_res.ast_type = AstType::Ref;
self.index += 1;
+ } else if self.tokens.len() - index > 2
+ && self.tokens[index].value == "enum"
+ && self.tokens[index + 1].token_type == TokenType::Identifier
+ && self.tokens[index + 2].token_type == TokenType::Curly
+ {
+ ast_res.tokens.push(self.tokens[index + 1].clone());
+ ast_res.tokens.push(self.tokens[index + 2].clone());
+ ast_res.ast_type = AstType::EnumDeceleration;
+ self.index += 2;
+ let mut desc = String::new();
+ if index > 0 && self.tokens[index - 1].token_type == TokenType::Comment {
+ desc = self.tokens[index - 1].value.clone()
+ }
+ self.variables.new_enum(
+ self.tokens[index + 1].clone().value,
+ LexerState {
+ line: self.tokens[index + 1].clone().line,
+ column: self.tokens[index + 1].clone().column,
+ },
+ desc,
+ );
} else if self.tokens.len() - index > 2
&& self.tokens[index].value == "struct"
&& self.tokens[index + 1].token_type == TokenType::Identifier
diff --git a/src/transpiler.rs b/src/transpiler.rs
index 190ae76..f794f88 100644
--- a/src/transpiler.rs
+++ b/src/transpiler.rs
@@ -149,6 +149,37 @@ impl Transpiler {
)
)
.as_str();
+ } else if ast.ast_type == AstType::StructDeceleration {
+ if self.auto_pub {
+ result += "pub ";
+ }
+ let mut vars: Variables = variables.clone();
+ let round = self.transpile_round(ast.tokens[1].value.clone(), &mut vars);
+ result += format!(
+ "enum {} {} {}",
+ ast.tokens[0].value,
+ "{\n",
+ round.trim_end()
+ )
+ .replace(
+ "\n",
+ ("\n".to_string() + " ".repeat(((indent + 1) as usize) * 2).as_str())
+ .as_str(),
+ )
+ .as_str();
+ result += "\n}\n";
+ let vvars = variables.clone();
+ if let Some(v) = variables.get_mut(ast.tokens[0].value.clone()) {
+ for (name, var) in vars.iter_mut() {
+ if !(vvars.vars.contains_key(name)) {
+ v.params.new_var(
+ name.to_string(),
+ LexerState { line: 0, column: 0 },
+ var.desc.clone(),
+ );
+ }
+ }
+ }
} else if ast.ast_type == AstType::StructDeceleration {
if self.auto_pub {
result += "pub ";
diff --git a/src/variable.rs b/src/variable.rs
index 127d4e4..e48a660 100644
--- a/src/variable.rs
+++ b/src/variable.rs
@@ -16,6 +16,7 @@ pub enum VariableType {
Keyword,
Struct,
Namespace,
+ Enum,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -93,6 +94,20 @@ impl Variables {
},
);
}
+ pub fn new_enum(&mut self, name: String, state: LexerState, desc: String) {
+ self.vars.insert(
+ name,
+ Variable {
+ vtype: VariableType::Enum,
+ desc,
+ state,
+ params: Variables {
+ vars: HashMap::new(),
+ },
+ rname: generate_varname(),
+ },
+ );
+ }
// pub fn new_keyword(&mut self, name: String, state: LexerState, desc: String) {
// self.vars.insert(