ref parser
This commit is contained in:
145
src/ins.rs
145
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<isize>) -> 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<Ins>,
|
||||
}
|
||||
|
||||
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),
|
||||
|
||||
144
src/parser.rs
144
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<isize>) -> 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<Ins>,
|
||||
}
|
||||
|
||||
pub fn parse_lang(lang: &str) -> Result<Vec<Instruction>, ParseError> {
|
||||
let mut r = vec![];
|
||||
|
||||
@@ -22,6 +107,65 @@ pub fn parse_lang(lang: &str) -> Result<Vec<Instruction>, 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<Item=char>) -> Result<Option<Instruction>, ParseError> {
|
||||
if let Some(c) = cs.next() {
|
||||
for ins in &ins_coll.inses {
|
||||
|
||||
Reference in New Issue
Block a user