added argument flags

This commit is contained in:
Sven Vogel 2022-11-28 19:10:29 +01:00
parent d3f121640a
commit fda09066c7
7 changed files with 366 additions and 200 deletions

34
src/conf/mod.rs Normal file
View File

@ -0,0 +1,34 @@
use crate::parser::data::Diagnostics;
pub struct Settings {
gen_erpn: bool
}
impl Settings {
fn new() -> Self {
Settings {
gen_erpn: false
}
}
pub fn gen_erpn(&self) -> bool {
self.gen_erpn
}
}
pub fn parse_args(diagnostics: &mut Diagnostics) -> Settings {
let args = std::env::args().collect::<Vec<String>>();
let mut settings = Settings::new();
for arg in args.iter() {
match arg.as_str() {
"--no-info" => diagnostics.set_loglvl(crate::parser::data::LogLvl::Warn),
"--no-warn" => diagnostics.set_loglvl(crate::parser::data::LogLvl::Err),
"--erpn" => settings.gen_erpn = true,
_ => ()
}
}
settings
}

View File

@ -5,11 +5,14 @@ mod parser;
// translate a tree of functions and expressions to pseudo assembly // translate a tree of functions and expressions to pseudo assembly
// designed for a virtual stack machiene // designed for a virtual stack machiene
mod inter; mod inter;
mod conf;
use colored::Colorize; use colored::Colorize;
use parser::*; use parser::*;
use token::*; use token::*;
use crate::parser::data::Diagnostics;
pub fn message<S>(typ: MessageType, msg: S) pub fn message<S>(typ: MessageType, msg: S)
where where
S: Into<String>, S: Into<String>,
@ -19,7 +22,7 @@ where
fn main() { fn main() {
let source = r" let source = r"
# this is pi # surely this is pi
pi = rat 5.1415926535 pi = rat 5.1415926535
foo(x:int, y:rat) = bool { foo(x:int, y:rat) = bool {
@ -38,19 +41,26 @@ foo(x:int, y:rat) = bool {
} }
-- comment -- comment
yield false yield true
} }
main() = int { main() = int {
a = 4 a = 4
b = 5.5 b = 5.5
c = true c = true
r = foo(3, 3.4) r = foo(3, ffalsee)
0 0
} }
"; ";
let diagnostics = parse(&mut tokenize(source), source); let mut diagnostics = Diagnostics::new(source);
let settings = conf::parse_args(&mut diagnostics);
if let Ok(mut tokens) = tokenize(source, &mut diagnostics) {
parse(&mut tokens, &mut diagnostics, &settings);
}
println!("{}", diagnostics); println!("{}", diagnostics);
} }

View File

@ -1,8 +1,18 @@
use crate::token::{DebugInfo, DebugNotice, Token}; use crate::token::{DebugInfo, DebugNotice, Token, MessageType};
use crate::Prim; use crate::Prim;
use core::panic; use core::panic;
use std::collections::VecDeque; use std::collections::VecDeque;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum LogLvl {
/// print everything
Info,
/// print only errors and warning
Warn,
/// print only errors
Err,
}
pub struct Diagnostics<'a> { pub struct Diagnostics<'a> {
/// terminating factor on error /// terminating factor on error
err: Option<DebugNotice<'a>>, err: Option<DebugNotice<'a>>,
@ -11,6 +21,8 @@ pub struct Diagnostics<'a> {
hints: Vec<DebugNotice<'a>>, hints: Vec<DebugNotice<'a>>,
/// source string /// source string
source: &'a str, source: &'a str,
/// flags
loglvl: LogLvl,
} }
impl<'a> Diagnostics<'a> { impl<'a> Diagnostics<'a> {
@ -19,9 +31,14 @@ impl<'a> Diagnostics<'a> {
err: None, err: None,
hints: vec![], hints: vec![],
source, source,
loglvl: LogLvl::Info
} }
} }
pub fn set_loglvl(&mut self, lvl: LogLvl) {
self.loglvl = lvl;
}
pub fn set_err<T, S>(&mut self, source: &S, message: &'static crate::token::DebugMsg, ext: T) pub fn set_err<T, S>(&mut self, source: &S, message: &'static crate::token::DebugMsg, ext: T)
where where
T: Into<String>, T: Into<String>,
@ -60,6 +77,16 @@ impl<'a> Diagnostics<'a> {
impl<'a> std::fmt::Display for Diagnostics<'a> { impl<'a> std::fmt::Display for Diagnostics<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for hint in self.hints.iter() { for hint in self.hints.iter() {
match hint.msg.typ {
MessageType::Info => if self.loglvl != LogLvl::Info {
continue;
},
MessageType::Warning => if self.loglvl == LogLvl::Err {
continue;
},
_ => (),
}
f.write_fmt(format_args!("{}\n\n", hint)).unwrap(); f.write_fmt(format_args!("{}\n\n", hint)).unwrap();
} }
@ -98,6 +125,9 @@ pub struct Declr<'a> {
pub results: bool, pub results: bool,
/// type of result /// type of result
pub result_typ: Option<Prim>, pub result_typ: Option<Prim>,
/// debug info
pub info: Option<DebugInfo>
} }
impl<'a> Declr<'a> { impl<'a> Declr<'a> {
@ -107,6 +137,7 @@ impl<'a> Declr<'a> {
args: None, args: None,
results: false, results: false,
result_typ: None, result_typ: None,
info: None,
} }
} }
} }
@ -134,6 +165,10 @@ impl<'a> std::fmt::Display for Declr<'a> {
f.write_str(" =")?; f.write_str(" =")?;
} }
if let Some(typ) = self.result_typ {
f.write_fmt(format_args!(" {:?}", typ))?;
}
f.write_str(" {}") f.write_str(" {}")
} }
} }

View File

@ -1,4 +1,4 @@
use crate::token::{Assoc, DebugInfo, Keyword, Operator, Prim, Token}; use crate::{token::{Assoc, DebugInfo, Keyword, Operator, Prim, Token}, conf::Settings};
use core::panic; use core::panic;
use std::{collections::VecDeque, vec}; use std::{collections::VecDeque, vec};
@ -12,6 +12,7 @@ fn discover_functions<'a>(
tokens: &mut VecDeque<crate::Token<'a>>, tokens: &mut VecDeque<crate::Token<'a>>,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) -> Result<(Vec<Func<'a>>, Vec<Declr<'a>>), ()> { ) -> Result<(Vec<Func<'a>>, Vec<Declr<'a>>), ()> {
let mut funcs = Vec::new(); let mut funcs = Vec::new();
let mut declrs = Vec::new(); let mut declrs = Vec::new();
@ -27,6 +28,7 @@ fn discover_functions<'a>(
macro_rules! finish_func { macro_rules! finish_func {
($token:expr) => { ($token:expr) => {
// check if the function is already declared
if declrs.contains(&declr) { if declrs.contains(&declr) {
diagnostics.set_err( diagnostics.set_err(
$token, $token,
@ -36,13 +38,17 @@ fn discover_functions<'a>(
return Err(()); return Err(());
} }
// check if the function returns sth but no return value is given
if declr.results && declr.result_typ.is_none() { if declr.results && declr.result_typ.is_none() {
diagnostics.set_err($token, crate::msg::ERR11, format!("for function {declr}")); diagnostics.set_err($token, crate::msg::ERR11, format!("for function {declr}"));
return Err(()); return Err(());
} }
// store new function and its declaration
funcs.push(func); funcs.push(func);
declrs.push(declr); declrs.push(declr);
// create new empty function
declr = Declr::new(); declr = Declr::new();
func = Func::new(); func = Func::new();
single_line = false; single_line = false;
@ -53,22 +59,25 @@ fn discover_functions<'a>(
// function body detection // function body detection
// has highest priority // has highest priority
match &top { match &top {
Token::Delemiter(char, dbginf) => match char { Token::Delemiter(char, _) => match char {
// open body
'{' => { '{' => {
brace_cnt += 1; brace_cnt += 1;
// we have an found open function body // we have an found open function body
if brace_cnt == 1 { if brace_cnt == 1 {
// check if we have a name for our function
if declr.name.is_none() { if declr.name.is_none() {
diagnostics.set_err(&top, crate::msg::ERR12, ""); diagnostics.set_err(&top, crate::msg::ERR12, "");
return Err(()); return Err(());
} }
// check if the parameter list was closed
if paren_cnt > 0 { if paren_cnt > 0 {
diagnostics.set_err(&top, crate::msg::ERR13, ""); diagnostics.set_err(&top, crate::msg::ERR13, "");
return Err(()); return Err(());
} }
single_line = false; single_line = false;
func.raw = Some(VecDeque::new()); func.raw = Some(VecDeque::new());
continue; continue;
@ -92,8 +101,10 @@ fn discover_functions<'a>(
_ => (), _ => (),
}, },
Token::Type(typ, dbginf) => { Token::Type(typ, _) => {
// check if we already have a result type
if declr.result_typ.is_none() { if declr.result_typ.is_none() {
// then check if we even need to return sth.
if declr.results { if declr.results {
declr.result_typ = Some(*typ); declr.result_typ = Some(*typ);
continue; continue;
@ -101,10 +112,13 @@ fn discover_functions<'a>(
diagnostics.set_err(&top, crate::msg::ERR16, ""); diagnostics.set_err(&top, crate::msg::ERR16, "");
return Err(()); return Err(());
} }
} else {
diagnostics.set_err(&top, crate::msg::ERR24, "");
return Err(());
} }
} }
Token::LineBreak(dbginf) => { Token::LineBreak(_) => {
if single_line { if single_line {
finish_func!(&top); finish_func!(&top);
continue; continue;
@ -120,12 +134,15 @@ fn discover_functions<'a>(
if func.raw.is_none() { if func.raw.is_none() {
match &top { match &top {
Token::Operator(op, dbginf) => match op { Token::Operator(op, _) => match op {
Operator::Assign => { Operator::Assign => {
// check if we already have an assign
if declr.results { if declr.results {
diagnostics.set_err(&top, crate::msg::ERR17, ""); diagnostics.set_err(&top, crate::msg::ERR17, "");
return Err(()); return Err(());
} }
// check if we even have a function name
// which must always be first
if declr.name.is_none() { if declr.name.is_none() {
diagnostics.set_err(&top, crate::msg::ERR12, ""); diagnostics.set_err(&top, crate::msg::ERR12, "");
return Err(()); return Err(());
@ -138,26 +155,38 @@ fn discover_functions<'a>(
_ => (), _ => (),
}, },
Token::Word(text, dbginf) => { Token::Word(text, info) => {
// check if we have a function name
if declr.name.is_some() { if declr.name.is_some() {
// we have a function name check if we have no open argument list.
// if so this word is missplaced
if declr.args.is_none() { if declr.args.is_none() {
diagnostics.set_err(&top, crate::msg::ERR18, ""); diagnostics.set_err(&top, crate::msg::ERR18, "");
return Err(()); return Err(());
} }
// function body is open and we have no function name
} else if brace_cnt > 0 { } else if brace_cnt > 0 {
diagnostics.set_err(&top, crate::msg::ERR13, ""); diagnostics.set_err(&top, crate::msg::ERR13, "");
return Err(()); return Err(());
// this must be a valid function name
} else { } else {
declr.name = Some(text); declr.name = Some(text);
declr.info = Some(info.to_owned());
continue; continue;
} }
} }
Token::Assign(name, _, dbginf) => { Token::Assign(name, _, info) => {
// check if we already marked a return type
// we dont want a double assignment
if declr.results { if declr.results {
diagnostics.set_err(&top, crate::msg::ERR17, ""); diagnostics.set_err(&top, crate::msg::ERR17, "");
return Err(()); return Err(());
} }
// check if we already set function name
// then we dont want to reassign
if declr.name.is_some() { if declr.name.is_some() {
diagnostics.set_err(&top, crate::msg::ERR18, ""); diagnostics.set_err(&top, crate::msg::ERR18, "");
return Err(()); return Err(());
@ -165,16 +194,22 @@ fn discover_functions<'a>(
func.raw = Some(VecDeque::new()); func.raw = Some(VecDeque::new());
declr.name = Some(name); declr.name = Some(name);
declr.info = Some(info.to_owned());
declr.results = true; declr.results = true;
single_line = true; single_line = true;
continue; continue;
} }
Token::Delemiter(char, dbginf) => match char { Token::Delemiter(char, _) => match char {
'(' => { '(' => {
// check for no existing function body
// if we have none we can open an parameter list
if func.raw.is_none() { if func.raw.is_none() {
paren_cnt += 1; paren_cnt += 1;
// check if we have one open parenthsis
if paren_cnt == 1 { if paren_cnt == 1 {
// we have some arguments then we have a double parameter list
// dont want that
if declr.args.is_some() { if declr.args.is_some() {
diagnostics.set_err(&top, crate::msg::ERR19, ""); diagnostics.set_err(&top, crate::msg::ERR19, "");
return Err(()); return Err(());
@ -198,9 +233,14 @@ fn discover_functions<'a>(
} }
if let Some(body) = &mut func.raw { if let Some(body) = &mut func.raw {
// if we have an open function body
// drop all token in there till it closes
body.push_back(top); body.push_back(top);
continue; continue;
// check for open parameter list
} else if let Some(args) = &mut declr.args { } else if let Some(args) = &mut declr.args {
// the parameter list is closed
if paren_cnt == 0 { if paren_cnt == 0 {
diagnostics.set_err(&top, crate::msg::ERR20, ""); diagnostics.set_err(&top, crate::msg::ERR20, "");
return Err(()); return Err(());
@ -208,7 +248,9 @@ fn discover_functions<'a>(
match &top { match &top {
Token::Decl(name, typ, _dbginf) => args.push((name, *typ)), Token::Decl(name, typ, _dbginf) => args.push((name, *typ)),
Token::Word(_, dbginf) => {
// as parameter we only accept declarations
Token::Word(_, _) => {
diagnostics.set_err(&top, crate::msg::ERR21, ""); diagnostics.set_err(&top, crate::msg::ERR21, "");
return Err(()); return Err(());
} }
@ -231,6 +273,7 @@ fn discover_functions<'a>(
} }
if let Some(raw) = func.raw { if let Some(raw) = func.raw {
// still some raw unused tokens left over
if let Some(front) = raw.front() { if let Some(front) = raw.front() {
diagnostics.set_err(front, crate::msg::ERR15, ""); diagnostics.set_err(front, crate::msg::ERR15, "");
return Err(()); return Err(());
@ -247,7 +290,8 @@ fn discover_exprs<'a>(
functions: &mut Vec<Func<'a>>, functions: &mut Vec<Func<'a>>,
_: &Vec<Declr<'a>>, _: &Vec<Declr<'a>>,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) { ) -> Result<(),()> {
for func in functions.iter_mut() { for func in functions.iter_mut() {
let mut blocks = vec![Block::new()]; let mut blocks = vec![Block::new()];
@ -255,27 +299,27 @@ fn discover_exprs<'a>(
while let Some(top) = func.raw.as_mut().unwrap().pop_front() { while let Some(top) = func.raw.as_mut().unwrap().pop_front() {
match &top { match &top {
Token::LineBreak(dbginf) | Token::Terminator(dbginf) => { Token::LineBreak(_) | Token::Terminator(_) => {
if !expr.is_empty() { if !expr.is_empty() {
if let Some(blocks) = blocks.last_mut() { if let Some(blocks) = blocks.last_mut() {
blocks.push_back(Expr::Term(expr)) blocks.push_back(Expr::Term(expr))
} else { } else {
diagnostics.set_err(&top, crate::msg::ERR41, ""); diagnostics.set_err(&top, crate::msg::ERR41, "");
return; return Err(());
} }
expr = VecDeque::new(); expr = VecDeque::new();
continue; continue;
} }
} }
Token::Delemiter(char, dbginf) => match char { Token::Delemiter(char, _) => match char {
'{' => { '{' => {
blocks
.last_mut() if let Some(block) = blocks.last_mut() {
.unwrap_or_else(|| { block.push_back(Expr::Term(expr));
diagnostics.set_err(&top, crate::msg::ERR41, ""); } else {
panic!() diagnostics.set_err(&top, crate::msg::ERR41, "");
}) return Err(());
.push_back(Expr::Term(expr)); }
expr = VecDeque::new(); expr = VecDeque::new();
blocks.push(Block::new()); blocks.push(Block::new());
continue; continue;
@ -283,17 +327,22 @@ fn discover_exprs<'a>(
'}' => { '}' => {
// pop topmost block of the stack, storing it in the next lower block // pop topmost block of the stack, storing it in the next lower block
if let Some(block) = blocks.pop() { if let Some(block) = blocks.pop() {
blocks if let Some(dst) = blocks.last_mut() {
.last_mut() dst.push_back(Expr::Block(block));
.unwrap_or_else(|| { } else {
//println!("{}", dbginf.make_msg(crate::msg::ERR41)); diagnostics.set_err(&top, crate::msg::ERR41, "");
panic!() return Err(());
}) }
.push_back(Expr::Block(block));
} else { } else {
//println!("{}", dbginf.make_msg(crate::msg::ERR40)); diagnostics.set_err(&top, crate::msg::ERR40, "");
panic!() return Err(());
} }
if blocks.is_empty() {
diagnostics.set_err(&top, crate::msg::ERR41, "");
return Err(());
}
continue; continue;
} }
_ => (), _ => (),
@ -305,21 +354,19 @@ fn discover_exprs<'a>(
} }
if !expr.is_empty() { if !expr.is_empty() {
blocks if let Some(block) = blocks.last_mut() {
.last_mut() block.push_back(Expr::Term(expr));
.unwrap_or_else(|| { } else {
diagnostics.set_err(expr.back().unwrap(), crate::msg::ERR40, ""); diagnostics.set_err(expr.back().unwrap(), crate::msg::ERR40, "");
panic!() return Err(());
}) }
.push_back(Expr::Term(expr));
} }
if let Some(block) = blocks.pop() { if let Some(block) = blocks.pop() {
func.expr = Some(Expr::Block(block)); func.expr = Some(Expr::Block(block));
} else {
panic!("curly brace missmatch")
} }
} }
Ok(())
} }
fn check_var_typ( fn check_var_typ(
@ -328,7 +375,7 @@ fn check_var_typ(
info: &crate::token::DebugInfo, info: &crate::token::DebugInfo,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) -> Result<(), ()> { ) -> Result<(), ()> {
if let Some(value) = operands.pop() { if let Some(mut value) = operands.pop() {
if !operands.is_empty() { if !operands.is_empty() {
diagnostics.set_err(info, crate::msg::ERR50, ""); diagnostics.set_err(info, crate::msg::ERR50, "");
return Err(()); return Err(());
@ -345,6 +392,17 @@ fn check_var_typ(
} }
} else { } else {
diagnostics.hint(info, crate::msg::INF51, format!("gessed type: {:?}", value)); diagnostics.hint(info, crate::msg::INF51, format!("gessed type: {:?}", value));
// resolve to concrete typ
// i.e all Prim::Num(hint) will convert to their hints.
value = match value {
Prim::Num(hint) => match hint {
crate::token::NumHint::Int => Prim::Int,
crate::token::NumHint::Rat => Prim::Rat,
}
_ => value
};
*typ = Some(value); *typ = Some(value);
} }
} else { } else {
@ -362,7 +420,7 @@ fn process_keyword(
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) -> Result<(), ()> { ) -> Result<(), ()> {
match keyword { match keyword {
Keyword::If | Keyword::While => { Keyword::Unless | Keyword::While => {
if operands.len() != 1 { if operands.len() != 1 {
diagnostics.set_err( diagnostics.set_err(
info, info,
@ -431,70 +489,78 @@ fn collapse_operation(
operands: &mut Vec<Prim>, operands: &mut Vec<Prim>,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) -> Result<(), ()> { ) -> Result<(), ()> {
match operation { match operation {
Token::Operator(op, dbginf) => op.operate(operands, &dbginf, diagnostics), Token::Operator(op, dbginf) => op.operate(operands, &dbginf, diagnostics)?,
Token::Assign(name, mut typ, dbginf) => { Token::Assign(name, ref mut typ, dbginf) => {
check_var_typ(&mut typ, operands, &dbginf, diagnostics)?; check_var_typ(typ, operands, &dbginf, diagnostics)?;
scope.decl_var((*name).to_owned(), typ); scope.decl_var((*name).to_owned(), typ.clone());
} }
Token::Func(name, dbginf) => call_func(name, declrs, scope, operands, &dbginf, diagnostics), Token::Func(name, dbginf) => {
call_func(name, declrs, operands, &dbginf, diagnostics)?;
},
Token::Keyword(keyword, dbginf) => { Token::Keyword(keyword, dbginf) => {
process_keyword(dbginf, *keyword, scope, operands, diagnostics)? process_keyword(dbginf, *keyword, scope, operands, diagnostics)?;
} }
_ => (), _ => (),
} }
Ok(())
return Ok(());
} }
fn call_func( fn call_func(
name: &str, name: &str,
declrs: &Vec<Declr>, declrs: &Vec<Declr>,
_: &mut Scope,
operands: &mut Vec<Prim>, operands: &mut Vec<Prim>,
dbginf: &crate::token::DebugInfo, info: &DebugInfo,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) { ) -> Result<(), ()> {
// find the function in our function declarations by its name
for declr in declrs { for declr in declrs {
if declr.name.is_some() && declr.name.unwrap() == name { // check if declaration name matches the function name
if let Some(args) = &declr.args { if let Some(declr_name) = declr.name {
if args.len() > operands.len() { if declr_name != name {
/* continue;
println!(
"{}",
dbginf.make_msg_w_ext(
crate::msg::ERR60,
format!("expected {:?} got {:?}", args.len(), operands.len())
)
);*/
panic!()
}
for (x, arg) in args.iter().enumerate() {
let operand = operands.first().unwrap();
if !operand.is_equal(arg.1) {
/*
println!(
"{}",
dbginf.make_msg_w_ext(
crate::msg::ERR61,
format!("expected {:?} got {:?}", arg, operand)
)
);*/
panic!()
}
operands.remove(0);
}
} }
} else {
if let Some(typ) = declr.result_typ { // some critical compiler error
operands.push(typ); crate::message(crate::token::MessageType::Critical, "Missing function name in declaration");
} panic!();
break;
} }
if let Some(args) = &declr.args {
// check if we have enough parameter on the stack
// note that the stack may contain more than just the functions
// // parameters
if args.len() > operands.len() {
diagnostics.set_err(info, crate::msg::ERR60, format!("expected {:?} got {:?}", args.len(), operands.len()));
return Err(());
}
// check parameter types
for (x, arg) in args.iter().enumerate() {
// parameter are in reverse order on the stack
// so they are placed at the bottom
let operand = operands.first().unwrap();
// check types
if !operand.is_equal(arg.1) {
diagnostics.set_err(info, crate::msg::ERR61, format!("expected {:?} got {:?} as {}th argument", arg, operand, x));
return Err(());
}
operands.remove(0);
}
}
// if the function returns sth. we will add
// its type to the stack
// assuming the execution was successfull
if let Some(typ) = declr.result_typ {
operands.push(typ);
}
break;
} }
Ok(())
} }
/// parse a single term using a modified shunting yard /// parse a single term using a modified shunting yard
@ -503,28 +569,36 @@ fn parse_term<'a>(
declrs: &Vec<Declr<'a>>, declrs: &Vec<Declr<'a>>,
scope: &mut Scope, scope: &mut Scope,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) { ) -> Result<(),()> {
let mut op_stack = vec![]; let mut op_stack = vec![];
let mut output = VecDeque::with_capacity(term.len()); let mut output = VecDeque::with_capacity(term.len());
let mut value_stack = vec![]; let mut value_stack = vec![];
'outer: while let Some(token) = term.pop_front() { 'outer: while let Some(token) = term.pop_front() {
match &token { match &token {
// resolve word to either a function, parameter or variable
Token::Word(text, dbginf) => { Token::Word(text, dbginf) => {
// test for function
if is_func(declrs, text) { if is_func(declrs, text) {
op_stack.push(Token::Func(text, *dbginf)); op_stack.push(Token::Func(text, *dbginf));
continue; continue;
// test for function parameter
} else if scope.is_arg(text) { } else if scope.is_arg(text) {
value_stack.push(scope.get_arg_type(text)); value_stack.push(scope.get_arg_type(text));
output.push_back(Token::Arg(text, *dbginf)); output.push_back(Token::Arg(text, *dbginf));
continue; continue;
// test for variable in scope
} else if scope.is_var(text).is_some() { } else if scope.is_var(text).is_some() {
value_stack.push(scope.get_var_type(text)); value_stack.push(scope.get_var_type(text));
output.push_back(Token::Var(text, *dbginf)); output.push_back(Token::Var(text, *dbginf));
continue; continue;
} }
//println!("{}", dbginf.make_msg(crate::msg::ERR62)); // word was not reolved to anything
panic!() diagnostics.set_err(&token, crate::msg::ERR62, "");
return Err(());
} }
Token::Bool(_, _) => { Token::Bool(_, _) => {
output.push_back(token); output.push_back(token);
@ -539,7 +613,7 @@ fn parse_term<'a>(
} }
Token::Keyword(_, _) => op_stack.push(token), Token::Keyword(_, _) => op_stack.push(token),
Token::Delemiter(char, dbginf) => match char { Token::Delemiter(char, _) => match char {
'(' => op_stack.push(token), '(' => op_stack.push(token),
')' => { ')' => {
while let Some(mut token) = op_stack.pop() { while let Some(mut token) = op_stack.pop() {
@ -556,7 +630,7 @@ fn parse_term<'a>(
scope, scope,
&mut value_stack, &mut value_stack,
diagnostics, diagnostics,
); )?;
output.push_back(token); output.push_back(token);
} }
_ => (), _ => (),
@ -572,17 +646,17 @@ fn parse_term<'a>(
scope, scope,
&mut value_stack, &mut value_stack,
diagnostics, diagnostics,
); )?;
output.push_back(token) output.push_back(token)
} }
} }
} }
//println!("{}", dbginf.make_msg(crate::msg::ERR64)); diagnostics.set_err(&token, crate::msg::ERR64, "");
panic!(); return Err(());
} }
_ => { _ => {
//println!("{}", dbginf.make_msg(crate::msg::ERR65)); diagnostics.set_err(&token, crate::msg::ERR65, "");
panic!() return Err(());
} }
}, },
@ -600,7 +674,7 @@ fn parse_term<'a>(
scope, scope,
&mut value_stack, &mut value_stack,
diagnostics, diagnostics,
); )?;
output.push_back(op_stack.pop().unwrap()); output.push_back(op_stack.pop().unwrap());
continue; continue;
} }
@ -617,13 +691,14 @@ fn parse_term<'a>(
while let Some(mut token) = op_stack.pop() { while let Some(mut token) = op_stack.pop() {
match &token { match &token {
Token::Delemiter(char, dbginf) => { Token::Delemiter(char, _) => {
if *char == '(' { if *char == '(' {
//println!("{}", dbginf.make_msg(crate::msg::ERR63)); diagnostics.set_err(&token, crate::msg::ERR63, "");
return Err(());
} }
} }
_ => { _ => {
collapse_operation(&mut token, declrs, scope, &mut value_stack, diagnostics); collapse_operation(&mut token, declrs, scope, &mut value_stack, diagnostics)?;
output.push_back(token) output.push_back(token)
} }
} }
@ -631,7 +706,7 @@ fn parse_term<'a>(
if value_stack.len() > 1 { if value_stack.len() > 1 {
diagnostics.set_err(&output[0], crate::msg::ERR50, ""); diagnostics.set_err(&output[0], crate::msg::ERR50, "");
return; return Err(());
} }
scope.expr_yield = value_stack.len() == 1; scope.expr_yield = value_stack.len() == 1;
@ -652,6 +727,8 @@ fn parse_term<'a>(
} }
term.append(&mut output); term.append(&mut output);
Ok(())
} }
fn is_func(declrs: &[Declr], text: &str) -> bool { fn is_func(declrs: &[Declr], text: &str) -> bool {
@ -668,24 +745,25 @@ fn parse_block<'a>(
declrs: &Vec<Declr<'a>>, declrs: &Vec<Declr<'a>>,
scope: &mut Scope, scope: &mut Scope,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) { ) -> Result<(), ()> {
scope.cond_count += 1; scope.cond_count += 1;
scope.alloc_scope(); scope.alloc_scope();
for expr in block.iter_mut() { for expr in block.iter_mut() {
match expr { match expr {
Expr::Block(block) => parse_block(block, declrs, scope, diagnostics), Expr::Block(block) => parse_block(block, declrs, scope, diagnostics)?,
Expr::Term(term) => parse_term(term, declrs, scope, diagnostics), Expr::Term(term) => parse_term(term, declrs, scope, diagnostics)?,
} }
} }
scope.pop_scope(); scope.pop_scope();
scope.cond_count -= 1; scope.cond_count -= 1;
Ok(())
} }
fn parse_exprs<'a>( fn parse_exprs<'a>(
funcs: &mut Vec<Func<'a>>, funcs: &mut Vec<Func<'a>>,
declrs: &Vec<Declr<'a>>, declrs: &Vec<Declr<'a>>,
diagnostics: &mut data::Diagnostics, diagnostics: &mut data::Diagnostics,
) { ) -> Result<(),()> {
let mut scope = Scope::new(); let mut scope = Scope::new();
for (x, func) in funcs.iter_mut().enumerate() { for (x, func) in funcs.iter_mut().enumerate() {
@ -696,31 +774,35 @@ fn parse_exprs<'a>(
scope.yields = false; scope.yields = false;
scope.cond_count = 0; scope.cond_count = 0;
parse_block(block, declrs, &mut scope, diagnostics); parse_block(block, declrs, &mut scope, diagnostics)?;
if scope.func_return_typ.is_some() && !scope.yields && !scope.expr_yield { if scope.func_return_typ.is_some() && !scope.yields && !scope.expr_yield {
//token.create_msg_w_ext(crate::msg::ERR56, format!("at function {}", declrs[x])); diagnostics.set_err(declrs[x].info.as_ref().unwrap(), crate::msg::ERR56, format!("for function: {}", declrs[x]));
panic!(); return Err(());
} }
} }
_ => panic!("Fatal-Compilier-Error: function must have a block"), _ => {
crate::message(crate::token::MessageType::Critical, "Fatal-Compilier-Error: function must have a block");
panic!();
},
} }
} }
Ok(())
} }
/// reorder and organize a listing of instructions to a RPN based format: /// reorder and organize a listing of instructions to a RPN based format:
/// any program is made out of functions. /// any program is made out of functions.
/// A function has a name followed by an optional parameter list, followed by an optional equal sign and block. /// A function has a name followed by an optional parameter list, followed by an optional equal sign and block.
pub fn parse<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &'a str) -> Diagnostics<'a> { pub fn parse<'a>(tokens: &mut VecDeque<crate::Token<'a>>, diagnostics: &mut data::Diagnostics, settings: &Settings) {
let mut dias = data::Diagnostics::new(source);
if let Ok((mut funcs, declrs)) = discover_functions(tokens, &mut dias) { if let Ok((mut funcs, declrs)) = discover_functions(tokens, diagnostics) {
// make all of this shit return a mutable diagnostics struct. if let Ok(()) = discover_exprs(&mut funcs, &declrs, diagnostics) {
discover_exprs(&mut funcs, &declrs, &mut dias); if let Ok(()) = parse_exprs(&mut funcs, &declrs, diagnostics) {
parse_exprs(&mut funcs, &declrs, &mut dias);
crate::inter::convert_to_erpn(&mut funcs, &declrs); if settings.gen_erpn() {
crate::inter::convert_to_erpn(&mut funcs, &declrs);
}
}
}
} }
dias
} }

View File

@ -1,7 +1,7 @@
use crate::token::DebugMsg; use crate::token::DebugMsg;
use crate::token::MessageType::Error; use crate::token::MessageType::Error;
use crate::token::MessageType::Info; use crate::token::MessageType::Info;
use crate::token::MessageType::Warning; //use crate::token::MessageType::Warning;
pub const ERR10: &DebugMsg = &DebugMsg { pub const ERR10: &DebugMsg = &DebugMsg {
typ: Error, typ: Error,
@ -73,6 +73,12 @@ pub const ERR23: &DebugMsg = &DebugMsg {
code: 23, code: 23,
msg: "token must be declaration", msg: "token must be declaration",
}; };
pub const ERR24: &DebugMsg = &DebugMsg {
typ: Error,
code: 24,
msg: "function already has return type",
};
pub const ERR40: &DebugMsg = &DebugMsg { pub const ERR40: &DebugMsg = &DebugMsg {
typ: Error, typ: Error,
@ -183,11 +189,7 @@ pub const ERR71: &DebugMsg = &DebugMsg {
code: 71, code: 71,
msg: "Unable to identify characters as token", msg: "Unable to identify characters as token",
}; };
pub const ERR72: &DebugMsg = &DebugMsg {
typ: Error,
code: 72,
msg: "Unknown operator",
};
pub const ERR73: &DebugMsg = &DebugMsg { pub const ERR73: &DebugMsg = &DebugMsg {
typ: Error, typ: Error,
code: 73, code: 73,

View File

@ -1,6 +1,8 @@
use colored::{ColoredString, Colorize}; use colored::{ColoredString, Colorize};
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::parser::data::Diagnostics;
#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)] #[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
pub enum Operator { pub enum Operator {
// bitwise boolean operations // bitwise boolean operations
@ -117,31 +119,26 @@ impl Operator {
operands: &[Prim], operands: &[Prim],
types: &[Prim], types: &[Prim],
r#yield: Prim, r#yield: Prim,
dbginf: &DebugInfo, info: &DebugInfo,
diagnostics: &mut crate::parser::data::Diagnostics, diagnostics: &mut crate::parser::data::Diagnostics,
) -> Option<Prim> { ) -> Result<Option<Prim>, ()> {
if operands.len() < types.len() { if operands.len() < types.len() {
/* diagnostics.set_err(info, crate::msg::ERR74, format!(
println!(
"{}",
dbginf.make_msg_w_ext(
crate::msg::ERR74,
format!(
"required {} got {}", "required {} got {}",
types.len() - operands.len(), types.len() - operands.len(),
operands.len() operands.len()
) )
) );
);*/ return Err(());
panic!()
} }
for (x, typ) in types.iter().enumerate() { for (x, typ) in types.iter().enumerate() {
if typ != &operands[x] { if typ != &operands[x] {
return None; return Ok(None);
} }
} }
Some(r#yield) Ok(Some(r#yield))
} }
fn check_types( fn check_types(
@ -149,60 +146,54 @@ impl Operator {
types: &[(&[Prim], Prim)], types: &[(&[Prim], Prim)],
dbginf: &DebugInfo, dbginf: &DebugInfo,
diagnostics: &mut crate::parser::data::Diagnostics, diagnostics: &mut crate::parser::data::Diagnostics,
) -> Option<Prim> { ) -> Result<Option<Prim>,()> {
for combination in types.iter() { for combination in types.iter() {
if let Some(result) = if let Some(result) =
Self::present_types(operands, combination.0, combination.1, dbginf, diagnostics) Self::present_types(operands, combination.0, combination.1, dbginf, diagnostics)?
{ {
return Some(result); return Ok(Some(result));
} }
} }
None Ok(None)
} }
pub fn operate( pub fn operate(
&self, &self,
operands: &mut Vec<Prim>, operands: &mut Vec<Prim>,
dbginf: &DebugInfo, info: &DebugInfo,
diagnostics: &mut crate::parser::data::Diagnostics, diagnostics: &mut crate::parser::data::Diagnostics,
) { ) -> Result<(),()> {
match self { match self {
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div => { Operator::Add | Operator::Sub | Operator::Mul | Operator::Div => {
let types_valid = let types_valid =
Self::check_types(operands, ARITHMETIC_TYPES, dbginf, diagnostics); Self::check_types(operands, ARITHMETIC_TYPES, info, diagnostics)?;
if let Some(result) = types_valid { if let Some(result) = types_valid {
operands.pop(); operands.pop();
operands.pop(); operands.pop();
operands.push(result); operands.push(result);
return Ok(());
} else { } else {
/* diagnostics.set_err(info, crate::msg::ERR73, "expected two numbers");
println!( return Err(());
"{}",
dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two numbers")
);*/
panic!()
} }
} }
Operator::And | Operator::Or | Operator::Xor => { Operator::And | Operator::Or | Operator::Xor => {
let types_valid = Self::check_types( let types_valid = Self::check_types(
operands, operands,
&[(&[Prim::Bool, Prim::Bool], Prim::Bool)], &[(&[Prim::Bool, Prim::Bool], Prim::Bool)],
dbginf, info,
diagnostics, diagnostics,
); )?;
if let Some(result) = types_valid { if let Some(result) = types_valid {
operands.pop(); operands.pop();
operands.pop(); operands.pop();
operands.push(result); operands.push(result);
return Ok(())
} else { } else {
/* diagnostics.set_err(info, crate::msg::ERR73, "expected two booleans");
println!( return Err(());
"{}",
dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two booleans")
);*/
panic!()
} }
} }
Operator::Eq Operator::Eq
@ -229,21 +220,18 @@ impl Operator {
Prim::Bool, Prim::Bool,
), ),
], ],
dbginf, info,
diagnostics, diagnostics,
); )?;
if let Some(result) = types_valid { if let Some(result) = types_valid {
operands.pop(); operands.pop();
operands.pop(); operands.pop();
operands.push(result); operands.push(result);
return Ok(());
} else { } else {
/* diagnostics.set_err(info, crate::msg::ERR73, "expected either two booleans or two numbers");
println!( return Err(());
"{}",
dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two numbers")
);*/
panic!()
} }
} }
_ => { _ => {
@ -255,7 +243,7 @@ impl Operator {
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Keyword { pub enum Keyword {
If, Unless,
While, While,
/// while(true) loop /// while(true) loop
Loop, Loop,
@ -269,7 +257,7 @@ pub enum Keyword {
impl Keyword { impl Keyword {
pub fn parse<'a>(text: &'a str) -> Keyword { pub fn parse<'a>(text: &'a str) -> Keyword {
return match text { return match text {
"unless" => Keyword::If, "unless" => Keyword::Unless,
"while" => Keyword::While, "while" => Keyword::While,
"loop" => Keyword::Loop, "loop" => Keyword::Loop,
"break" => Keyword::Break, "break" => Keyword::Break,
@ -314,14 +302,14 @@ pub enum Prim {
} }
impl Prim { impl Prim {
fn from<'a>(text: &'a str, dbginf: &DebugInfo) -> Prim { fn from<'a>(text: &'a str, info: &DebugInfo, diagnostics: &mut Diagnostics) -> Result<Prim, ()> {
return match text { return match text {
"int" => Prim::Int, "int" => Ok(Prim::Int),
"rat" => Prim::Rat, "rat" => Ok(Prim::Rat),
"bool" => Prim::Bool, "bool" => Ok(Prim::Bool),
_ => { _ => {
//println!("{}", dbginf.make_msg(&crate::msg::ERR70)); diagnostics.set_err(info, crate::msg::ERR70, format!("token is not a type: {}", text));
panic!() return Err(())
} }
}; };
} }
@ -358,6 +346,18 @@ impl Prim {
} }
} }
impl std::fmt::Display for Prim {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Prim::Int => f.write_str("Int")?,
Prim::Rat => f.write_str("Rat")?,
Prim::Bool => f.write_str("Bool")?,
Prim::Num(_) => f.write_fmt(format_args!("{:?}", self))?
}
Ok(())
}
}
pub struct DebugMsg { pub struct DebugMsg {
pub code: i32, pub code: i32,
pub typ: MessageType, pub typ: MessageType,
@ -384,7 +384,7 @@ impl<'a> std::fmt::Display for DebugNotice<'a> {
self.msg.msg.bold().bright_white(), self.msg.msg.bold().bright_white(),
self.info.line, self.info.line,
self.ext self.ext
)); ))?;
// write additional information // write additional information
f.write_fmt(format_args!( f.write_fmt(format_args!(
" somewhere in here:\n --> `{}`\n", " somewhere in here:\n --> `{}`\n",
@ -446,7 +446,7 @@ impl MessageType {
} }
impl std::fmt::Display for DebugInfo { impl std::fmt::Display for DebugInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(()) Ok(())
} }
} }
@ -491,7 +491,7 @@ impl<'a> std::fmt::Display for Token<'a> {
Token::Func(name, _) => f.write_fmt(format_args!("Call {}", name)), Token::Func(name, _) => f.write_fmt(format_args!("Call {}", name)),
Token::Var(v, _) => f.write_fmt(format_args!("Load Var {}", v)), Token::Var(v, _) => f.write_fmt(format_args!("Load Var {}", v)),
Token::Arg(a, _) => f.write_fmt(format_args!("Load Arg {}", a)), Token::Arg(a, _) => f.write_fmt(format_args!("Load Arg {}", a)),
Token::Assign(a, typ, _) => f.write_fmt(format_args!("Store {:?} {}", typ, a)), Token::Assign(a, typ, _) => f.write_fmt(format_args!("Store {} {}", typ.unwrap(), a)),
Token::Decl(d, typ, _) => f.write_fmt(format_args!("__Decl {:?} as {}", typ, d)), Token::Decl(d, typ, _) => f.write_fmt(format_args!("__Decl {:?} as {}", typ, d)),
Token::Bool(b, _) => f.write_fmt(format_args!("Load Bool {}", b)), Token::Bool(b, _) => f.write_fmt(format_args!("Load Bool {}", b)),
Token::Keyword(k, _) => f.write_fmt(format_args!("{:?}", k)), Token::Keyword(k, _) => f.write_fmt(format_args!("{:?}", k)),
@ -528,7 +528,7 @@ lazy_static::lazy_static! {
} }
/// creates a vector of tokens from the specified str. /// creates a vector of tokens from the specified str.
pub fn tokenize(source: &str) -> VecDeque<Token> { pub fn tokenize<'a>(source: &'a str, diagnostics: &mut Diagnostics) -> Result<VecDeque<Token<'a>>, ()> {
let mut tokens = VecDeque::new(); let mut tokens = VecDeque::new();
let mut line_count = 0; let mut line_count = 0;
@ -560,11 +560,11 @@ pub fn tokenize(source: &str) -> VecDeque<Token> {
tokens.push_back(match i { tokens.push_back(match i {
2 => Token::Keyword(Keyword::parse(mat.as_str()), debug_info), 2 => Token::Keyword(Keyword::parse(mat.as_str()), debug_info),
3 => Token::Type(Prim::from(mat.as_str(), &debug_info), debug_info), 3 => Token::Type(Prim::from(mat.as_str(), &debug_info, diagnostics)?, debug_info),
4 => Token::Bool(parse_bool(mat.as_str()), debug_info), 4 => Token::Bool(parse_bool(mat.as_str()), debug_info),
5 => { 5 => {
let var_type = if let Some(mat) = enumerator.next().unwrap().1 { let var_type = if let Some(mat) = enumerator.next().unwrap().1 {
Some(Prim::from(mat.as_str(), &debug_info)) Some(Prim::from(mat.as_str(), &debug_info, diagnostics)?)
} else { } else {
None None
}; };
@ -572,7 +572,7 @@ pub fn tokenize(source: &str) -> VecDeque<Token> {
} }
7 => { 7 => {
let var_type = let var_type =
Prim::from(enumerator.next().unwrap().1.unwrap().as_str(), &debug_info); Prim::from(enumerator.next().unwrap().1.unwrap().as_str(), &debug_info, diagnostics)?;
Token::Decl(mat.as_str(), var_type, debug_info) Token::Decl(mat.as_str(), var_type, debug_info)
} }
9 => Token::Word(mat.as_str(), debug_info), 9 => Token::Word(mat.as_str(), debug_info),
@ -587,8 +587,8 @@ pub fn tokenize(source: &str) -> VecDeque<Token> {
14 => Token::Terminator(debug_info), 14 => Token::Terminator(debug_info),
_ => { _ => {
//println!("{}", debug_info.make_msg(crate::msg::ERR71)); diagnostics.set_err(&debug_info, crate::msg::ERR71, format!("token: {}", mat.as_str()));
panic!() return Err(());
} }
}); });
break; break;
@ -596,7 +596,7 @@ pub fn tokenize(source: &str) -> VecDeque<Token> {
} }
} }
return tokens; return Ok(tokens);
} }
fn parse_bool(text: &str) -> bool { fn parse_bool(text: &str) -> bool {
@ -604,6 +604,9 @@ fn parse_bool(text: &str) -> bool {
"true" | "ye" => true, "true" | "ye" => true,
"false" | "no" => false, "false" | "no" => false,
"maybe" => rand::random(), "maybe" => rand::random(),
_ => panic!("Not a recognized boolean {text}"), _ => {
crate::message(MessageType::Critical, format!("token: {}", text));
panic!();
},
}; };
} }

View File

@ -4,31 +4,31 @@ foo:
Load Int 5 Load Int 5
Load Int 6 Load Int 6
Add Add
Store Some(Int) x Store Int x
Load Arg x Load Arg x
Load Int 6 Load Int 6
Lt Lt
If Unless
Load Bool true Load Bool true
Yield Yield
Please Please
Load Arg x Load Arg x
Load Int 6 Load Int 6
Lt Lt
If Unless
Load Bool true Load Bool true
Yield Yield
Load Bool false Load Bool true
Yield Yield
main: main:
Load Int 4 Load Int 4
Store None a Store Int a
Load Rat 5.5 Load Rat 5.5
Store None b Store Rat b
Load Bool true Load Bool true
Store None c Store Bool c
Load Int 3 Load Int 3
Load Rat 3.4 Load Rat 3.4
Call foo Call foo
Store None r Store Bool r
Load Int 0 Load Int 0