added argument flags
This commit is contained in:
parent
d3f121640a
commit
fda09066c7
|
@ -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
|
||||||
|
}
|
18
src/main.rs
18
src/main.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(" {}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,17 +59,20 @@ 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(());
|
||||||
|
@ -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));
|
||||||
|
} else {
|
||||||
diagnostics.set_err(&top, crate::msg::ERR41, "");
|
diagnostics.set_err(&top, crate::msg::ERR41, "");
|
||||||
panic!()
|
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(|| {
|
|
||||||
//println!("{}", dbginf.make_msg(crate::msg::ERR41));
|
|
||||||
panic!()
|
|
||||||
})
|
|
||||||
.push_back(Expr::Block(block));
|
|
||||||
} else {
|
} else {
|
||||||
//println!("{}", dbginf.make_msg(crate::msg::ERR40));
|
diagnostics.set_err(&top, crate::msg::ERR41, "");
|
||||||
panic!()
|
return Err(());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
diagnostics.set_err(&top, crate::msg::ERR40, "");
|
||||||
|
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(declr_name) = declr.name {
|
||||||
|
if declr_name != name {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// some critical compiler error
|
||||||
|
crate::message(crate::token::MessageType::Critical, "Missing function name in declaration");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(args) = &declr.args {
|
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() {
|
if args.len() > operands.len() {
|
||||||
/*
|
diagnostics.set_err(info, crate::msg::ERR60, format!("expected {:?} got {:?}", args.len(), operands.len()));
|
||||||
println!(
|
return Err(());
|
||||||
"{}",
|
|
||||||
dbginf.make_msg_w_ext(
|
|
||||||
crate::msg::ERR60,
|
|
||||||
format!("expected {:?} got {:?}", args.len(), operands.len())
|
|
||||||
)
|
|
||||||
);*/
|
|
||||||
panic!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check parameter types
|
||||||
for (x, arg) in args.iter().enumerate() {
|
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();
|
let operand = operands.first().unwrap();
|
||||||
|
// check types
|
||||||
if !operand.is_equal(arg.1) {
|
if !operand.is_equal(arg.1) {
|
||||||
/*
|
diagnostics.set_err(info, crate::msg::ERR61, format!("expected {:?} got {:?} as {}th argument", arg, operand, x));
|
||||||
println!(
|
return Err(());
|
||||||
"{}",
|
|
||||||
dbginf.make_msg_w_ext(
|
|
||||||
crate::msg::ERR61,
|
|
||||||
format!("expected {:?} got {:?}", arg, operand)
|
|
||||||
)
|
|
||||||
);*/
|
|
||||||
panic!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operands.remove(0);
|
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 {
|
if let Some(typ) = declr.result_typ {
|
||||||
operands.push(typ);
|
operands.push(typ);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
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]));
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
crate::message(crate::token::MessageType::Critical, "Fatal-Compilier-Error: function must have a block");
|
||||||
panic!();
|
panic!();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("Fatal-Compilier-Error: function must have a block"),
|
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);
|
|
||||||
|
|
||||||
|
if settings.gen_erpn() {
|
||||||
crate::inter::convert_to_erpn(&mut funcs, &declrs);
|
crate::inter::convert_to_erpn(&mut funcs, &declrs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
dias
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
125
src/token/mod.rs
125
src/token/mod.rs
|
@ -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!();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
16
test.erpn
16
test.erpn
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue