From 15baba8cbb11e3729273607a317ea3fa7e1b87e2 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Fri, 20 Jan 2023 15:47:43 +0100 Subject: [PATCH] sdl and parser --- Cargo.lock | 56 +++++++++++++++ Cargo.toml | 4 +- src/bong/lexer.rs | 4 ++ src/bong/parser.rs | 169 +++++++++++++++++++++++++++++++++------------ 4 files changed, 187 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a9a044..7d722ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,62 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "sdl2" +version = "0.35.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a" +dependencies = [ + "bitflags", + "lazy_static", + "libc", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.35.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3586be2cf6c0a8099a79a12b4084357aa9b3e0b0d7980e3b67aaf7a9d55f9f0" +dependencies = [ + "cfg-if", + "libc", + "version-compare", +] + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + [[package]] name = "web-stack-project" version = "0.1.0" +dependencies = [ + "sdl2", +] diff --git a/Cargo.toml b/Cargo.toml index 38200a5..fa67ed9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] +[dependencies.sdl2] +version = "0.35.2" +features = ["image", "mixer", "ttf"] diff --git a/src/bong/lexer.rs b/src/bong/lexer.rs index 8c1b6c0..b9ebcad 100644 --- a/src/bong/lexer.rs +++ b/src/bong/lexer.rs @@ -30,6 +30,10 @@ pub enum Token { RBrace(String), LBracket(String), RBracket(String), + Equal(String), + Colon(String), + SemiColon(String), + Comma(String), } #[derive(PartialEq)] diff --git a/src/bong/parser.rs b/src/bong/parser.rs index 0c3d313..aa7cfba 100644 --- a/src/bong/parser.rs +++ b/src/bong/parser.rs @@ -1,70 +1,149 @@ #![allow(dead_code)] -use std::iter::Map; +use super::lexer::Token; +use std::collections::HashMap; pub enum Node { Element { name: String, ids: Vec, classes: Vec, - properties: Map>, + properties: HashMap>, values: Vec, }, - Object(Map>), + Object(HashMap>), Array(Vec), Int(i64), Float(f64), String(String), Bool(bool), + Null, } -// pub struct Parser { -// tokens: Vec, -// } +pub struct Parser { + tokens: Vec, + index: usize, +} -// impl Parser { -// pub fn new(lexer: Lexer) -> Self { -// Self { lexer } -// } -// } +type ParserError = String; -// type ParserError = String; +impl Parser { + pub fn new(tokens: Vec) -> Self { + Self { tokens, index: 0 } + } -// impl Parser { -// pub fn new(tokens: Vec) -> Self { -// Self { tokens, index: 0 } -// } + pub fn parse_top_level(&mut self) -> Result { + match self.current() { + Some(Token::Name(_)) => self.parse_element(), + Some(_) => self.parse_value(), + None => Err("expected value or element".to_owned()), + } + } -// pub fn parse_top_level(&mut self) -> Result { -// match self.peek() { -// Some(Token::Name(_)) => self.parse_element(), -// Some(_) => self.parse_value(), -// None => Err("expected value or element".to_owned()), -// } -// } + fn parse_element(&mut self) -> Result {} -// fn parse_element(&mut self) -> Result {} + fn parse_value(&mut self) -> Result { + match self.current() { + Some(Token::LBrace(_)) => self.parse_object(), + Some(Token::LBracket(_)) => self.parse_object(), + Some(Token::Int(value)) => Ok(Node::Int( + value.parse().map_err(|_| "malformed int".to_string())?, + )), + Some(Token::Float(value)) => Ok(Node::Int( + value.parse().map_err(|_| "malformed float".to_string())?, + )), + Some(Token::String(value)) => Ok(Node::String(value[1..value.len() - 1].to_string())), + Some(Token::False(_)) => Ok(Node::Bool(false)), + Some(Token::True(_)) => Ok(Node::Bool(false)), + Some(Token::Null(_)) => Ok(Node::Null), + Some(_) => Err("unexpected token, expected value".to_owned()), + None => Err("expected value".to_owned()), + } + } -// fn parse_value(&mut self) -> Result { -// match self.peek() { -// Some(Token::LBrace(_)) => self.parse_object(), -// Some(Token::LBracket(_)) => self.parse_object(), -// Some(_) => Err("unexpected token, expected value".to_owned()), -// None => Err("expected value".to_owned()), -// } -// } + fn parse_object(&mut self) -> Result { + self.step(); + let mut values = HashMap::>::new(); + match self.current() { + Some(Token::RBrace(_)) => { + self.step(); + Ok(Node::Object(values)) + } + Some(t @ (Token::Name(_) | Token::String(_))) => { + let key = match t { + Token::Name(v) => v, + Token::String(v) => &v[1..v.len() - 1].to_string(), + _ => panic!("checked by previous predicate"), + }; + self.step(); + match self.current() { + Some(Token::Equal(_) | Token::Colon(_)) => {} + _ => return Err("expected ':' or '='".to_string()), + } + self.step(); + values[key] = Box::new(self.parse_value()?); + self.parse_object_tail(values) + } + _ => Err("expected Name, String or '}'".to_string()), + } + } -// fn parse_object(&mut self) -> Result {} -// fn parse_array(&mut self) -> Result {} -// fn parse_number(&mut self) -> Result {} -// fn parse_string(&mut self) -> Result {} -// fn parse_bool(&mut self) -> Result {} -// fn parse_null(&mut self) -> Result {} + fn parse_object_tail(&mut self, values: HashMap>) -> Result { + loop { + match self.current() { + Some(Token::RBrace(_)) => { + self.step(); + break Ok(Node::Object(values)); + } + Some(Token::Comma(_)) => { + self.step(); + match self.current() { + Some(Token::RBrace(_)) => { + self.step(); + break Ok(Node::Object(values)); + } + Some(t @ (Token::Name(_) | Token::String(_))) => { + let key = match t { + Token::Name(v) => v, + Token::String(v) => &v[1..v.len() - 1].to_string(), + _ => panic!("unterminated object, checked by previous predicate"), + }; + self.step(); + match self.current() { + Some(Token::Equal(_) | Token::Colon(_)) => {} + _ => return Err("expected ':' or '='".to_string()), + } + self.step(); + values[key] = Box::new(self.parse_value()?); + } + _ => { + break Err( + "unterminated object, expected Name, String or '}'".to_string() + ) + } + } + } + _ => break Err("unterminated object, expected ',' or '}'".to_string()), + } + } + } -// fn step(&mut self) { -// self.index += 1 -// } -// fn peek(&self) -> Option<&Token> { -// self.tokens.get(self.index) -// } -// } + fn parse_array(&mut self) -> Result { + self.step(); + let mut values = Vec::::new(); + match self.current() { + Some(Token::RBracket(_)) => { + self.step(); + Ok(Node::Array(values)) + } + _ => Err("unterminated array, expected Value or ']'".to_string()), + } + } + + fn step(&mut self) { + self.index += 1 + } + fn current(&self) -> Option<&Token> { + self.tokens.get(self.index) + } +}