diff --git a/src/ins.rs b/src/ins.rs index 5a72716..8bd0d3a 100644 --- a/src/ins.rs +++ b/src/ins.rs @@ -1,148 +1,3 @@ - -#[derive(Debug)] -pub enum InsId { - Push, // has data - Dup, - CopyN, // has data - Swap, - Pop, - PopN, // has data - Add, - Sub, - Mul, - Div, - Mod, - Store, - Retrieve, - DefineLabel, // has data - CallAtLabel, // has data - GotoLabel, // has data - GotoLabelE0, // has data - GotoLabelL0, // has data - ReturnCallAt, - End, - StdOutChar, - StdOutNum, - StdInChar, - StdInNum, -} - -impl InsId { - pub fn has_data(&self) -> bool { - match self { - InsId::Push | InsId::CopyN | InsId::PopN | - InsId::DefineLabel | InsId::CallAtLabel | - InsId::GotoLabel | InsId::GotoLabelE0 | InsId::GotoLabelL0 => true, - _ => false, - } - } - - pub fn new_instruction(&self, data: Option) -> Instruction { - match self { - InsId::Push => Instruction::Push(data.unwrap_or(0)), - InsId::Dup => Instruction::Dup, - InsId::CopyN => Instruction::CopyN(data.unwrap_or(0)), - InsId::Swap => Instruction::Swap, - InsId::Pop => Instruction::Pop, - InsId::PopN => Instruction::PopN(data.unwrap_or(0)), - InsId::Add => Instruction::Add, - InsId::Sub => Instruction::Sub, - InsId::Mul => Instruction::Mul, - InsId::Div => Instruction::Div, - InsId::Mod => Instruction::Mod, - InsId::Store => Instruction::Store, - InsId::Retrieve => Instruction::Retrieve, - InsId::DefineLabel => Instruction::DefineLabel(data.unwrap_or(0)), - InsId::CallAtLabel => Instruction::CallAtLabel(data.unwrap_or(0)), - InsId::GotoLabel => Instruction::GotoLabel(data.unwrap_or(0)), - InsId::GotoLabelE0 => Instruction::GotoLabelE0(data.unwrap_or(0)), - InsId::GotoLabelL0 => Instruction::GotoLabelL0(data.unwrap_or(0)), - InsId::ReturnCallAt => Instruction::ReturnCallAt, - InsId::End => Instruction::End, - InsId::StdOutChar => Instruction::StdOutChar, - InsId::StdOutNum => Instruction::StdOutNum, - InsId::StdInChar => Instruction::StdInChar, - InsId::StdInNum => Instruction::StdInNum, - } - } -} - -#[derive(Debug)] -pub enum InsType { - Path(InsColl), - Node(InsId), -} - -#[derive(Debug)] -pub struct Ins { - pub c: char, - pub ins_type: InsType, -} - -#[derive(Debug)] -pub struct InsColl { - pub inses: Vec, -} - -pub fn make_instruction_tree() -> InsColl { - InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::Push) }, - Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::Dup) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::Swap) }, - Ins{ c: '马', ins_type: InsType::Node(InsId::Pop) } - ]})}, - Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::CopyN) }, - Ins{ c: '马', ins_type: InsType::Node(InsId::PopN) } - ]})}, - ]})}, - Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::Add) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::Sub) }, - Ins{ c: '马', ins_type: InsType::Node(InsId::Mul) }, - ]})}, - Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::Div) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::Mod) }, - ]})}, - ]})}, - Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::Store) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::Retrieve) }, - ]})}, - Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::StdOutChar) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::StdOutNum) }, - ]})}, - Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::StdInChar) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::StdInNum) }, - ]})}, - ]})}, - ]})}, - Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::DefineLabel) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::CallAtLabel) }, - Ins{ c: '马', ins_type: InsType::Node(InsId::GotoLabel) }, - ]})}, - Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '草', ins_type: InsType::Node(InsId::GotoLabelE0) }, - Ins{ c: '泥', ins_type: InsType::Node(InsId::GotoLabelL0) }, - Ins{ c: '马', ins_type: InsType::Node(InsId::ReturnCallAt) }, - ]})}, - Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ - Ins{ c: '马', ins_type: InsType::Node(InsId::End) }, - ]})}, - ]})}, - ]} -} - #[derive(Debug, Clone)] pub enum Instruction { Push(isize), diff --git a/src/parser.rs b/src/parser.rs index d9733f3..586749f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,6 +3,91 @@ use super::ins::*; pub const VALID_INSTRUCTION_CHARS: &str = "草泥马河蟹"; +#[derive(Debug)] +enum InsId { + Push, // has data + Dup, + CopyN, // has data + Swap, + Pop, + PopN, // has data + Add, + Sub, + Mul, + Div, + Mod, + Store, + Retrieve, + DefineLabel, // has data + CallAtLabel, // has data + GotoLabel, // has data + GotoLabelE0, // has data + GotoLabelL0, // has data + ReturnCallAt, + End, + StdOutChar, + StdOutNum, + StdInChar, + StdInNum, +} + +impl InsId { + fn has_data(&self) -> bool { + match self { + InsId::Push | InsId::CopyN | InsId::PopN | + InsId::DefineLabel | InsId::CallAtLabel | + InsId::GotoLabel | InsId::GotoLabelE0 | InsId::GotoLabelL0 => true, + _ => false, + } + } + + fn new_instruction(&self, data: Option) -> Instruction { + match self { + InsId::Push => Instruction::Push(data.unwrap_or(0)), + InsId::Dup => Instruction::Dup, + InsId::CopyN => Instruction::CopyN(data.unwrap_or(0)), + InsId::Swap => Instruction::Swap, + InsId::Pop => Instruction::Pop, + InsId::PopN => Instruction::PopN(data.unwrap_or(0)), + InsId::Add => Instruction::Add, + InsId::Sub => Instruction::Sub, + InsId::Mul => Instruction::Mul, + InsId::Div => Instruction::Div, + InsId::Mod => Instruction::Mod, + InsId::Store => Instruction::Store, + InsId::Retrieve => Instruction::Retrieve, + InsId::DefineLabel => Instruction::DefineLabel(data.unwrap_or(0)), + InsId::CallAtLabel => Instruction::CallAtLabel(data.unwrap_or(0)), + InsId::GotoLabel => Instruction::GotoLabel(data.unwrap_or(0)), + InsId::GotoLabelE0 => Instruction::GotoLabelE0(data.unwrap_or(0)), + InsId::GotoLabelL0 => Instruction::GotoLabelL0(data.unwrap_or(0)), + InsId::ReturnCallAt => Instruction::ReturnCallAt, + InsId::End => Instruction::End, + InsId::StdOutChar => Instruction::StdOutChar, + InsId::StdOutNum => Instruction::StdOutNum, + InsId::StdInChar => Instruction::StdInChar, + InsId::StdInNum => Instruction::StdInNum, + } + } +} + +#[derive(Debug)] +enum InsType { + Path(InsColl), + Node(InsId), +} + +#[derive(Debug)] +struct Ins { + c: char, + ins_type: InsType, +} + +#[derive(Debug)] +struct InsColl { + inses: Vec, +} + pub fn parse_lang(lang: &str) -> Result, ParseError> { let mut r = vec![]; @@ -22,6 +107,65 @@ pub fn parse_lang(lang: &str) -> Result, ParseError> { Ok(r) } +fn make_instruction_tree() -> InsColl { + InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::Push) }, + Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::Dup) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::Swap) }, + Ins{ c: '马', ins_type: InsType::Node(InsId::Pop) } + ]})}, + Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::CopyN) }, + Ins{ c: '马', ins_type: InsType::Node(InsId::PopN) } + ]})}, + ]})}, + Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::Add) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::Sub) }, + Ins{ c: '马', ins_type: InsType::Node(InsId::Mul) }, + ]})}, + Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::Div) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::Mod) }, + ]})}, + ]})}, + Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::Store) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::Retrieve) }, + ]})}, + Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::StdOutChar) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::StdOutNum) }, + ]})}, + Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::StdInChar) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::StdInNum) }, + ]})}, + ]})}, + ]})}, + Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::DefineLabel) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::CallAtLabel) }, + Ins{ c: '马', ins_type: InsType::Node(InsId::GotoLabel) }, + ]})}, + Ins{ c: '泥', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '草', ins_type: InsType::Node(InsId::GotoLabelE0) }, + Ins{ c: '泥', ins_type: InsType::Node(InsId::GotoLabelL0) }, + Ins{ c: '马', ins_type: InsType::Node(InsId::ReturnCallAt) }, + ]})}, + Ins{ c: '马', ins_type: InsType::Path(InsColl{ inses: vec![ + Ins{ c: '马', ins_type: InsType::Node(InsId::End) }, + ]})}, + ]})}, + ]} +} + fn match_instruction(ins_coll: &InsColl, cs: &mut dyn Iterator) -> Result, ParseError> { if let Some(c) = cs.next() { for ins in &ins_coll.inses {