Move command parsers into parsers module
This commit is contained in:
parent
92e98bbdcb
commit
ed885b0f81
80
src/basic.rs
80
src/basic.rs
@ -1,11 +1,8 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use nom::{
|
use nom::{bytes::complete::tag, multi::separated_list0, IResult};
|
||||||
branch::alt, bytes::complete::tag, character::complete::u64 as ccu64, combinator::map,
|
|
||||||
multi::separated_list0, sequence::terminated, IResult,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::parsers::{generic, variables};
|
use crate::parsers::commands;
|
||||||
|
|
||||||
pub type Line = (usize, Command);
|
pub type Line = (usize, Command);
|
||||||
|
|
||||||
@ -115,11 +112,22 @@ impl Program {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read(i: &str) -> IResult<&str, Self> {
|
||||||
|
let (i, lines) = separated_list0(tag("\n"), commands::parse_line)(i)?;
|
||||||
|
let mut node = Node::None;
|
||||||
|
|
||||||
|
for line in lines.iter() {
|
||||||
|
node.push(line.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((i, Program::new(node)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Program {
|
impl From<&str> for Program {
|
||||||
fn from(value: &str) -> Self {
|
fn from(value: &str) -> Self {
|
||||||
let (_, program) = read_program(value).unwrap();
|
let (_, program) = Self::read(value).unwrap();
|
||||||
program
|
program
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,65 +147,13 @@ impl Iterator for Program {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_command(i: &str) -> IResult<&str, &str> {
|
|
||||||
alt((tag("PRINT"), tag("GO TO"), tag("LET"), tag("REM")))(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_print_command(i: &str) -> IResult<&str, PrintOutput> {
|
|
||||||
alt((
|
|
||||||
map(
|
|
||||||
alt((
|
|
||||||
variables::parse_str_variable_name,
|
|
||||||
variables::parse_int_variable_name,
|
|
||||||
)),
|
|
||||||
PrintOutput::Variable,
|
|
||||||
),
|
|
||||||
map(generic::read_string, PrintOutput::Value),
|
|
||||||
))(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_command(i: &str) -> IResult<&str, Command> {
|
|
||||||
let (i, command): (&str, &str) = match_command(i).unwrap_or((i, ""));
|
|
||||||
let (i, _) = tag(" ")(i)?;
|
|
||||||
|
|
||||||
let (i, cmd) = match command {
|
|
||||||
"PRINT" => map(parse_print_command, Command::Print)(i)?,
|
|
||||||
"GO TO" => map(ccu64, |line| Command::GoTo(line as usize))(i)?,
|
|
||||||
"LET" => map(variables::parse_var, Command::Var)(i)?,
|
|
||||||
"REM" => {
|
|
||||||
let (i, _) = generic::consume_line(i)?;
|
|
||||||
(i, Command::Comment)
|
|
||||||
}
|
|
||||||
_ => (i, Command::None),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((i, cmd))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_line(line: &str) -> IResult<&str, Line> {
|
|
||||||
let (i, line_number) = map(terminated(ccu64, tag(" ")), |l| l as usize)(line)?;
|
|
||||||
let (i, command) = parse_command(i)?;
|
|
||||||
Ok((i, (line_number, command)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_program(i: &str) -> IResult<&str, Program> {
|
|
||||||
let (i, lines) = separated_list0(tag("\n"), parse_line)(i)?;
|
|
||||||
let mut node = Node::None;
|
|
||||||
|
|
||||||
for line in lines.iter() {
|
|
||||||
node.push(line.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((i, Program::new(node)))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::basic::PrintOutput;
|
use crate::basic::PrintOutput;
|
||||||
|
|
||||||
use super::{parse_line, read_program, Command, Line, Node, Primitive};
|
use super::{Command, Line, Node, Primitive, Program};
|
||||||
|
|
||||||
use crate::parsers::generic::read_string;
|
use crate::parsers::{commands::parse_line, generic::read_string};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn it_parses_a_print_command() {
|
fn it_parses_a_print_command() {
|
||||||
@ -308,8 +264,8 @@ mod tests {
|
|||||||
next: Box::new(Node::None),
|
next: Box::new(Node::None),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
let expected = ("", super::Program::new(expected_node));
|
let expected = Program::new(expected_node);
|
||||||
let result = read_program(lines).unwrap();
|
let result = Program::from(lines);
|
||||||
assert_eq!(expected, result);
|
assert_eq!(expected, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
|
pub mod commands;
|
||||||
pub mod generic;
|
pub mod generic;
|
||||||
pub mod variables;
|
pub mod variables;
|
||||||
|
49
src/parsers/commands.rs
Normal file
49
src/parsers/commands.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use nom::{
|
||||||
|
branch::alt, bytes::complete::tag, character::complete::u64 as ccu64, combinator::map,
|
||||||
|
sequence::terminated, IResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::basic::{Command, Line, PrintOutput};
|
||||||
|
|
||||||
|
use super::{generic, variables};
|
||||||
|
|
||||||
|
pub fn match_command(i: &str) -> IResult<&str, &str> {
|
||||||
|
alt((tag("PRINT"), tag("GO TO"), tag("LET"), tag("REM")))(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_print_command(i: &str) -> IResult<&str, PrintOutput> {
|
||||||
|
alt((
|
||||||
|
map(
|
||||||
|
alt((
|
||||||
|
variables::parse_str_variable_name,
|
||||||
|
variables::parse_int_variable_name,
|
||||||
|
)),
|
||||||
|
PrintOutput::Variable,
|
||||||
|
),
|
||||||
|
map(generic::read_string, PrintOutput::Value),
|
||||||
|
))(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_command(i: &str) -> IResult<&str, Command> {
|
||||||
|
let (i, command): (&str, &str) = match_command(i).unwrap_or((i, ""));
|
||||||
|
let (i, _) = tag(" ")(i)?;
|
||||||
|
|
||||||
|
let (i, cmd) = match command {
|
||||||
|
"PRINT" => map(parse_print_command, Command::Print)(i)?,
|
||||||
|
"GO TO" => map(ccu64, |line| Command::GoTo(line as usize))(i)?,
|
||||||
|
"LET" => map(variables::parse_var, Command::Var)(i)?,
|
||||||
|
"REM" => {
|
||||||
|
let (i, _) = generic::consume_line(i)?;
|
||||||
|
(i, Command::Comment)
|
||||||
|
}
|
||||||
|
_ => (i, Command::None),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((i, cmd))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_line(line: &str) -> IResult<&str, Line> {
|
||||||
|
let (i, line_number) = map(terminated(ccu64, tag(" ")), |l| l as usize)(line)?;
|
||||||
|
let (i, command) = parse_command(i)?;
|
||||||
|
Ok((i, (line_number, command)))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user