mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'lemu/src/parser/error.rs')
-rw-r--r--lemu/src/parser/error.rs442
1 files changed, 0 insertions, 442 deletions
diff --git a/lemu/src/parser/error.rs b/lemu/src/parser/error.rs
deleted file mode 100644
index c2b053b..0000000
--- a/lemu/src/parser/error.rs
+++ /dev/null
@@ -1,442 +0,0 @@
-use super::tokstr;
-use crate::executor::Instruction;
-use crate::lexer::Token;
-use logos::Span;
-
-/// Errors returned when parsing fails.
-#[derive(thiserror::Error, Debug)]
-pub enum Error<'s> {
- /// Occurs from eg `set x`. (needs a value to set to)
- #[error("unexpected end of stream")]
- UnexpectedEof,
- /// Occurs from eg `op add\n...` (needs a variable)
- #[error("expected variable, got {0:?}")]
- ExpectedVar(Token<'s>, Span),
- /// Occurs from eg `draw 4` (needs a ident of the type of drawing)
- #[error("expected identifier, got {0:?}")]
- ExpectedIdent(Token<'s>, Span),
- /// Occurs from eg `jump house` (assuming house isnt a label).
- #[error("expected jump target, got {0:?}")]
- ExpectedJump(Token<'s>, Span),
- /// Occurs from eg `op add "three" "four"`
- #[error("expected number, got {0:?}")]
- ExpectedNum(Token<'s>, Span),
- /// Occurs from eg `op 4` (4 is not add/mul/...)
- #[error("expected operator, got {0:?}")]
- ExpectedOp(Token<'s>, Span),
- /// Occurs from eg `write cell1 5.5` (5.5 is not int)
- #[error("expected integer, got {0:?}")]
- ExpectedInt(Token<'s>, Span),
- /// Occurs from eg `control shootp building 4`
- #[error("expected string, got {0:?}")]
- ExpectedString(Token<'s>, Span),
- /// Occurs from `status not_a_bool`
- #[error("expected bool, got {0:?}")]
- ExpectedBool(Token<'s>, Span),
- /// Occurs from eg `4.0 add 5.0`
- #[error("expected instruction, got {0:?}")]
- ExpectedInstr(Token<'s>, Span),
- /// Occurs from eg
- /// ```text
- /// lable:
- /// jump label always
- /// ```
- /// (typo: lable not label)
- #[error("unable to find label {0}")]
- LabelNotFound(&'s str, Span),
- /// Occurs from eg `jump 4910294029 always`
- #[error("unable to jump to instruction {0:?}")]
- InvalidJump(Instruction, Span),
- /// Occurs from eg `read bank9223372036854775807 5` (only `126` banks can exist)
- #[error("cannot get cell>{0}")]
- MemoryTooFar(usize, Span),
- /// Occurs from eg `read bank1 512`
- #[error("index {0} out of bounds ({1} max)")]
- IndexOutOfBounds(usize, usize, Span),
- /// Occurs from `read register1`
- #[error("unknown memory type {0:?}, expected (cell)|(bank)")]
- InvalidMemoryType(&'s str, Span),
- /// Occurs from `drawflush bank1`
- #[error("unknown display type {0}, expected 'display'")]
- InvalidDisplayType(&'s str, Span),
- /// Occurs from `draw house` (or `draw image`, a valid but unsupported instruction here)
- #[error("unknown image operation {0}")]
- UnsupportedImageOp(&'s str, Span),
- /// Occurs from `control what`
- #[error("unknown control operation {0}")]
- UnknownControlOp(&'s str, Span),
- /// Occurs from `ucontrol kill`
- #[error("unknown ucontrol operation {0}")]
- UnknownUnitControlOp(&'s str, Span),
- /// Occurs from `ulocate five`
- #[error("unknown ulocate operation {0}")]
- UnknownUnitLocateOp(&'s str, Span),
- /// Occurs from `getblock core`
- #[error("unknown getblock operation {0}")]
- UnknownGetBlockOp(&'s str, Span),
- /// Occurs from `setblock unit`
- #[error("unknown setblock operation {0}")]
- UnknownSetBlockOp(&'s str, Span),
- /// Occurs from `setrule hello`
- #[error("unknown rule {0}")]
- UnknownRule(&'s str, Span),
- /// Occurs from `cutscene begin`
- #[error("unknown cutscene {0}")]
- UnknownCutscene(&'s str, Span),
- /// Occurs from `fetch hostages`
- #[error("unknown fetch operation {0}")]
- UnknownFetchOp(&'s str, Span),
- #[error("couldnt get display #{0:?}.")]
- /// Occurs from eg `display 50`.
- ///
- /// call `display` 50 more times to have more display options:
- /// ```rust,ignore
- /// executor
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display()
- /// .display();
- /// ```
- NoDisplay(usize, Span),
- /// We have a limit of [`u32::MAX`] variables.
- #[error("too many variables")]
- TooManyVariables(Span),
-}
-
-impl Error<'_> {
- /// Produces a [`Error`](lerr::Error) from this error.
- #[cfg(feature = "diagnose")]
- pub fn diagnose<'s>(&self, source: &'s str) -> lerr::Error<'s> {
- use comat::{cformat as cmt, cformat_args};
- use lerr::Error;
-
- let error = cformat_args!("{bold_red}error{reset}");
- let note = cformat_args!("{bold_blue}note{reset}");
- let help = cformat_args!("{bold_green}help{reset}");
- let mut e = Error::new(source);
- macro_rules! msg {
- ($ms:literal $(, $args:expr)* $(,)?) => {
- e.message(cmt!($ms $(, $args)*))
- };
- }
- macro_rules! op {
- ($op:ident, $ops:expr) => {{
- let mut out = String::from("{");
- let mut ops = $ops.iter();
- use std::fmt::Write;
- write!(out, "{}", ops.next().unwrap()).unwrap();
- for op in ops {
- write!(out, ", {}", op).unwrap();
- }
- out.write_char('}').unwrap();
- if let Some((mat, score)) =
- rust_fuzzy_search::fuzzy_search_best_n($op, $ops, 1).first()
- && *score > 0.5
- {
- e.note(cmt!("{help}: you may have meant {bold_green}{mat}{reset}"));
- }
- out
- }};
- }
- match self {
- Self::UnexpectedEof => {
- msg!("{error}: wasnt able to finish read, got newline").label((
- source.len()..source.len(),
- cmt!("there was supposed to be another token here"),
- ));
- }
- Self::ExpectedVar(t, s) => {
- msg!("{error}: expected variable, got {:?}", t)
- .label((s, cmt!("this was supposed to be a {blue}variable{reset} ({magenta}identifier{reset}, {magenta}number{reset}, or {magenta}string{reset})")));
- }
- Self::ExpectedIdent(_, s) => {
- msg!("{error}: expected identifier").label((
- s,
- cmt!("this was supposed to be a {bold_blue}identifier{reset} (eg. {magenta}name{reset})"),
- ));
- }
- Self::ExpectedJump(t, s) => {
- msg!("{error}: expected jump target")
- .label((s, cmt!("this was supposed to be a jump target")))
- .note(
- cmt!("{note}: a jump target is a {bold_blue}label{reset} ({magenta}ident{reset}, or {magenta}integer{reset})"),
- );
- if let Token::Num(n) = t {
- e.note(cmt!(
- "{help}: remove the fractional part: {bold_green}{n:.0}{reset}"
- ));
- }
- }
- Self::ExpectedNum(_, s) => {
- msg!("{error}: expected number")
- .label((s, cmt!("this was supposed to be a {bold_blue}number{reset} (eg. {magenta}3.14159{reset})")));
- }
- Self::ExpectedString(_, s) => {
- msg!("{error}: expected string").label((s, cmt!(r#"this was supposed to be a {bold_blue}string{reset} (eg. {magenta}"a cool string"{reset})"#)));
- }
- Self::ExpectedBool(_, s) => {
- msg!("{error}: expected bool").label((s, cmt!("this was supposed to be a {bold_blue}boolean{reset} (eg. {magenta}true{reset})")));
- }
- Self::ExpectedOp(t, s) => {
- msg!("{error}: expected operator")
- .label((s, cmt!("this was supposed to be a {bold_blue}operator{reset} (eg. {magenta}equal{reset})")));
- if let Some(i) = tokstr!(*t)
- && let Some((mat, score)) =
- rust_fuzzy_search::fuzzy_search_best_n(i, crate::instructions::OPS, 1)
- .first()
- && *score > 0.5
- {
- e.note(cmt!("{help}: maybe you meant {bold_green}{mat}{reset}"));
- }
- }
- Self::ExpectedInt(t, s) => {
- msg!("{error}: expected integer")
- .label((s, cmt!("this was supposed to be a {bold_blue}integer{reset} (eg. {magenta}4{reset})")));
- if let Token::Num(n) = t {
- e.note(cmt!(
- "{help}: remove the mantissa: {bold_green}{n:.0}{reset}"
- ));
- }
- }
- Self::ExpectedInstr(t, s) => {
- msg!("{error}: expected instruction")
- .label((s, cmt!("this was supposed to be a {bold_blue}instruction{reset} (eg. {magenta}print{reset})")));
- if let Some(i) = tokstr!(*t)
- && let Some((mat, score)) = rust_fuzzy_search::fuzzy_search_best_n(
- i,
- &[
- "getlink",
- "read",
- "write",
- "set",
- "op",
- "end",
- "drawflush",
- "draw",
- "print",
- "packcolor",
- "jump",
- "stop",
- "printflush",
- "control",
- "radar",
- "sensor",
- "wait",
- "lookup",
- "packcolor",
- "ubind",
- "ucontrol",
- "uradar",
- "ulocate",
- "getblock",
- "setblock",
- "spawn",
- "status",
- "spawnwave",
- "setrule",
- "cutscene",
- "explosion",
- "setrate",
- "fetch",
- "getflag",
- "setflag",
- "setprop",
- "effect",
- ],
- 1,
- )
- .first()
- && *score > 0.5
- {
- e.note(cmt!("{help}: maybe you meant {mat}"));
- }
- }
- Self::LabelNotFound(_, s) => {
- msg!("{error}: label not found").label((
- s,
- cmt!("this was supposed to be a (existing) {bold_blue}label{reset}"),
- )).note(cmt!("{help}: define a label with {yellow}`label_name:`{reset}, then you can {yellow}`jump label_name`{reset}."));
- }
- Self::InvalidJump(target, s) => {
- msg!("{error}: invalid jump")
- .label((
- s,
- cmt!(
- "line#{bold_red}{}{reset} is not in the program",
- target.get()
- ),
- ))
- .note(cmt!(
- "{help}: there are {bold_blue}{}{reset} available lines",
- source.lines().count()
- ));
- }
- Self::MemoryTooFar(b, s) => {
- msg!("{error}: invalid memory cell/bank")
- .label((s, cmt!("cant get cell/bank#{bold_red}{b}{reset}")))
- .note(cmt!(
- "{note}: only {blue}126{reset} cells/banks are allowed"
- ));
- }
- Self::InvalidMemoryType(t, s) => {
- msg!("{error}: invalid memory type {bold_red}{}{reset}", t)
- .label((s, "here"))
- .note(cmt!("{note}: only banks/cells are allowed"));
- }
- Self::InvalidDisplayType(disp, s) => {
- msg!("{error}: invalid display type {bold_red}{}{reset}", disp)
- .label((s, "here"))
- .note(cmt!("{help}: change this to {bold_green}'display'{reset}"));
- }
- Self::UnknownControlOp(op, s) => {
- let available = op!(op, &["enabled", "shoot", "shootp", "config", "color"]);
- msg!("{error}: invalid control op {}", op)
- .label((s, cmt!("must be one of {available}",)));
- }
- Self::UnknownUnitControlOp(op, s) => {
- let available = op!(
- op,
- &[
- "idle", "stop", "move", "approach", "boost", "pathfind", "target",
- "targetp", "itemDrop", "itemTake", "payDrop", "payEnter", "mine", "flag",
- "build", "getBlock", "within"
- ]
- );
- msg!("{error}: unknown unit control op {}", op)
- .label((s, cmt!("must be one of {available}",)));
- }
- Self::UnknownSetBlockOp(op, s) => {
- let available = op!(op, &["floor", "ore", "block"]);
- msg!("{error}: unknown set block op {}", op)
- .label((s, cmt!("must be one of {available}")));
- }
- Self::UnknownUnitLocateOp(op, s) => {
- let a = op!(op, &["ore", "spawn", "damaged", "building"]);
- msg!("{error}: unkown unit locate op {}", op)
- .label((s, cmt!("must be one of {a}",)));
- }
- Self::UnknownGetBlockOp(op, s) => {
- let a = op!(op, &["floor", "ore", "block", "building"]);
- msg!("{error}: unknown getblock op {}", op).label((s, cmt!("must be one of {a}",)));
- }
- Self::UnsupportedImageOp(op, s) => {
- let a = op!(op, crate::instructions::draw::INSTRS);
- msg!("{error}: invalid image op {}", op).label((s, cmt!("must be one of {a}")));
- }
- Self::UnknownRule(rule, s) => {
- let a = op!(
- rule,
- &[
- "currentWaveTime",
- "waveTimer",
- "waves",
- "wave",
- "waveSpacing",
- "waveSending",
- "attackMode",
- "enemyCoreBuildRadius",
- "dropZoneRadius",
- "unitCap",
- "wave",
- "lighting",
- "ambientLight",
- "solarMultiplier",
- "mapArea",
- "buildSpeed",
- "unitHealth",
- "unitBuildSpeed",
- "unitCost",
- "unitDamage",
- "blockHealth",
- "blockDamage",
- "rtsMinWeight",
- "rtsMinSquad",
- ]
- );
- msg!("{error}: invalid rule {}", rule).label((s, cmt!("must be one of {a}")));
- }
- Self::UnknownCutscene(op, s) => {
- let a = op!(op, &["pan", "zoom", "stop"]);
- msg!("{error}: invalid cutscene type {}", op)
- .label((s, cmt!("must be one of {a}")));
- }
- Self::UnknownFetchOp(op, s) => {
- let a = op!(
- op,
- &[
- "buildCount",
- "coreCount",
- "playerCount",
- "unitCount",
- "build",
- "core",
- "player",
- "unit"
- ]
- );
- msg!("{error}: invalid op {}", op).label((s, cmt!("must be one of {a}")));
- }
- Self::NoDisplay(disp, s) => {
- msg!("{error}: no display allocated")
- .label((s, cmt!("display#{bold_red}{disp}{reset} has not been created")))
- .note(cmt!("{note}: it is impossible for me to dynamically allocate displays, as {blue}'display1'{reset} could be large or small"));
- }
- Self::IndexOutOfBounds(index, size, s) => {
- msg!("{error}: {bold_red}index{reset} {} out of bounds", index)
- .label((s, cmt!("memory has only {magenta}{size}{reset} elements")));
- }
- Self::TooManyVariables(s) => {
- msg!("{error}: {bold_red}too many variables{reset}. ")
- .label((s, cmt!("we only have 65536 variable slots")))
- .note(cmt!("consider not using variables"));
- }
- };
- e
- }
-}