From 0536daefa382fec9ed8fc39b7f72daef875e98c6 Mon Sep 17 00:00:00 2001 From: Lewis Dale Date: Mon, 2 Jan 2023 15:21:35 +0000 Subject: [PATCH] First program: Runs Hello World using PRINT --- .gitignore | 1 + Cargo.lock | 32 ++++++++++++++++++++++++++++ Cargo.toml | 9 ++++++++ inputs/hello_world.bas | 1 + src/basic.rs | 48 ++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 17 +++++++++++++++ 6 files changed, 108 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 inputs/hello_world.bas create mode 100644 src/basic.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6b9e971 --- /dev/null +++ b/Cargo.lock @@ -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", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..804b2cb --- /dev/null +++ b/Cargo.toml @@ -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" diff --git a/inputs/hello_world.bas b/inputs/hello_world.bas new file mode 100644 index 0000000..ac29b12 --- /dev/null +++ b/inputs/hello_world.bas @@ -0,0 +1 @@ +10 PRINT "Hello, world." \ No newline at end of file diff --git a/src/basic.rs b/src/basic.rs new file mode 100644 index 0000000..dea8f02 --- /dev/null +++ b/src/basic.rs @@ -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); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6afda37 --- /dev/null +++ b/src/main.rs @@ -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"); + } + }; +}