using results instead panic
This commit is contained in:
parent
f262a5d92b
commit
d3f121640a
20
src/main.rs
20
src/main.rs
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
// tokenizer
|
// tokenizer
|
||||||
mod token;
|
mod token;
|
||||||
// ro parse a queue of tokens into functions with expressions
|
// ro parse a queue of tokens into functions with expressions
|
||||||
|
@ -7,18 +6,19 @@ mod parser;
|
||||||
// designed for a virtual stack machiene
|
// designed for a virtual stack machiene
|
||||||
mod inter;
|
mod inter;
|
||||||
|
|
||||||
use token::*;
|
|
||||||
use parser::*;
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use parser::*;
|
||||||
|
use token::*;
|
||||||
|
|
||||||
pub fn message(typ: MessageType, msg: String) {
|
pub fn message<S>(typ: MessageType, msg: S)
|
||||||
println!("{}: {}", typ.to_colored(), msg.bold().bright_white());
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
println!("{}: {}", typ.to_colored(), msg.into().bold().bright_white());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let source = r"
|
||||||
let source =
|
|
||||||
r"
|
|
||||||
# this is pi
|
# this is pi
|
||||||
pi = rat 5.1415926535
|
pi = rat 5.1415926535
|
||||||
|
|
||||||
|
@ -50,5 +50,7 @@ main() = int {
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
parse(&mut tokenize(source), source);
|
let diagnostics = parse(&mut tokenize(source), source);
|
||||||
|
|
||||||
|
println!("{}", diagnostics);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,74 @@
|
||||||
use core::panic;
|
use crate::token::{DebugInfo, DebugNotice, Token};
|
||||||
use std::collections::{VecDeque};
|
|
||||||
use crate::token::{Token, DebugErr};
|
|
||||||
use crate::Prim;
|
use crate::Prim;
|
||||||
|
use core::panic;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub struct Diagnostics<'a> {
|
pub struct Diagnostics<'a> {
|
||||||
/// terminating factor on error
|
/// terminating factor on error
|
||||||
err: Option<DebugErr<'a>>,
|
err: Option<DebugNotice<'a>>,
|
||||||
/// additional warning and informations
|
/// additional warning and informations
|
||||||
/// all non critical
|
/// all non critical
|
||||||
hints: Vec<DebugErr<'a>>
|
hints: Vec<DebugNotice<'a>>,
|
||||||
|
/// source string
|
||||||
|
source: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Diagnostics<'a> {
|
||||||
|
pub fn new(source: &'a str) -> Self {
|
||||||
|
Self {
|
||||||
|
err: None,
|
||||||
|
hints: vec![],
|
||||||
|
source,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_err<T, S>(&mut self, source: &S, message: &'static crate::token::DebugMsg, ext: T)
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
S: Into<DebugInfo> + Clone,
|
||||||
|
{
|
||||||
|
if self.err.is_some() {
|
||||||
|
panic!("Error already set");
|
||||||
|
}
|
||||||
|
|
||||||
|
let info: DebugInfo = source.clone().into();
|
||||||
|
|
||||||
|
self.err = Some(DebugNotice {
|
||||||
|
info,
|
||||||
|
msg: message,
|
||||||
|
ext: ext.into(),
|
||||||
|
source: self.source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hint<T, S>(&mut self, source: &S, message: &'static crate::token::DebugMsg, ext: T)
|
||||||
|
where
|
||||||
|
T: Into<String>,
|
||||||
|
S: Into<DebugInfo> + Clone,
|
||||||
|
{
|
||||||
|
let info: DebugInfo = source.clone().into();
|
||||||
|
|
||||||
|
self.hints.push(DebugNotice {
|
||||||
|
info,
|
||||||
|
msg: message,
|
||||||
|
ext: ext.into(),
|
||||||
|
source: self.source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> std::fmt::Display for Diagnostics<'a> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
for hint in self.hints.iter() {
|
||||||
|
f.write_fmt(format_args!("{}\n\n", hint)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(err) = self.err.as_ref() {
|
||||||
|
f.write_fmt(format_args!("{}\n\n", err)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -37,7 +97,7 @@ pub struct Declr<'a> {
|
||||||
/// if the function returns a single value
|
/// if the function returns a single value
|
||||||
pub results: bool,
|
pub results: bool,
|
||||||
/// type of result
|
/// type of result
|
||||||
pub result_typ: Option<Prim>
|
pub result_typ: Option<Prim>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Declr<'a> {
|
impl<'a> Declr<'a> {
|
||||||
|
@ -46,7 +106,7 @@ impl<'a> Declr<'a> {
|
||||||
name: None,
|
name: None,
|
||||||
args: None,
|
args: None,
|
||||||
results: false,
|
results: false,
|
||||||
result_typ: None
|
result_typ: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +145,7 @@ pub enum Expr<'a> {
|
||||||
/// group of more expressions
|
/// group of more expressions
|
||||||
Block(Block<'a>),
|
Block(Block<'a>),
|
||||||
/// single term
|
/// single term
|
||||||
Term(VecDeque<Token<'a>>)
|
Term(VecDeque<Token<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Scope<'a> {
|
pub struct Scope<'a> {
|
||||||
|
@ -97,7 +157,7 @@ pub struct Scope<'a> {
|
||||||
pub yields: bool,
|
pub yields: bool,
|
||||||
/// if the last expr yielded a result
|
/// if the last expr yielded a result
|
||||||
pub expr_yield: bool,
|
pub expr_yield: bool,
|
||||||
pub cond_count: usize
|
pub cond_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Scope<'a> {
|
impl<'a> Scope<'a> {
|
||||||
|
@ -171,7 +231,7 @@ impl<'a> Scope<'a> {
|
||||||
func_return_typ: None,
|
func_return_typ: None,
|
||||||
expr_yield: false,
|
expr_yield: false,
|
||||||
yields: false,
|
yields: false,
|
||||||
cond_count: 0
|
cond_count: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use core::{panic};
|
use crate::token::{Assoc, DebugInfo, Keyword, Operator, Prim, Token};
|
||||||
use std::{collections::{VecDeque}, vec};
|
use core::panic;
|
||||||
use crate::token::{Token, Operator, Assoc, Prim, MessageType, Keyword};
|
use std::{collections::VecDeque, vec};
|
||||||
|
|
||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod msg;
|
pub mod msg;
|
||||||
|
@ -8,7 +8,10 @@ pub mod msg;
|
||||||
use data::*;
|
use data::*;
|
||||||
|
|
||||||
/// simple brace-counting parser to detect functions
|
/// simple brace-counting parser to detect functions
|
||||||
fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str) -> (Vec<Func<'a>>, Vec<Declr<'a>>) {
|
fn discover_functions<'a>(
|
||||||
|
tokens: &mut VecDeque<crate::Token<'a>>,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) -> 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();
|
||||||
|
|
||||||
|
@ -23,15 +26,19 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
||||||
let mut single_line = false;
|
let mut single_line = false;
|
||||||
|
|
||||||
macro_rules! finish_func {
|
macro_rules! finish_func {
|
||||||
($dbginf:expr) => {
|
($token:expr) => {
|
||||||
if declrs.contains(&declr) {
|
if declrs.contains(&declr) {
|
||||||
println!("{}", $dbginf.make_msg_w_ext(crate::msg::ERR10, format!("Multiple definitions: {declr}")));
|
diagnostics.set_err(
|
||||||
panic!()
|
$token,
|
||||||
|
crate::msg::ERR10,
|
||||||
|
format!("Multiple definitions: {declr}"),
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if declr.results && declr.result_typ.is_none() {
|
if declr.results && declr.result_typ.is_none() {
|
||||||
println!("{}", $dbginf.make_msg_w_ext(crate::msg::ERR11, format!("for function {declr}")));
|
diagnostics.set_err($token, crate::msg::ERR11, format!("for function {declr}"));
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
funcs.push(func);
|
funcs.push(func);
|
||||||
|
@ -43,7 +50,6 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(top) = tokens.pop_front() {
|
while let Some(top) = tokens.pop_front() {
|
||||||
|
|
||||||
// function body detection
|
// function body detection
|
||||||
// has highest priority
|
// has highest priority
|
||||||
match &top {
|
match &top {
|
||||||
|
@ -54,102 +60,107 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
||||||
// we have an found open function body
|
// we have an found open function body
|
||||||
if brace_cnt == 1 {
|
if brace_cnt == 1 {
|
||||||
if declr.name.is_none() {
|
if declr.name.is_none() {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR12));
|
diagnostics.set_err(&top, crate::msg::ERR12, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if paren_cnt > 0 {
|
if paren_cnt > 0 {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR13));
|
diagnostics.set_err(&top, crate::msg::ERR13, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
single_line = false;
|
single_line = false;
|
||||||
func.raw = Some(VecDeque::new());
|
func.raw = Some(VecDeque::new());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
'}' => {
|
'}' => {
|
||||||
brace_cnt -= 1;
|
brace_cnt -= 1;
|
||||||
|
|
||||||
// we closed one to much
|
// we closed one to much
|
||||||
if brace_cnt < 0 {
|
if brace_cnt < 0 {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR14));
|
diagnostics.set_err(&top, crate::msg::ERR14, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of function body
|
// end of function body
|
||||||
if brace_cnt == 0 {
|
if brace_cnt == 0 {
|
||||||
finish_func!(dbginf);
|
finish_func!(&top);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
},
|
||||||
|
|
||||||
Token::Type(typ, dbginf) => if declr.result_typ.is_none() {
|
Token::Type(typ, dbginf) => {
|
||||||
|
if declr.result_typ.is_none() {
|
||||||
if declr.results {
|
if declr.results {
|
||||||
declr.result_typ = Some(*typ);
|
declr.result_typ = Some(*typ);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR16));
|
diagnostics.set_err(&top, crate::msg::ERR16, "");
|
||||||
panic!();
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
Token::LineBreak(dbginf) => if single_line {
|
Token::LineBreak(dbginf) => {
|
||||||
finish_func!(dbginf);
|
if single_line {
|
||||||
|
finish_func!(&top);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ => if single_line && func.raw.is_none() {
|
_ => {
|
||||||
|
if single_line && func.raw.is_none() {
|
||||||
func.raw = Some(VecDeque::new());
|
func.raw = Some(VecDeque::new());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if func.raw.is_none() {
|
if func.raw.is_none() {
|
||||||
match &top {
|
match &top {
|
||||||
Token::Operator(op, dbginf) => match op {
|
Token::Operator(op, dbginf) => match op {
|
||||||
Operator::Assign => {
|
Operator::Assign => {
|
||||||
if declr.results {
|
if declr.results {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR17));
|
diagnostics.set_err(&top, crate::msg::ERR17, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
if declr.name.is_none() {
|
if declr.name.is_none() {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR12));
|
diagnostics.set_err(&top, crate::msg::ERR12, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
declr.results = true;
|
declr.results = true;
|
||||||
single_line = true;
|
single_line = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
},
|
||||||
|
|
||||||
Token::Word(text, dbginf) => {
|
Token::Word(text, dbginf) => {
|
||||||
|
|
||||||
if declr.name.is_some() {
|
if declr.name.is_some() {
|
||||||
if declr.args.is_none() {
|
if declr.args.is_none() {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR18));
|
diagnostics.set_err(&top, crate::msg::ERR18, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
} else if brace_cnt > 0 {
|
} else if brace_cnt > 0 {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR13));
|
diagnostics.set_err(&top, crate::msg::ERR13, "");
|
||||||
panic!();
|
return Err(());
|
||||||
} else {
|
} else {
|
||||||
declr.name = Some(text);
|
declr.name = Some(text);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
Token::Assign(name, _, dbginf) => {
|
Token::Assign(name, _, dbginf) => {
|
||||||
if declr.results {
|
if declr.results {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR17));
|
diagnostics.set_err(&top, crate::msg::ERR17, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
if declr.name.is_some() {
|
if declr.name.is_some() {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR18));
|
diagnostics.set_err(&top, crate::msg::ERR18, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
func.raw = Some(VecDeque::new());
|
func.raw = Some(VecDeque::new());
|
||||||
|
@ -160,52 +171,50 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
||||||
}
|
}
|
||||||
|
|
||||||
Token::Delemiter(char, dbginf) => match char {
|
Token::Delemiter(char, dbginf) => match char {
|
||||||
|
'(' => {
|
||||||
'(' => if func.raw.is_none() {
|
if func.raw.is_none() {
|
||||||
paren_cnt += 1;
|
paren_cnt += 1;
|
||||||
if paren_cnt == 1 {
|
if paren_cnt == 1 {
|
||||||
|
|
||||||
if declr.args.is_some() {
|
if declr.args.is_some() {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR19));
|
diagnostics.set_err(&top, crate::msg::ERR19, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
declr.args = Some(Vec::new());
|
declr.args = Some(Vec::new());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
')' => {
|
')' => {
|
||||||
paren_cnt -= 1;
|
paren_cnt -= 1;
|
||||||
if paren_cnt == 0 {
|
if paren_cnt == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
},
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(body) = &mut func.raw {
|
if let Some(body) = &mut func.raw {
|
||||||
body.push_back(top);
|
body.push_back(top);
|
||||||
continue;
|
continue;
|
||||||
}
|
} else if let Some(args) = &mut declr.args {
|
||||||
else if let Some(args) = &mut declr.args {
|
|
||||||
|
|
||||||
if paren_cnt == 0 {
|
if paren_cnt == 0 {
|
||||||
println!("{}", top.create_msg(crate::msg::ERR20));
|
diagnostics.set_err(&top, crate::msg::ERR20, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
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) => {
|
Token::Word(_, dbginf) => {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR21));
|
diagnostics.set_err(&top, crate::msg::ERR21, "");
|
||||||
panic!()
|
return Err(());
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("{}", top.create_msg(crate::msg::ERR23));
|
diagnostics.set_err(&top, crate::msg::ERR23, "");
|
||||||
panic!()
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -215,79 +224,94 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
||||||
match &top {
|
match &top {
|
||||||
Token::LineBreak(_) | Token::Terminator(_) => (), // valid whitespace
|
Token::LineBreak(_) | Token::Terminator(_) => (), // valid whitespace
|
||||||
_ => {
|
_ => {
|
||||||
println!("{}", top.create_msg(crate::msg::ERR22));
|
diagnostics.set_err(&top, crate::msg::ERR22, "");
|
||||||
panic!()
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(raw) = func.raw {
|
if let Some(raw) = func.raw {
|
||||||
if let Some(front) = raw.front() {
|
if let Some(front) = raw.front() {
|
||||||
println!("{}", front.create_msg(crate::msg::ERR15));
|
diagnostics.set_err(front, crate::msg::ERR15, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(funcs, declrs)
|
Ok((funcs, declrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// parse the functions raw content to expr for easy compilation using a brace-counter.
|
/// parse the functions raw content to expr for easy compilation using a brace-counter.
|
||||||
/// - ```{...}``` surround a block
|
/// - ```{...}``` surround a block
|
||||||
/// - line breaks seperate expressions
|
/// - line breaks seperate expressions
|
||||||
fn discover_exprs<'a>(functions: &mut Vec<Func<'a>>, _: &Vec<Declr<'a>>, source: &'a str) {
|
fn discover_exprs<'a>(
|
||||||
|
functions: &mut Vec<Func<'a>>,
|
||||||
|
_: &Vec<Declr<'a>>,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) {
|
||||||
for func in functions.iter_mut() {
|
for func in functions.iter_mut() {
|
||||||
|
|
||||||
let mut blocks = vec![Block::new()];
|
let mut blocks = vec![Block::new()];
|
||||||
|
|
||||||
let mut expr = VecDeque::new();
|
let mut expr = VecDeque::new();
|
||||||
|
|
||||||
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) => if !expr.is_empty() {
|
Token::LineBreak(dbginf) | Token::Terminator(dbginf) => {
|
||||||
blocks.last_mut().unwrap_or_else(|| {
|
if !expr.is_empty() {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR41));
|
if let Some(blocks) = blocks.last_mut() {
|
||||||
panic!()
|
blocks.push_back(Expr::Term(expr))
|
||||||
}).push_back(Expr::Term(expr));
|
} else {
|
||||||
|
diagnostics.set_err(&top, crate::msg::ERR41, "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
expr = VecDeque::new();
|
expr = VecDeque::new();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Token::Delemiter(char, dbginf) => match char {
|
Token::Delemiter(char, dbginf) => match char {
|
||||||
'{' => {
|
'{' => {
|
||||||
blocks.last_mut().unwrap_or_else(|| {
|
blocks
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR41));
|
.last_mut()
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
diagnostics.set_err(&top, crate::msg::ERR41, "");
|
||||||
panic!()
|
panic!()
|
||||||
}).push_back(Expr::Term(expr));
|
})
|
||||||
|
.push_back(Expr::Term(expr));
|
||||||
expr = VecDeque::new();
|
expr = VecDeque::new();
|
||||||
blocks.push(Block::new());
|
blocks.push(Block::new());
|
||||||
continue;
|
continue;
|
||||||
},
|
}
|
||||||
'}' => {
|
'}' => {
|
||||||
// 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.last_mut().unwrap_or_else(|| {
|
blocks
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR41));
|
.last_mut()
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
//println!("{}", dbginf.make_msg(crate::msg::ERR41));
|
||||||
panic!()
|
panic!()
|
||||||
}).push_back(Expr::Block(block));
|
})
|
||||||
|
.push_back(Expr::Block(block));
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR40));
|
//println!("{}", dbginf.make_msg(crate::msg::ERR40));
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
},
|
},
|
||||||
_ => ()
|
_ => (),
|
||||||
},
|
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr.push_back(top)
|
expr.push_back(top)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !expr.is_empty() {
|
if !expr.is_empty() {
|
||||||
blocks.last_mut().unwrap_or_else(|| {
|
blocks
|
||||||
println!("{}", expr.back().unwrap().create_msg(crate::msg::ERR40));
|
.last_mut()
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
diagnostics.set_err(expr.back().unwrap(), crate::msg::ERR40, "");
|
||||||
panic!()
|
panic!()
|
||||||
}).push_back(Expr::Term(expr));
|
})
|
||||||
|
.push_back(Expr::Term(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(block) = blocks.pop() {
|
if let Some(block) = blocks.pop() {
|
||||||
|
@ -298,103 +322,150 @@ fn discover_exprs<'a>(functions: &mut Vec<Func<'a>>, _: &Vec<Declr<'a>>, source:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_var_typ(typ: &mut Option<Prim>, operands: &mut Vec<Prim>, dbginf: &crate::token::DebugInfo, source: &str) {
|
fn check_var_typ(
|
||||||
|
typ: &mut Option<Prim>,
|
||||||
|
operands: &mut Vec<Prim>,
|
||||||
|
info: &crate::token::DebugInfo,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) -> Result<(), ()> {
|
||||||
if let Some(value) = operands.pop() {
|
if let Some(value) = operands.pop() {
|
||||||
if !operands.is_empty() {
|
if !operands.is_empty() {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR50));
|
diagnostics.set_err(info, crate::msg::ERR50, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(typ) = typ {
|
if let Some(typ) = typ {
|
||||||
if !typ.is_equal(value) {
|
if !typ.is_equal(value) {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR51, format!("needed {:?} got {:?}", typ, value) ));
|
diagnostics.set_err(
|
||||||
panic!();
|
info,
|
||||||
|
crate::msg::ERR51,
|
||||||
|
format!("needed {:?} got {:?}", typ, value),
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// assign a type to untyped variable
|
diagnostics.hint(info, crate::msg::INF51, format!("gessed type: {:?}", value));
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::INF51, format!("gessed type: {:?}", value) ));
|
|
||||||
*typ = Some(value);
|
*typ = Some(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR52));
|
diagnostics.set_err(info, crate::msg::ERR52, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_keyword(keyword: Keyword, _: &Vec<Declr>, scope: &mut Scope, operands: &mut Vec<Prim>, dbginf: &crate::token::DebugInfo, source: &str) {
|
fn process_keyword(
|
||||||
|
info: &DebugInfo,
|
||||||
|
keyword: Keyword,
|
||||||
|
scope: &mut Scope,
|
||||||
|
operands: &mut Vec<Prim>,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) -> Result<(), ()> {
|
||||||
match keyword {
|
match keyword {
|
||||||
Keyword::If | Keyword::While => {
|
Keyword::If | Keyword::While => {
|
||||||
if operands.len() != 1 {
|
if operands.len() != 1 {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR53, format!("got {:?} values", operands.len()) ));
|
diagnostics.set_err(
|
||||||
panic!();
|
info,
|
||||||
|
crate::msg::ERR53,
|
||||||
|
format!("got {:?} values", operands.len()),
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(operand) = operands.pop() {
|
if let Some(operand) = operands.pop() {
|
||||||
match operand {
|
match operand {
|
||||||
Prim::Bool => (),
|
Prim::Bool => (),
|
||||||
_ => {
|
_ => {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR53, format!("got {:?}", operand) ));
|
diagnostics.set_err(info, crate::msg::ERR53, format!("got {:?}", operand));
|
||||||
panic!();
|
return Err(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Keyword::Return => {
|
Keyword::Return => {
|
||||||
if scope.func_return_typ.is_some() {
|
if scope.func_return_typ.is_some() {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR54, "perhaps use `yield`" ));
|
diagnostics.set_err(info, crate::msg::ERR54, "perhaps use `yield`");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keyword::Yield => {
|
Keyword::Yield => {
|
||||||
if operands.len() != 1 {
|
if operands.len() != 1 {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR55, format!("got {:?} instead of 1", operands.len()) ));
|
diagnostics.set_err(
|
||||||
panic!();
|
info,
|
||||||
|
crate::msg::ERR55,
|
||||||
|
format!("got {:?} instead of 1", operands.len()),
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(operand) = operands.pop() {
|
if let Some(operand) = operands.pop() {
|
||||||
if let Some(typ) = scope.func_return_typ {
|
if let Some(typ) = scope.func_return_typ {
|
||||||
if typ != operand {
|
if typ != operand {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR59, format!("expected {:?} got {:?}", typ, operand) ));
|
diagnostics.set_err(
|
||||||
panic!();
|
info,
|
||||||
|
crate::msg::ERR59,
|
||||||
|
format!("expected {:?} got {:?}", typ, operand),
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
}
|
}
|
||||||
println!("{}", scope.cond_count);
|
|
||||||
scope.yields = scope.cond_count == 1;
|
scope.yields = scope.cond_count == 1;
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR57));
|
diagnostics.set_err(info, crate::msg::ERR57, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR58));
|
diagnostics.set_err(info, crate::msg::ERR58, "");
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collapse_operation(operation: &mut Token, declrs: &Vec<Declr>, scope: &mut Scope, operands: &mut Vec<Prim>, source: &str) {
|
fn collapse_operation(
|
||||||
|
operation: &mut Token,
|
||||||
|
declrs: &Vec<Declr>,
|
||||||
|
scope: &mut Scope,
|
||||||
|
operands: &mut Vec<Prim>,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) -> Result<(), ()> {
|
||||||
match operation {
|
match operation {
|
||||||
Token::Operator(op, dbginf) => op.operate(operands, &dbginf, source),
|
Token::Operator(op, dbginf) => op.operate(operands, &dbginf, diagnostics),
|
||||||
Token::Assign(name, mut typ, dbginf) => {
|
Token::Assign(name, mut typ, dbginf) => {
|
||||||
check_var_typ(&mut typ, operands, &dbginf, source);
|
check_var_typ(&mut typ, operands, &dbginf, diagnostics)?;
|
||||||
scope.decl_var((*name).to_owned(), typ);
|
scope.decl_var((*name).to_owned(), typ);
|
||||||
},
|
|
||||||
Token::Func(name, dbginf) => call_func(name, declrs, scope, operands, &dbginf, source),
|
|
||||||
Token::Keyword(keyword, dbginf) => process_keyword(*keyword, declrs, scope, operands, &dbginf, source),
|
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
|
Token::Func(name, dbginf) => call_func(name, declrs, scope, operands, &dbginf, diagnostics),
|
||||||
|
Token::Keyword(keyword, dbginf) => {
|
||||||
|
process_keyword(dbginf, *keyword, scope, operands, diagnostics)?
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_func(name: &str, declrs: &Vec<Declr>, _: &mut Scope, operands: &mut Vec<Prim>, dbginf: &crate::token::DebugInfo, source: &str) {
|
fn call_func(
|
||||||
|
name: &str,
|
||||||
|
declrs: &Vec<Declr>,
|
||||||
|
_: &mut Scope,
|
||||||
|
operands: &mut Vec<Prim>,
|
||||||
|
dbginf: &crate::token::DebugInfo,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) {
|
||||||
for declr in declrs {
|
for declr in declrs {
|
||||||
if declr.name.is_some() && declr.name.unwrap() == name {
|
if declr.name.is_some() && declr.name.unwrap() == name {
|
||||||
|
|
||||||
if let Some(args) = &declr.args {
|
if let Some(args) = &declr.args {
|
||||||
|
|
||||||
if args.len() > operands.len() {
|
if args.len() > operands.len() {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR60, format!("expected {:?} got {:?}", args.len(), operands.len()) ));
|
/*
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
dbginf.make_msg_w_ext(
|
||||||
|
crate::msg::ERR60,
|
||||||
|
format!("expected {:?} got {:?}", args.len(), operands.len())
|
||||||
|
)
|
||||||
|
);*/
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +473,14 @@ fn call_func(name: &str, declrs: &Vec<Declr>, _: &mut Scope, operands: &mut Vec<
|
||||||
let operand = operands.first().unwrap();
|
let operand = operands.first().unwrap();
|
||||||
|
|
||||||
if !operand.is_equal(arg.1) {
|
if !operand.is_equal(arg.1) {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR61, format!("expected {:?} got {:?}", arg, operand) ));
|
/*
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
dbginf.make_msg_w_ext(
|
||||||
|
crate::msg::ERR61,
|
||||||
|
format!("expected {:?} got {:?}", arg, operand)
|
||||||
|
)
|
||||||
|
);*/
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,19 +492,23 @@ fn call_func(name: &str, declrs: &Vec<Declr>, _: &mut Scope, operands: &mut Vec<
|
||||||
operands.push(typ);
|
operands.push(typ);
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// parse a single term using a modified shunting yard
|
/// parse a single term using a modified shunting yard
|
||||||
fn parse_term<'a>(term: &mut VecDeque<Token<'a>>, declrs: &Vec<Declr<'a>>, scope: &mut Scope, source: & str) {
|
fn parse_term<'a>(
|
||||||
|
term: &mut VecDeque<Token<'a>>,
|
||||||
|
declrs: &Vec<Declr<'a>>,
|
||||||
|
scope: &mut Scope,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) {
|
||||||
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:
|
'outer: while let Some(token) = term.pop_front() {
|
||||||
while let Some(token) = term.pop_front() {
|
|
||||||
match &token {
|
match &token {
|
||||||
Token::Word(text, dbginf) => {
|
Token::Word(text, dbginf) => {
|
||||||
if is_func(declrs, text) {
|
if is_func(declrs, text) {
|
||||||
|
@ -441,102 +523,130 @@ fn parse_term<'a>(term: &mut VecDeque<Token<'a>>, declrs: &Vec<Declr<'a>>, scope
|
||||||
output.push_back(Token::Var(text, *dbginf));
|
output.push_back(Token::Var(text, *dbginf));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR62));
|
//println!("{}", dbginf.make_msg(crate::msg::ERR62));
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
Token::Bool(_, _) => {
|
Token::Bool(_, _) => {
|
||||||
output.push_back(token);
|
output.push_back(token);
|
||||||
value_stack.push(Prim::Bool)
|
value_stack.push(Prim::Bool)
|
||||||
},
|
}
|
||||||
Token::Number(_, hint, _) => {
|
Token::Number(_, hint, _) => {
|
||||||
output.push_back(token.clone());
|
output.push_back(token.clone());
|
||||||
value_stack.push(Prim::UntypedNum(*hint))
|
value_stack.push(Prim::Num(*hint))
|
||||||
},
|
}
|
||||||
Token::Assign(_, _, _) => {
|
Token::Assign(_, _, _) => {
|
||||||
op_stack.push(token);
|
op_stack.push(token);
|
||||||
},
|
}
|
||||||
Token::Keyword(_, _) => op_stack.push(token),
|
Token::Keyword(_, _) => op_stack.push(token),
|
||||||
|
|
||||||
Token::Delemiter(char, dbginf) => {
|
Token::Delemiter(char, dbginf) => match 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() {
|
||||||
match &token {
|
match &token {
|
||||||
Token::Delemiter(char, _) => if *char == '(' {
|
Token::Delemiter(char, _) => {
|
||||||
|
if *char == '(' {
|
||||||
if let Some(next) = op_stack.last() {
|
if let Some(next) = op_stack.last() {
|
||||||
match &next {
|
match &next {
|
||||||
Token::Func(_, _) => {
|
Token::Func(_, _) => {
|
||||||
let mut token = op_stack.pop().unwrap();
|
let mut token = op_stack.pop().unwrap();
|
||||||
collapse_operation(&mut token, declrs, scope, &mut value_stack, source);
|
collapse_operation(
|
||||||
|
&mut token,
|
||||||
|
declrs,
|
||||||
|
scope,
|
||||||
|
&mut value_stack,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
output.push_back(token);
|
output.push_back(token);
|
||||||
},
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
},
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
collapse_operation(&mut token, declrs, scope, &mut value_stack, source);
|
collapse_operation(
|
||||||
|
&mut token,
|
||||||
|
declrs,
|
||||||
|
scope,
|
||||||
|
&mut value_stack,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
output.push_back(token)
|
output.push_back(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR64));
|
//println!("{}", dbginf.make_msg(crate::msg::ERR64));
|
||||||
panic!();
|
panic!();
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR65));
|
//println!("{}", dbginf.make_msg(crate::msg::ERR65));
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
Token::Operator(op, _) => {
|
Token::Operator(op, _) => {
|
||||||
let prec0 = op.prec();
|
let prec0 = op.prec();
|
||||||
while let Some(mut top) = op_stack.last_mut(){
|
while let Some(mut top) = op_stack.last_mut() {
|
||||||
match &top {
|
match &top {
|
||||||
Token::Operator(op1, _) => {
|
Token::Operator(op1, _) => {
|
||||||
let prec1 = op1.prec();
|
let prec1 = op1.prec();
|
||||||
|
|
||||||
if prec1 > prec0 || prec0 == prec1 && op.assoc() == Assoc::Left {
|
if prec1 > prec0 || prec0 == prec1 && op.assoc() == Assoc::Left {
|
||||||
collapse_operation(&mut top, declrs, scope, &mut value_stack, source);
|
collapse_operation(
|
||||||
|
&mut top,
|
||||||
|
declrs,
|
||||||
|
scope,
|
||||||
|
&mut value_stack,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
output.push_back(op_stack.pop().unwrap());
|
output.push_back(op_stack.pop().unwrap());
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
break
|
break;
|
||||||
},
|
}
|
||||||
_ => break
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
op_stack.push(token);
|
op_stack.push(token);
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(mut token) = op_stack.pop() {
|
while let Some(mut token) = op_stack.pop() {
|
||||||
match &token {
|
match &token {
|
||||||
Token::Delemiter(char, dbginf) => if *char == '(' {
|
Token::Delemiter(char, dbginf) => {
|
||||||
println!("{}", dbginf.make_msg(crate::msg::ERR63));
|
if *char == '(' {
|
||||||
},
|
//println!("{}", dbginf.make_msg(crate::msg::ERR63));
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
collapse_operation(&mut token, declrs, scope, &mut value_stack, source);
|
collapse_operation(&mut token, declrs, scope, &mut value_stack, diagnostics);
|
||||||
output.push_back(token)
|
output.push_back(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if value_stack.len() > 1 {
|
if value_stack.len() > 1 {
|
||||||
println!("{}", output[0].create_msg(crate::msg::ERR50));
|
diagnostics.set_err(&output[0], crate::msg::ERR50, "");
|
||||||
panic!();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.expr_yield = value_stack.len() == 1;
|
scope.expr_yield = value_stack.len() == 1;
|
||||||
if scope.expr_yield {
|
if scope.expr_yield {
|
||||||
let yielded = value_stack.pop().unwrap();
|
let yielded = value_stack.pop().unwrap();
|
||||||
if !yielded.is_equal(scope.func_return_typ.unwrap()) {
|
if !yielded.is_equal(scope.func_return_typ.unwrap()) {
|
||||||
println!("{}", output[0].create_msg_w_ext(crate::msg::ERR59, format!("expected: {:?} got {:?}", scope.func_return_typ.unwrap(), yielded) ));
|
diagnostics.set_err(
|
||||||
|
&output[0],
|
||||||
|
crate::msg::ERR59,
|
||||||
|
format!(
|
||||||
|
"expected {:?} got {:?}",
|
||||||
|
scope.func_return_typ.unwrap(),
|
||||||
|
yielded
|
||||||
|
),
|
||||||
|
);
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,20 +663,29 @@ fn is_func(declrs: &[Declr], text: &str) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block<'a>(block: &mut Block<'a>, declrs: &Vec<Declr<'a>>, scope: &mut Scope, source: &str) {
|
fn parse_block<'a>(
|
||||||
|
block: &mut Block<'a>,
|
||||||
|
declrs: &Vec<Declr<'a>>,
|
||||||
|
scope: &mut Scope,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) {
|
||||||
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, source),
|
Expr::Block(block) => parse_block(block, declrs, scope, diagnostics),
|
||||||
Expr::Term(term) => parse_term(term, declrs, scope, source)
|
Expr::Term(term) => parse_term(term, declrs, scope, diagnostics),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope.pop_scope();
|
scope.pop_scope();
|
||||||
scope.cond_count -= 1;
|
scope.cond_count -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_exprs<'a>(funcs: &mut Vec<Func<'a>>, declrs: &Vec<Declr<'a>>, source: &'a str) {
|
fn parse_exprs<'a>(
|
||||||
|
funcs: &mut Vec<Func<'a>>,
|
||||||
|
declrs: &Vec<Declr<'a>>,
|
||||||
|
diagnostics: &mut data::Diagnostics,
|
||||||
|
) {
|
||||||
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() {
|
||||||
|
@ -577,14 +696,14 @@ fn parse_exprs<'a>(funcs: &mut Vec<Func<'a>>, declrs: &Vec<Declr<'a>>, source: &
|
||||||
scope.yields = false;
|
scope.yields = false;
|
||||||
scope.cond_count = 0;
|
scope.cond_count = 0;
|
||||||
|
|
||||||
parse_block(block, declrs, &mut scope, source);
|
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]));
|
//token.create_msg_w_ext(crate::msg::ERR56, format!("at function {}", declrs[x]));
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => panic!("Fatal-Compilier-Error: function must have a block")
|
_ => panic!("Fatal-Compilier-Error: function must have a block"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,14 +711,16 @@ fn parse_exprs<'a>(funcs: &mut Vec<Func<'a>>, declrs: &Vec<Declr<'a>>, source: &
|
||||||
/// 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) -> Vec<Func<'a>> {
|
pub fn parse<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &'a str) -> Diagnostics<'a> {
|
||||||
let (mut funcs, declrs) = discover_functions(tokens, source);
|
let mut dias = data::Diagnostics::new(source);
|
||||||
|
|
||||||
|
if let Ok((mut funcs, declrs)) = discover_functions(tokens, &mut dias) {
|
||||||
// make all of this shit return a mutable diagnostics struct.
|
// make all of this shit return a mutable diagnostics struct.
|
||||||
discover_exprs(&mut funcs, &declrs, source);
|
discover_exprs(&mut funcs, &declrs, &mut dias);
|
||||||
parse_exprs(&mut funcs, &declrs, source);
|
parse_exprs(&mut funcs, &declrs, &mut dias);
|
||||||
|
|
||||||
crate::inter::convert_to_erpn(&mut funcs, &declrs);
|
crate::inter::convert_to_erpn(&mut funcs, &declrs);
|
||||||
|
}
|
||||||
|
|
||||||
funcs
|
dias
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,200 @@
|
||||||
|
|
||||||
use crate::token::DebugMsg;
|
use crate::token::DebugMsg;
|
||||||
use crate::token::MessageType::Error;
|
use crate::token::MessageType::Error;
|
||||||
use crate::token::MessageType::Warning;
|
|
||||||
use crate::token::MessageType::Info;
|
use crate::token::MessageType::Info;
|
||||||
|
use crate::token::MessageType::Warning;
|
||||||
|
|
||||||
pub const ERR10: &DebugMsg = &DebugMsg { typ: Error, code: 10, msg: "Function defined multiple times" };
|
pub const ERR10: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR11: &DebugMsg = &DebugMsg { typ: Error, code: 11, msg: "Function missing return type" };
|
typ: Error,
|
||||||
pub const ERR12: &DebugMsg = &DebugMsg { typ: Error, code: 12, msg: "Function missing name" };
|
code: 10,
|
||||||
pub const ERR13: &DebugMsg = &DebugMsg { typ: Error, code: 13, msg: "Open parameter list" };
|
msg: "Function defined multiple times",
|
||||||
pub const ERR14: &DebugMsg = &DebugMsg { typ: Error, code: 14, msg: "Closed non existant function body" };
|
};
|
||||||
pub const ERR15: &DebugMsg = &DebugMsg { typ: Error, code: 15, msg: "Open function body" };
|
pub const ERR11: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR16: &DebugMsg = &DebugMsg { typ: Error, code: 16, msg: "Missing assign for return type" };
|
typ: Error,
|
||||||
pub const ERR17: &DebugMsg = &DebugMsg { typ: Error, code: 17, msg: "Double function assign" };
|
code: 11,
|
||||||
pub const ERR18: &DebugMsg = &DebugMsg { typ: Error, code: 18, msg: "Function has multiple names" };
|
msg: "Function missing return type",
|
||||||
pub const ERR19: &DebugMsg = &DebugMsg { typ: Error, code: 19, msg: "Multiple parameter lists" };
|
};
|
||||||
pub const ERR20: &DebugMsg = &DebugMsg { typ: Error, code: 20, msg: "not a valid parameter" };
|
pub const ERR12: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR21: &DebugMsg = &DebugMsg { typ: Error, code: 21, msg: "type declaration missing for parameter" };
|
typ: Error,
|
||||||
pub const ERR22: &DebugMsg = &DebugMsg { typ: Error, code: 22, msg: "token outside of function definition" };
|
code: 12,
|
||||||
pub const ERR23: &DebugMsg = &DebugMsg { typ: Error, code: 23, msg: "token must be declaration" };
|
msg: "Function missing name",
|
||||||
|
};
|
||||||
|
pub const ERR13: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 13,
|
||||||
|
msg: "Open parameter list",
|
||||||
|
};
|
||||||
|
pub const ERR14: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 14,
|
||||||
|
msg: "Closed non existant function body",
|
||||||
|
};
|
||||||
|
pub const ERR15: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 15,
|
||||||
|
msg: "Open function body",
|
||||||
|
};
|
||||||
|
pub const ERR16: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 16,
|
||||||
|
msg: "Missing assign for return type",
|
||||||
|
};
|
||||||
|
pub const ERR17: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 17,
|
||||||
|
msg: "Double function assign",
|
||||||
|
};
|
||||||
|
pub const ERR18: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 18,
|
||||||
|
msg: "Function has multiple names",
|
||||||
|
};
|
||||||
|
pub const ERR19: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 19,
|
||||||
|
msg: "Multiple parameter lists",
|
||||||
|
};
|
||||||
|
pub const ERR20: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 20,
|
||||||
|
msg: "not a valid parameter",
|
||||||
|
};
|
||||||
|
pub const ERR21: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 21,
|
||||||
|
msg: "type declaration missing for parameter",
|
||||||
|
};
|
||||||
|
pub const ERR22: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 22,
|
||||||
|
msg: "token outside of function definition",
|
||||||
|
};
|
||||||
|
pub const ERR23: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 23,
|
||||||
|
msg: "token must be declaration",
|
||||||
|
};
|
||||||
|
|
||||||
pub const ERR40: &DebugMsg = &DebugMsg { typ: Error, code: 40, msg: "Open block" };
|
pub const ERR40: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR41: &DebugMsg = &DebugMsg { typ: Error, code: 41, msg: "Closed non existant block" };
|
typ: Error,
|
||||||
|
code: 40,
|
||||||
|
msg: "Open block",
|
||||||
|
};
|
||||||
|
pub const ERR41: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 41,
|
||||||
|
msg: "Closed non existant block",
|
||||||
|
};
|
||||||
|
|
||||||
pub const INF51: &DebugMsg = &DebugMsg { typ: Info, code: 51, msg: "No variable type provided" };
|
pub const INF51: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Info,
|
||||||
|
code: 51,
|
||||||
|
msg: "No variable type provided",
|
||||||
|
};
|
||||||
|
|
||||||
pub const ERR50: &DebugMsg = &DebugMsg { typ: Error, code: 50, msg: "Expression has multiple values" };
|
pub const ERR50: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR51: &DebugMsg = &DebugMsg { typ: Error, code: 51, msg: "Missmatched variable types" };
|
typ: Error,
|
||||||
pub const ERR52: &DebugMsg = &DebugMsg { typ: Error, code: 52, msg: "Unable to assign variable type" };
|
code: 50,
|
||||||
pub const ERR53: &DebugMsg = &DebugMsg { typ: Error, code: 53, msg: "Expected single boolean value" };
|
msg: "Expression has multiple values",
|
||||||
pub const ERR54: &DebugMsg = &DebugMsg { typ: Error, code: 54, msg: "Cannot return from function without result" };
|
};
|
||||||
pub const ERR55: &DebugMsg = &DebugMsg { typ: Error, code: 55, msg: "Expected single value" };
|
pub const ERR51: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR56: &DebugMsg = &DebugMsg { typ: Error, code: 56, msg: "Function missing return value" };
|
typ: Error,
|
||||||
pub const ERR57: &DebugMsg = &DebugMsg { typ: Error, code: 57, msg: "Function does not return anything" };
|
code: 51,
|
||||||
pub const ERR58: &DebugMsg = &DebugMsg { typ: Error, code: 58, msg: "Yield must return a value" };
|
msg: "Missmatched variable types",
|
||||||
pub const ERR59: &DebugMsg = &DebugMsg { typ: Error, code: 59, msg: "Missmatched function return type" };
|
};
|
||||||
|
pub const ERR52: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 52,
|
||||||
|
msg: "Unable to assign variable type",
|
||||||
|
};
|
||||||
|
pub const ERR53: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 53,
|
||||||
|
msg: "Expected single boolean value",
|
||||||
|
};
|
||||||
|
pub const ERR54: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 54,
|
||||||
|
msg: "Cannot return from function without result",
|
||||||
|
};
|
||||||
|
pub const ERR55: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 55,
|
||||||
|
msg: "Expected single value",
|
||||||
|
};
|
||||||
|
pub const ERR56: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 56,
|
||||||
|
msg: "Function missing return value",
|
||||||
|
};
|
||||||
|
pub const ERR57: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 57,
|
||||||
|
msg: "Function does not return anything",
|
||||||
|
};
|
||||||
|
pub const ERR58: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 58,
|
||||||
|
msg: "Yield must return a value",
|
||||||
|
};
|
||||||
|
pub const ERR59: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 59,
|
||||||
|
msg: "Missmatched function return type",
|
||||||
|
};
|
||||||
|
|
||||||
pub const ERR60: &DebugMsg = &DebugMsg { typ: Error, code: 60, msg: "Missmatched parameter count" };
|
pub const ERR60: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR61: &DebugMsg = &DebugMsg { typ: Error, code: 61, msg: "Missmatched parameter type" };
|
typ: Error,
|
||||||
pub const ERR62: &DebugMsg = &DebugMsg { typ: Error, code: 62, msg: "Unknown symbol" };
|
code: 60,
|
||||||
pub const ERR63: &DebugMsg = &DebugMsg { typ: Error, code: 63, msg: "Missing left parenthesis" };
|
msg: "Missmatched parameter count",
|
||||||
pub const ERR64: &DebugMsg = &DebugMsg { typ: Error, code: 64, msg: "Missing right parenthesis" };
|
};
|
||||||
pub const ERR65: &DebugMsg = &DebugMsg { typ: Error, code: 65, msg: "Missplaced character" };
|
pub const ERR61: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
pub const ERR70: &DebugMsg = &DebugMsg { typ: Error, code: 70, msg: "Unknown type declaration"};
|
code: 61,
|
||||||
pub const ERR71: &DebugMsg = &DebugMsg { typ: Error, code: 71, msg: "Unable to identify characters as token"};
|
msg: "Missmatched parameter type",
|
||||||
pub const ERR72: &DebugMsg = &DebugMsg { typ: Error, code: 72, msg: "Unknown operator"};
|
};
|
||||||
pub const ERR73: &DebugMsg = &DebugMsg { typ: Error, code: 73, msg: "Missmatched types for operation"};
|
pub const ERR62: &DebugMsg = &DebugMsg {
|
||||||
pub const ERR74: &DebugMsg = &DebugMsg { typ: Error, code: 74, msg: "Missing operands"};
|
typ: Error,
|
||||||
|
code: 62,
|
||||||
|
msg: "Unknown symbol",
|
||||||
|
};
|
||||||
|
pub const ERR63: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 63,
|
||||||
|
msg: "Missing left parenthesis",
|
||||||
|
};
|
||||||
|
pub const ERR64: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 64,
|
||||||
|
msg: "Missing right parenthesis",
|
||||||
|
};
|
||||||
|
pub const ERR65: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 65,
|
||||||
|
msg: "Missplaced character",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ERR70: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 70,
|
||||||
|
msg: "Unknown type declaration",
|
||||||
|
};
|
||||||
|
pub const ERR71: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 71,
|
||||||
|
msg: "Unable to identify characters as token",
|
||||||
|
};
|
||||||
|
pub const ERR72: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 72,
|
||||||
|
msg: "Unknown operator",
|
||||||
|
};
|
||||||
|
pub const ERR73: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 73,
|
||||||
|
msg: "Missmatched types for operation",
|
||||||
|
};
|
||||||
|
pub const ERR74: &DebugMsg = &DebugMsg {
|
||||||
|
typ: Error,
|
||||||
|
code: 74,
|
||||||
|
msg: "Missing operands",
|
||||||
|
};
|
||||||
|
|
402
src/token/mod.rs
402
src/token/mod.rs
|
@ -1,12 +1,14 @@
|
||||||
|
use colored::{ColoredString, Colorize};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use colored::{Colorize, ColoredString};
|
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
|
// bitwise boolean operations
|
||||||
Or,
|
Or,
|
||||||
And,
|
And,
|
||||||
Xor,
|
Xor,
|
||||||
|
|
||||||
|
// comparisons
|
||||||
Eq,
|
Eq,
|
||||||
Lt,
|
Lt,
|
||||||
Gt,
|
Gt,
|
||||||
|
@ -14,20 +16,48 @@ pub enum Operator {
|
||||||
LtEq,
|
LtEq,
|
||||||
NotEq,
|
NotEq,
|
||||||
|
|
||||||
|
// arithmetic
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
Mul,
|
Mul,
|
||||||
Div,
|
Div,
|
||||||
|
|
||||||
Assign
|
Assign,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum Assoc {
|
pub enum Assoc {
|
||||||
Right,
|
Right,
|
||||||
Left
|
Left,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ARITHMETIC_TYPES: &'static [(&[Prim], Prim)] = &[
|
||||||
|
(&[Prim::Int, Prim::Int], Prim::Int),
|
||||||
|
(&[Prim::Rat, Prim::Rat], Prim::Rat),
|
||||||
|
(&[Prim::Num(NumHint::Int), Prim::Int], Prim::Int),
|
||||||
|
(&[Prim::Num(NumHint::Int), Prim::Rat], Prim::Rat),
|
||||||
|
(&[Prim::Num(NumHint::Rat), Prim::Rat], Prim::Rat),
|
||||||
|
(&[Prim::Int, Prim::Num(NumHint::Int)], Prim::Int),
|
||||||
|
(&[Prim::Rat, Prim::Num(NumHint::Rat)], Prim::Rat),
|
||||||
|
(&[Prim::Rat, Prim::Num(NumHint::Int)], Prim::Rat),
|
||||||
|
(
|
||||||
|
&[Prim::Num(NumHint::Rat), Prim::Num(NumHint::Rat)],
|
||||||
|
Prim::Rat,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
&[Prim::Num(NumHint::Int), Prim::Num(NumHint::Rat)],
|
||||||
|
Prim::Rat,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
&[Prim::Num(NumHint::Rat), Prim::Num(NumHint::Int)],
|
||||||
|
Prim::Rat,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
&[Prim::Num(NumHint::Int), Prim::Num(NumHint::Int)],
|
||||||
|
Prim::Int,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
impl Operator {
|
impl Operator {
|
||||||
pub fn parse<'a>(str: &'a str) -> Self {
|
pub fn parse<'a>(str: &'a str) -> Self {
|
||||||
return match str {
|
return match str {
|
||||||
|
@ -48,7 +78,10 @@ impl Operator {
|
||||||
"/" => Operator::Div,
|
"/" => Operator::Div,
|
||||||
"=" => Operator::Assign,
|
"=" => Operator::Assign,
|
||||||
|
|
||||||
_ => panic!("Unspecified operator")
|
_ => {
|
||||||
|
crate::message(MessageType::Critical, "Unknown operator");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +90,7 @@ impl Operator {
|
||||||
Operator::Eq => 2,
|
Operator::Eq => 2,
|
||||||
Operator::Lt => 2,
|
Operator::Lt => 2,
|
||||||
Operator::Gt => 2,
|
Operator::Gt => 2,
|
||||||
|
Operator::NotEq => 2,
|
||||||
Operator::LtEq => 2,
|
Operator::LtEq => 2,
|
||||||
Operator::GtEq => 2,
|
Operator::GtEq => 2,
|
||||||
|
|
||||||
|
@ -66,113 +100,152 @@ impl Operator {
|
||||||
|
|
||||||
Operator::Add => 3,
|
Operator::Add => 3,
|
||||||
Operator::Sub => 3,
|
Operator::Sub => 3,
|
||||||
|
|
||||||
Operator::Mul => 4,
|
Operator::Mul => 4,
|
||||||
Operator::Div => 4,
|
Operator::Div => 4,
|
||||||
|
|
||||||
_ => 0
|
Operator::Assign => 0,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assoc(&self) -> Assoc {
|
pub fn assoc(&self) -> Assoc {
|
||||||
match self {
|
match self {
|
||||||
_ => Assoc::Right
|
_ => Assoc::Right,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn present_types(operands: &[Prim], types: &[Prim], r#yield: Prim, dbginf: &DebugInfo, source: &str) -> Option<Prim> {
|
fn present_types(
|
||||||
|
operands: &[Prim],
|
||||||
|
types: &[Prim],
|
||||||
|
r#yield: Prim,
|
||||||
|
dbginf: &DebugInfo,
|
||||||
|
diagnostics: &mut crate::parser::data::Diagnostics,
|
||||||
|
) -> Option<Prim> {
|
||||||
if operands.len() < types.len() {
|
if operands.len() < types.len() {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR74, format!("required {} got {}", types.len() - operands.len(), operands.len())));
|
/*
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
dbginf.make_msg_w_ext(
|
||||||
|
crate::msg::ERR74,
|
||||||
|
format!(
|
||||||
|
"required {} got {}",
|
||||||
|
types.len() - operands.len(),
|
||||||
|
operands.len()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);*/
|
||||||
panic!()
|
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 None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(r#yield)
|
Some(r#yield)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_types(operands: &[Prim], types: &[(Vec<Prim>, Prim)], dbginf: &DebugInfo, source: &str) -> Option<Prim> {
|
fn check_types(
|
||||||
|
operands: &[Prim],
|
||||||
|
types: &[(&[Prim], Prim)],
|
||||||
|
dbginf: &DebugInfo,
|
||||||
|
diagnostics: &mut crate::parser::data::Diagnostics,
|
||||||
|
) -> 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, source) {
|
Self::present_types(operands, combination.0, combination.1, dbginf, diagnostics)
|
||||||
|
{
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn operate(&self, operands: &mut Vec<Prim>, dbginf: &DebugInfo, source: &str) {
|
pub fn operate(
|
||||||
|
&self,
|
||||||
|
operands: &mut Vec<Prim>,
|
||||||
|
dbginf: &DebugInfo,
|
||||||
|
diagnostics: &mut crate::parser::data::Diagnostics,
|
||||||
|
) {
|
||||||
match self {
|
match self {
|
||||||
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div=> {
|
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div => {
|
||||||
let types_valid = Self::check_types(operands, &[
|
let types_valid =
|
||||||
// +------------------------------------------------------------------------------------+---------------------------------+
|
Self::check_types(operands, ARITHMETIC_TYPES, dbginf, diagnostics);
|
||||||
// | Parameter list of types | result type |
|
|
||||||
// +------------------------------------------------------------------------------------+---------------------------------+
|
|
||||||
(vec![Prim::Int, Prim::Int ], Prim::Int),
|
|
||||||
(vec![Prim::Rat, Prim::Rat ], Prim::Rat),
|
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Int ], Prim::Int),
|
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Rat ], Prim::Rat),
|
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::Rat ], Prim::Rat),
|
|
||||||
(vec![Prim::Int, Prim::UntypedNum(NumberClassHint::Int)], Prim::Int),
|
|
||||||
(vec![Prim::Rat, Prim::UntypedNum(NumberClassHint::Rat)], Prim::Rat),
|
|
||||||
(vec![Prim::Rat, Prim::UntypedNum(NumberClassHint::Int)], Prim::Rat),
|
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::UntypedNum(NumberClassHint::Rat)], Prim::Rat),
|
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::UntypedNum(NumberClassHint::Rat)], Prim::Rat),
|
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::UntypedNum(NumberClassHint::Int)], Prim::Rat),
|
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::UntypedNum(NumberClassHint::Int)], Prim::Int)
|
|
||||||
], dbginf, source);
|
|
||||||
|
|
||||||
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);
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two numbers"));
|
/*
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two numbers")
|
||||||
|
);*/
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Operator::And | Operator::Or | Operator::Xor => {
|
Operator::And | Operator::Or | Operator::Xor => {
|
||||||
let types_valid = Self::check_types(operands, &[
|
let types_valid = Self::check_types(
|
||||||
(vec![Prim::Bool, Prim::Bool ], Prim::Bool),
|
operands,
|
||||||
], dbginf, source);
|
&[(&[Prim::Bool, Prim::Bool], Prim::Bool)],
|
||||||
|
dbginf,
|
||||||
|
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);
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two booleans"));
|
/*
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two booleans")
|
||||||
|
);*/
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Operator::Eq | Operator::NotEq | Operator::Lt | Operator::Gt | Operator::GtEq | Operator::LtEq => {
|
Operator::Eq
|
||||||
let types_valid = Self::check_types(operands, &[
|
| Operator::NotEq
|
||||||
// +------------------------------------------------------------------------------------+---------------------------------+
|
| Operator::Lt
|
||||||
// | Parameter list of types | result type |
|
| Operator::Gt
|
||||||
// +------------------------------------------------------------------------------------+---------------------------------+
|
| Operator::GtEq
|
||||||
(vec![Prim::Int, Prim::Int ], Prim::Bool ),
|
| Operator::LtEq => {
|
||||||
(vec![Prim::Rat, Prim::Rat ], Prim::Bool ),
|
let types_valid = Self::check_types(
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Int ], Prim::Bool ),
|
operands,
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::Rat ], Prim::Bool ),
|
&[
|
||||||
(vec![Prim::Int, Prim::UntypedNum(NumberClassHint::Int)], Prim::Bool ),
|
(&[Prim::Int, Prim::Int], Prim::Bool),
|
||||||
(vec![Prim::Rat, Prim::UntypedNum(NumberClassHint::Rat)], Prim::Bool ),
|
(&[Prim::Rat, Prim::Rat], Prim::Bool),
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::UntypedNum(NumberClassHint::Rat)], Prim::Bool ),
|
(&[Prim::Num(NumHint::Int), Prim::Int], Prim::Bool),
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::UntypedNum(NumberClassHint::Int)], Prim::Bool )
|
(&[Prim::Num(NumHint::Rat), Prim::Rat], Prim::Bool),
|
||||||
], dbginf, source);
|
(&[Prim::Int, Prim::Num(NumHint::Int)], Prim::Bool),
|
||||||
|
(&[Prim::Rat, Prim::Num(NumHint::Rat)], Prim::Bool),
|
||||||
|
(
|
||||||
|
&[Prim::Num(NumHint::Rat), Prim::Num(NumHint::Rat)],
|
||||||
|
Prim::Bool,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
&[Prim::Num(NumHint::Int), Prim::Num(NumHint::Int)],
|
||||||
|
Prim::Bool,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
dbginf,
|
||||||
|
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);
|
||||||
} else {
|
} else {
|
||||||
println!("{}", dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two numbers"));
|
/*
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
dbginf.make_msg_w_ext(crate::msg::ERR73, "expected two numbers")
|
||||||
|
);*/
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Unknown operator");
|
panic!("Unknown operator");
|
||||||
}
|
}
|
||||||
|
@ -204,25 +277,30 @@ impl Keyword {
|
||||||
"ret" => Keyword::Return,
|
"ret" => Keyword::Return,
|
||||||
"yield" => Keyword::Yield,
|
"yield" => Keyword::Yield,
|
||||||
"please" => Keyword::Please,
|
"please" => Keyword::Please,
|
||||||
_ => panic!("Text not a known keyword {text}")
|
_ => {
|
||||||
|
crate::message(
|
||||||
|
MessageType::Critical,
|
||||||
|
format!("not a known keyword: {}", text),
|
||||||
|
);
|
||||||
|
panic!()
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
||||||
pub enum NumberClassHint {
|
pub enum NumHint {
|
||||||
Int,
|
Int,
|
||||||
Rat
|
Rat,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NumberClassHint {
|
impl NumHint {
|
||||||
|
pub fn from(str: &str) -> NumHint {
|
||||||
pub fn from(str: &str) -> NumberClassHint {
|
|
||||||
if str.parse::<i32>().is_err() {
|
if str.parse::<i32>().is_err() {
|
||||||
return NumberClassHint::Rat;
|
return NumHint::Rat;
|
||||||
}
|
}
|
||||||
|
|
||||||
NumberClassHint::Int
|
NumHint::Int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,45 +310,52 @@ pub enum Prim {
|
||||||
Int,
|
Int,
|
||||||
Rat,
|
Rat,
|
||||||
Bool,
|
Bool,
|
||||||
UntypedNum(NumberClassHint)
|
Num(NumHint),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Prim {
|
impl Prim {
|
||||||
fn from<'a>(text: &'a str, dbginf: &DebugInfo, source: &str) -> Prim {
|
fn from<'a>(text: &'a str, dbginf: &DebugInfo) -> Prim {
|
||||||
return match text {
|
return match text {
|
||||||
"int" => Prim::Int,
|
"int" => Prim::Int,
|
||||||
"rat" => Prim::Rat,
|
"rat" => Prim::Rat,
|
||||||
"bool" => Prim::Bool,
|
"bool" => Prim::Bool,
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
println!("{}", dbginf.make_msg(&crate::msg::ERR70));
|
//println!("{}", dbginf.make_msg(&crate::msg::ERR70));
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_equal(&self, value: Prim) -> bool {
|
pub fn is_equal(&self, value: Prim) -> bool {
|
||||||
return match self {
|
return match self {
|
||||||
Prim::Bool => *self == value,
|
Prim::Bool => *self == value,
|
||||||
Prim::Rat => return match value {
|
Prim::Rat => {
|
||||||
Prim::UntypedNum(NumberClassHint::Int) => true,
|
return match value {
|
||||||
Prim::UntypedNum(NumberClassHint::Rat) => true,
|
Prim::Num(NumHint::Int) => true,
|
||||||
|
Prim::Num(NumHint::Rat) => true,
|
||||||
_ => *self == value,
|
_ => *self == value,
|
||||||
},
|
}
|
||||||
Prim::Int => return match value {
|
}
|
||||||
Prim::UntypedNum(NumberClassHint::Int) => true,
|
Prim::Int => {
|
||||||
|
return match value {
|
||||||
|
Prim::Num(NumHint::Int) => true,
|
||||||
_ => *self == value,
|
_ => *self == value,
|
||||||
},
|
}
|
||||||
Prim::UntypedNum(NumberClassHint::Rat) => return match value {
|
}
|
||||||
|
Prim::Num(NumHint::Rat) => {
|
||||||
|
return match value {
|
||||||
Prim::Rat | Prim::Int => true,
|
Prim::Rat | Prim::Int => true,
|
||||||
_ => *self == value,
|
_ => *self == value,
|
||||||
},
|
}
|
||||||
Prim::UntypedNum(NumberClassHint::Int) => return match value {
|
}
|
||||||
|
Prim::Num(NumHint::Int) => {
|
||||||
|
return match value {
|
||||||
Prim::Int => true,
|
Prim::Int => true,
|
||||||
_ => *self == value,
|
_ => *self == value,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DebugMsg {
|
pub struct DebugMsg {
|
||||||
|
@ -279,65 +364,69 @@ pub struct DebugMsg {
|
||||||
pub msg: &'static str,
|
pub msg: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DebugErr<'a> {
|
pub struct DebugNotice<'a> {
|
||||||
info: DebugInfo<'a>,
|
pub info: DebugInfo,
|
||||||
/// generic error description
|
/// generic error description
|
||||||
msg: &'static DebugMsg,
|
pub msg: &'static DebugMsg,
|
||||||
/// extra message which is case specific
|
/// extra message which is case specific
|
||||||
ext: Option<String>,
|
pub ext: String,
|
||||||
|
pub source: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for DebugErr<'a> {
|
impl<'a> std::fmt::Display for DebugNotice<'a> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
// write header as:
|
// write header as:
|
||||||
// `Error (56) some syntax error message in line 5:`
|
// `Error (56) some syntax error message in line 5:`
|
||||||
f.write_fmt(format_args!("{} ({}) {} in line {}: {}\n",
|
f.write_fmt(format_args!(
|
||||||
|
"{} ({}) {} in line {}: {}\n",
|
||||||
self.msg.typ.to_colored(),
|
self.msg.typ.to_colored(),
|
||||||
self.msg.code,
|
self.msg.code,
|
||||||
self.msg.msg.bold().bright_white(),
|
self.msg.msg.bold().bright_white(),
|
||||||
self.info.line,
|
self.info.line,
|
||||||
self.ext.as_ref().unwrap_or(&String::new())
|
self.ext
|
||||||
));
|
));
|
||||||
// write additional information
|
// write additional information
|
||||||
f.write_fmt(format_args!("{}", self.info))
|
f.write_fmt(format_args!(
|
||||||
|
" somewhere in here:\n --> `{}`\n",
|
||||||
|
self.source
|
||||||
|
.lines()
|
||||||
|
.nth(self.info.line)
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.bold()
|
||||||
|
.bright_white()
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
(0..self.info.start + 6)
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|_| f.write_str(" ").unwrap());
|
||||||
|
(self.info.start..self.info.end)
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|_| f.write_str("^").unwrap());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub struct DebugInfo<'a> {
|
pub struct DebugInfo {
|
||||||
/// index in source string where the token begins in the current line
|
/// index in source string where the token begins in the current line
|
||||||
start: usize,
|
pub start: usize,
|
||||||
/// index in source string where the token ends in the current line
|
/// index in source string where the token ends in the current line
|
||||||
end: usize,
|
pub end: usize,
|
||||||
/// line number where the line in which the token is begins
|
/// line number where the line in which the token is begins
|
||||||
line: usize,
|
pub line: usize,
|
||||||
|
|
||||||
source: &'a str
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DebugInfo<'a> {
|
|
||||||
pub fn make_msg(&self, msg: &'static DebugMsg) -> DebugErr {
|
|
||||||
DebugErr {
|
|
||||||
info: self.clone(),
|
|
||||||
msg,
|
|
||||||
ext: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_msg_w_ext<T>(&self, msg: &'static DebugMsg, ext: T) -> DebugErr where T: Into<String> {
|
|
||||||
DebugErr {
|
|
||||||
info: self.clone(),
|
|
||||||
msg,
|
|
||||||
ext: Some(ext.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum MessageType {
|
pub enum MessageType {
|
||||||
|
/// For internal compiler critical error
|
||||||
|
Critical,
|
||||||
|
/// compile errors that won't allow for further compilation
|
||||||
Error,
|
Error,
|
||||||
Warning,
|
Warning,
|
||||||
Info
|
Info,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageType {
|
impl MessageType {
|
||||||
|
@ -348,21 +437,16 @@ impl MessageType {
|
||||||
pub fn to_colored(&self) -> ColoredString {
|
pub fn to_colored(&self) -> ColoredString {
|
||||||
let raw = format!("{:#?}", self);
|
let raw = format!("{:#?}", self);
|
||||||
return match self {
|
return match self {
|
||||||
|
MessageType::Critical => raw.on_red().bold(),
|
||||||
MessageType::Error => raw.red().bold(),
|
MessageType::Error => raw.red().bold(),
|
||||||
MessageType::Warning => raw.yellow().bold(),
|
MessageType::Warning => raw.yellow().bold(),
|
||||||
MessageType::Info => raw.blue().bold()
|
MessageType::Info => raw.blue().bold(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for DebugInfo<'a> {
|
impl std::fmt::Display for DebugInfo {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.write_fmt(format_args!(" somewhere in here:\n --> `{}`\n",
|
|
||||||
self.source.lines().nth(self.line).unwrap().trim().bold().bright_white())).unwrap();
|
|
||||||
|
|
||||||
(0..self.start + 6).into_iter().for_each(|_| f.write_str(" ").unwrap());
|
|
||||||
(self.start..self.end).into_iter().for_each(|_| f.write_str("^").unwrap());
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,27 +456,27 @@ impl<'a> std::fmt::Display for DebugInfo<'a> {
|
||||||
/// They give a meaning to patterns of chars allowing to interpret them.
|
/// They give a meaning to patterns of chars allowing to interpret them.
|
||||||
pub enum Token<'a> {
|
pub enum Token<'a> {
|
||||||
// base tokens that can simply be split to from raw source code
|
// base tokens that can simply be split to from raw source code
|
||||||
Word(&'a str, DebugInfo<'a>),
|
Word(&'a str, DebugInfo),
|
||||||
/// Single symbol delemiter like ```(```,```}```
|
/// Single symbol delemiter like ```(```,```}```
|
||||||
Delemiter(char, DebugInfo<'a>),
|
Delemiter(char, DebugInfo),
|
||||||
Operator(Operator, DebugInfo<'a>),
|
Operator(Operator, DebugInfo),
|
||||||
Number(&'a str, NumberClassHint, DebugInfo<'a>),
|
Number(&'a str, NumHint, DebugInfo),
|
||||||
LineBreak(DebugInfo<'a>),
|
LineBreak(DebugInfo),
|
||||||
Func(&'a str, DebugInfo<'a>),
|
Func(&'a str, DebugInfo),
|
||||||
/// Variable
|
/// Variable
|
||||||
Var(&'a str, DebugInfo<'a>),
|
Var(&'a str, DebugInfo),
|
||||||
/// Function argument
|
/// Function argument
|
||||||
Arg(&'a str, DebugInfo<'a>),
|
Arg(&'a str, DebugInfo),
|
||||||
/// Variable assignment in the form of ```name = ```
|
/// Variable assignment in the form of ```name = ```
|
||||||
Assign(&'a str, Option<Prim>, DebugInfo<'a>),
|
Assign(&'a str, Option<Prim>, DebugInfo),
|
||||||
/// Variable type declaration in the form of ```name:type```
|
/// Variable type declaration in the form of ```name:type```
|
||||||
Decl(&'a str, Prim, DebugInfo<'a>),
|
Decl(&'a str, Prim, DebugInfo),
|
||||||
Bool(bool, DebugInfo<'a>),
|
Bool(bool, DebugInfo),
|
||||||
/// Keywords like ```if```,```break```,```while```
|
/// Keywords like ```if```,```break```,```while```
|
||||||
Keyword(Keyword, DebugInfo<'a>),
|
Keyword(Keyword, DebugInfo),
|
||||||
Type(Prim, DebugInfo<'a>),
|
Type(Prim, DebugInfo),
|
||||||
/// Semicolon
|
/// Semicolon
|
||||||
Terminator(DebugInfo<'a>)
|
Terminator(DebugInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for Token<'a> {
|
impl<'a> std::fmt::Display for Token<'a> {
|
||||||
|
@ -416,8 +500,8 @@ impl<'a> std::fmt::Display for Token<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Token<'a> {
|
impl<'a> Into<DebugInfo> for Token<'a> {
|
||||||
fn debug_info(&self) -> &DebugInfo {
|
fn into(self) -> DebugInfo {
|
||||||
match self {
|
match self {
|
||||||
Token::Type(_, d) => d,
|
Token::Type(_, d) => d,
|
||||||
Token::Word(_, d) => d,
|
Token::Word(_, d) => d,
|
||||||
|
@ -435,14 +519,6 @@ impl<'a> Token<'a> {
|
||||||
Token::Terminator(d) => d,
|
Token::Terminator(d) => d,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_msg(&self, msg: &'static DebugMsg) -> DebugErr {
|
|
||||||
DebugErr { info: self.debug_info().clone(), msg, ext: None }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_msg_w_ext<T>(&self, msg: &'static DebugMsg, ext: T) -> DebugErr where T: Into<String> {
|
|
||||||
DebugErr { info: self.debug_info().clone(), msg, ext: Some(ext.into()) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const TOKEN_REGEX_SRC: &'static str = r"(#.*|--.*)|(unless|while|loop|break|cont|ret|yield|please)|(int|rat|bool)|(true|false|ye|no|maybe)|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))?\s*=|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))|([A-Za-z_]+)|(\d*\.?\d+)|(!=|==|<=|<=|[&|+\-*/<>=])|([(){}])|(\n)|(;)";
|
const TOKEN_REGEX_SRC: &'static str = r"(#.*|--.*)|(unless|while|loop|break|cont|ret|yield|please)|(int|rat|bool)|(true|false|ye|no|maybe)|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))?\s*=|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))|([A-Za-z_]+)|(\d*\.?\d+)|(!=|==|<=|<=|[&|+\-*/<>=])|([(){}])|(\n)|(;)";
|
||||||
|
@ -452,18 +528,18 @@ 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<'a>(source: &'a str) -> VecDeque<Token<'a>> {
|
pub fn tokenize(source: &str) -> VecDeque<Token> {
|
||||||
let mut tokens = VecDeque::new();
|
let mut tokens = VecDeque::new();
|
||||||
|
|
||||||
let mut line_count = 0;
|
let mut line_count = 0;
|
||||||
let mut line_start = 0;
|
let mut line_start = 0;
|
||||||
|
|
||||||
for cap in TOKEN_REGEX.captures_iter(source) {
|
for cap in TOKEN_REGEX.captures_iter(source.as_ref()) {
|
||||||
let mut enumerator = cap.iter().enumerate();
|
let mut enumerator = cap.iter().enumerate();
|
||||||
loop {
|
loop {
|
||||||
let next = enumerator.next();
|
let next = enumerator.next();
|
||||||
if next.is_none() {
|
if next.is_none() {
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (i, group) = next.unwrap();
|
let (i, group) = next.unwrap();
|
||||||
|
@ -477,43 +553,41 @@ pub fn tokenize<'a>(source: &'a str) -> VecDeque<Token<'a>> {
|
||||||
// if we have a match, save it as token
|
// if we have a match, save it as token
|
||||||
if let Some(mat) = group {
|
if let Some(mat) = group {
|
||||||
let debug_info = DebugInfo {
|
let debug_info = DebugInfo {
|
||||||
source,
|
|
||||||
start: mat.start() - line_start,
|
start: mat.start() - line_start,
|
||||||
end: mat.end() - line_start,
|
end: mat.end() - line_start,
|
||||||
line: line_count
|
line: line_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
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 => {
|
3 => Token::Type(Prim::from(mat.as_str(), &debug_info), debug_info),
|
||||||
Token::Type(Prim::from(mat.as_str(), &debug_info, source), 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, source))
|
Some(Prim::from(mat.as_str(), &debug_info))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Token::Assign(mat.as_str(), var_type, debug_info)
|
Token::Assign(mat.as_str(), var_type, debug_info)
|
||||||
},
|
}
|
||||||
7 => {
|
7 => {
|
||||||
let var_type = Prim::from(enumerator.next().unwrap().1.unwrap().as_str(), &debug_info, source);
|
let var_type =
|
||||||
|
Prim::from(enumerator.next().unwrap().1.unwrap().as_str(), &debug_info);
|
||||||
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),
|
||||||
10 => Token::Number(mat.as_str(), NumberClassHint::from(mat.as_str()), debug_info),
|
10 => Token::Number(mat.as_str(), NumHint::from(mat.as_str()), debug_info),
|
||||||
11 => Token::Operator(Operator::parse(mat.as_str()), debug_info),
|
11 => Token::Operator(Operator::parse(mat.as_str()), debug_info),
|
||||||
12 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap(), debug_info),
|
12 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap(), debug_info),
|
||||||
13 => {
|
13 => {
|
||||||
line_count += 1;
|
line_count += 1;
|
||||||
line_start = mat.start();
|
line_start = mat.start();
|
||||||
Token::LineBreak(debug_info)
|
Token::LineBreak(debug_info)
|
||||||
},
|
}
|
||||||
14 => Token::Terminator(debug_info),
|
14 => Token::Terminator(debug_info),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
println!("{}", debug_info.make_msg(crate::msg::ERR71));
|
//println!("{}", debug_info.make_msg(crate::msg::ERR71));
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -528,8 +602,8 @@ pub fn tokenize<'a>(source: &'a str) -> VecDeque<Token<'a>> {
|
||||||
fn parse_bool(text: &str) -> bool {
|
fn parse_bool(text: &str) -> bool {
|
||||||
return match text {
|
return match text {
|
||||||
"true" | "ye" => true,
|
"true" | "ye" => true,
|
||||||
"false" |"no" => false,
|
"false" | "no" => false,
|
||||||
"maybe" => rand::random(),
|
"maybe" => rand::random(),
|
||||||
_ => panic!("Not a recognized boolean {text}")
|
_ => panic!("Not a recognized boolean {text}"),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue