First program: Runs Hello World using PRINT

This commit is contained in:
Lewis Dale 2023-01-02 15:21:35 +00:00
commit 0536daefa3
6 changed files with 108 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

32
Cargo.lock generated Normal file
View File

@ -0,0 +1,32 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "basic-interpreter"
version = "0.1.0"
dependencies = [
"nom",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c"
dependencies = [
"memchr",
"minimal-lexical",
]

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "basic-interpreter"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
nom = "7.1.2"

1
inputs/hello_world.bas Normal file
View File

@ -0,0 +1 @@
10 PRINT "Hello, world."

48
src/basic.rs Normal file
View File

@ -0,0 +1,48 @@
use nom::{
bytes::complete::{tag, take_until},
character::complete::u32 as ccu32,
combinator::map,
sequence::{delimited, terminated, tuple},
IResult,
};
pub type Line<'a> = (u32, Command<'a>);
#[derive(Debug, PartialEq, Eq)]
pub enum Command<'a> {
Print(&'a str),
None,
}
fn read_string(i: &str) -> IResult<&str, &str> {
take_until("\"")(i)
}
fn parse_command(i: &str) -> IResult<&str, Command> {
let (i, (command, _)) = tuple((take_until(" "), tag(" ")))(i)?;
let (i, cmd) = match command {
"PRINT" => map(delimited(tag("\""), read_string, tag("\"")), Command::Print)(i)?,
_ => (i, Command::None),
};
Ok((i, cmd))
}
pub fn parse_line(line: &str) -> IResult<&str, Line> {
let (i, line_number) = terminated(ccu32, tag(" "))(line)?;
let (i, command) = parse_command(i)?;
Ok((i, (line_number, command)))
}
#[cfg(test)]
mod tests {
#[test]
fn it_parses_a_print_command() {
let input = "10 PRINT \"Hello, world\"";
let expected = (10, super::Command::Print("Hello, world"));
let (_, result) = super::parse_line(input).unwrap();
assert_eq!(expected, result);
}
}

17
src/main.rs Normal file
View File

@ -0,0 +1,17 @@
use std::fs;
mod basic;
fn main() {
let file = fs::read_to_string("./inputs/hello_world.bas").unwrap();
let lines = file.lines().next().unwrap();
let (_, (_, command)) = basic::parse_line(lines).unwrap();
match command {
basic::Command::Print(input) => {
println!("{}", input);
}
_ => {
panic!("Command not recognised");
}
};
}