diff --git a/Cargo.toml b/Cargo.toml index 2199fb61..5dd28186 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,4 +32,5 @@ winit = "0.22.0" hprof = "0.1.3" rusttype = { version = "0.7.0", features = ["gpu_cache"] } vulkano_text = "0.12.0" -petgraph = "0.5.1" \ No newline at end of file +petgraph = "0.5.1" +nom = "6.0.0-alpha3" \ No newline at end of file diff --git a/resources/scripts/scratch b/resources/scripts/scratch new file mode 100644 index 00000000..16f09096 --- /dev/null +++ b/resources/scripts/scratch @@ -0,0 +1,6 @@ + +# this is a comment +elem table : globalTableFormatting { + +} + diff --git a/src/event_system.rs b/src/event_system.rs index 21b450db..c6205b24 100644 --- a/src/event_system.rs +++ b/src/event_system.rs @@ -4,8 +4,6 @@ use specs::{Component, Entities, Join, System, VecStorage, Write, WriteStorage}; use vulkano::swapchain::Surface; use winit::window::Window; -use crate::canvas::canvas_frame::CanvasFrame; -use crate::canvas::compu_frame::CompuFrame; use crate::PersistentState; use crate::render_system::Position; use crate::util::tr_event::{TrEvent, TrEventExtension, TrWindowEvent}; diff --git a/src/main.rs b/src/main.rs index cba58c95..abe3a789 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,8 @@ extern crate nalgebra as na; extern crate rand; extern crate specs; extern crate time; +#[macro_use] +extern crate nom; use std::path::Path; use std::sync::Arc; @@ -57,6 +59,7 @@ pub mod canvas; pub mod render_system; pub mod compu_system; pub mod event_system; +pub mod parser; #[derive(Default)] pub struct PersistentState { @@ -72,61 +75,26 @@ struct TrSprite { } +use std::fs; +use nom::sequence::{preceded, tuple}; +use nom::bytes::complete::{take_while1, tag, take_while_m_n}; +use nom::character::complete::line_ending; +use nom::error::ErrorKind; +use nom::combinator::map_res; +use nom::IResult; +use crate::parser::parser::{Color, hex_color, parse_script}; -use logos::Logos; - -#[derive(Logos, Debug, PartialEq)] -enum Token { - // Tokens can be literal strings, of any length. - #[token("fast")] - Fast, - - #[token(".")] - Period, - - // Or regular expressions. - #[regex("[a-zA-Z]+")] - Text, - - // Logos requires one token variant to handle errors, - // it can be named anything you wish. - #[error] - // We can also use this variant to define whitespace, - // or any other matches we wish to skip. - #[regex(r"[ \t\n\f]+", logos::skip)] - Error, -} pub fn main() { //https://dylanede.github.io/cassowary-rs/cassowary/index.html - let mut lex = Token::lexer("Create ridiculously fast Lexers."); - - assert_eq!(lex.next(), Some(Token::Text)); - assert_eq!(lex.span(), 0..6); - assert_eq!(lex.slice(), "Create"); - - assert_eq!(lex.next(), Some(Token::Text)); - assert_eq!(lex.span(), 7..19); - assert_eq!(lex.slice(), "ridiculously"); - - assert_eq!(lex.next(), Some(Token::Fast)); - assert_eq!(lex.span(), 20..24); - assert_eq!(lex.slice(), "fast"); - - assert_eq!(lex.next(), Some(Token::Text)); - assert_eq!(lex.span(), 25..31); - assert_eq!(lex.slice(), "Lexers"); - - assert_eq!(lex.next(), Some(Token::Period)); - assert_eq!(lex.span(), 31..32); - assert_eq!(lex.slice(), "."); - - assert_eq!(lex.next(), None); + let input_string = fs::read_to_string("./resources/scripts/scratch").unwrap(); + parse_script::<(&str, ErrorKind)>(&input_string); + return; //hprof::start_frame(); //let g = hprof::enter("vulkan preload"); diff --git a/src/parser/mod.rs b/src/parser/mod.rs new file mode 100644 index 00000000..b2819a7e --- /dev/null +++ b/src/parser/mod.rs @@ -0,0 +1 @@ +pub mod parser; \ No newline at end of file diff --git a/src/parser/parser.rs b/src/parser/parser.rs new file mode 100644 index 00000000..7f9b4bd0 --- /dev/null +++ b/src/parser/parser.rs @@ -0,0 +1,109 @@ +use nom::IResult; +use nom::number::complete::be_u16; +use nom::bytes::complete::{take, is_not, take_while, escaped}; +use nom::character::complete::{char, one_of}; +use nom::bytes::complete::{take_while1, tag, take_while_m_n}; +use nom::combinator::{map_res, opt, cut}; +use nom::sequence::{preceded, tuple, delimited, terminated}; +use nom::error::ParseError; +use nom::character::complete::{alphanumeric1 as alphanumeric}; + +pub fn length_value(input: &[u8]) -> IResult<&[u8],&[u8]> { + let (input, length) = be_u16(input)?; + take(length)(input) +} + +#[derive(Debug,PartialEq)] +pub struct Color { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +pub struct ScriptMeta { + +} + +pub fn from_hex(input: &str) -> Result { + u8::from_str_radix(input, 16) +} + +pub fn is_hex_digit(c: char) -> bool { + c.is_digit(16) +} + +pub fn hex_primary(input: &str) -> IResult<&str, u8> { + map_res( + take_while_m_n(2, 2, is_hex_digit), + from_hex + )(input) +} + +pub fn hex_color(input: &str) -> IResult<&str, Color> { + let (input, _) = tag("#")(input)?; + let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; + + Ok((input, Color { red, green, blue })) +} + +pub fn elem_tag(input: &str) -> IResult<&str, u8> { + let (input, _) = tag("elem")(input)?; + let input = sp(input)?; + Ok((input.0, 0)) +} + +pub fn comment<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, u8, E> { + + preceded(char('#'), cut(terminated(escaped( + alphanumeric, '\\', one_of("\"n\\")), char('\"'))) + )(input)?; + // let (input, _) = tag("#")(input)?; + Ok(("", 0)) +} + +fn curlies(input: &str) -> IResult<&str, &str> { + delimited(char('{'), is_not("}"), char('}'))(input) +} + +/// parser combinators are constructed from the bottom up: +/// first we write parsers for the smallest elements (here a space character), +/// then we'll combine them in larger parsers +fn sp<'a>(i: &'a str) -> IResult<&'a str, &'a str> { + let chars = " \t\r\n"; + + // nom combinators like `take_while` return a function. That function is the + // parser,to which we can pass the input + take_while(move |c| chars.contains(c))(i) +} + +pub fn parse_script<'a, E: ParseError<&'a str>>(input: &'a str) -> IResult<&'a str, ScriptMeta, E> { + + + if let Ok(v) = elem_tag(input) { + println!("Found elem tag"); + if let Ok(v) = sp(v.0) { + preceded(sp, char(':')); + println!("ate some spaces"); + } + else { + println!("didn't eat spaces?"); + } + } + if let Ok(v) = comment(input) { + println!("Found comment tag") + } + + return Ok(("", ScriptMeta{})) +} + + +/* +// ( and any amount of bytes ). Returns the bytes between the () +fn parens(input: &str) -> IResult<&str, &str> { + delimited(char('('), is_not(")"), char(')'))(input) +} + +// `take_while_m_n` parses between `m` and `n` bytes (inclusive) that match +// a predicate. `parse_hex` here parses between 1 and 6 hexadecimal numerals. +let parse_hex = take_while_m_n(1, 6, |c: char| c.is_ascii_hexdigit()); +*/ \ No newline at end of file