diff --git a/src/compiler.rs b/src/compiler.rs index d8bf99a..6ffcfc7 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -3,6 +3,8 @@ use std::io::Write; use std::path::Path; use ::lexer::Lexer; +use ::lexer::Token; +use ::lexer::TokenTypes; use ::parser::Parser; use ::reader::Reader; use ::util::Util; @@ -29,6 +31,7 @@ pub fn read_file(util: &Util, input_path: &Path) -> String { let mut output: String; let mut reader: Reader; + let mut parser: Parser; let mut lines: Vec; // Create the output string of the compiled file. @@ -37,18 +40,28 @@ pub fn read_file(util: &Util, input_path: &Path) -> String // Create a Reader from the given input file. reader = Reader::from_file(input_path); - Lexer::scan(&mut reader); - - /* - // Parse the file and turn it into a set of compiled lines. - lines = Parser::parse(&util, &mut reader); - - // Add all these lines to the final output. - for line in lines.into_iter() + // + match Lexer::scan(&mut reader) { - output.push_str(&line); + Ok(tokens) => + { + // Parse the file and turn it into a set of compiled lines. + parser = Parser::new(util); + lines = parser.parse(tokens); + + // Add all these lines to the final output. + for line in lines.into_iter() + { + output.push_str(&line); + } + } + + Err(error) => + { + error!("{}", error); + } } -*/ + // Return the final output. output } diff --git a/src/parser.rs b/src/parser.rs index 78e6954..9913a1b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,121 +1,210 @@ use std::path::PathBuf; use ::compiler::read_file; +use ::lexer::Token; +use ::lexer::TokenTypes; use ::reader::Reader; use ::util::Util; /// -pub enum Parser +pub struct Parser<'a> { + /// + util: &'a Util } /// -fn process_line(util: &Util, output: &mut Vec, line: String) +fn flush_buffer(output: &mut Vec, buffer: &mut String) { - let start: usize; - let end: usize; - let mut include_file: PathBuf; - let mut processed_line: String; + // Put the buffer into the output list. + output.push(buffer.clone()); - // Copy the given line. - processed_line = line.clone(); + // Clear the buffer out. + buffer.clear(); +} - // Remove any code block brackets. - processed_line = processed_line.replace("{@", ""); - processed_line = processed_line.replace("@}", ""); +/// +fn buffer_token(buffer: &mut String, token: &Token) +{ + buffer.push_str(&token.to_string()); +} - // Just handling the include code right now. - if processed_line.contains("include") == true +/// +fn is_start_of_code_section(tokens: &Vec, pos: &usize) -> bool +{ + // Check if this is the start of a code section. + if *pos + 1usize < tokens.len() && + tokens[*pos].get_type() == TokenTypes::Symbol && + tokens[*pos + 1usize].get_type() == TokenTypes::Symbol && + tokens[*pos].to_string() == "{" && + tokens[*pos + 1usize].to_string() == "@" { - // Parse one or more include statements on a line. - - // Cut out the include statement so it can be processed. - match processed_line.find("\"") - { - Some(location) => - { - // Add one to move past the quote mark. - start = location + 1usize; - } - - None => - { - start = 0usize; - } - } - - match processed_line[start..].find("\"") - { - Some(location) => - { - end = start + location; - } - - None => - { - end = start + 0usize; - } - } - - include_file = PathBuf::from(&processed_line[start..end]); - - // Try to find the include file in one of the - // include directories. - match util.get_include_file_path(&include_file) - { - Some(file) => - { - // Process the include file found and add it to - // the output list. - output.push(read_file(util, &file)); - } - - None => - { - error!("Unable to find desired include file: {:?}", - include_file); - } - } + return true; } - else + + false +} + +/// +fn is_end_of_code_section(tokens: &Vec, pos: &usize) -> bool +{ + // Check if this is the start of a code section. + if *pos + 1usize < tokens.len() && + tokens[*pos].get_type() == TokenTypes::Symbol && + tokens[*pos + 1usize].get_type() == TokenTypes::Symbol && + tokens[*pos].to_string() == "@" && + tokens[*pos + 1usize].to_string() == "}" { - output.push(processed_line); + return true; } + + false +} + +/// +fn is_include_statement(tokens: &Vec, pos: &usize) -> bool +{ + // Check if this is an include statement. + if *pos + 4usize < tokens.len() && + tokens[*pos + 0usize].get_type() == TokenTypes::Keyword && + tokens[*pos + 1usize].get_type() == TokenTypes::Symbol && + tokens[*pos + 2usize].get_type() == TokenTypes::StaticString && + tokens[*pos + 3usize].get_type() == TokenTypes::Symbol && + tokens[*pos + 4usize].get_type() == TokenTypes::Symbol && + tokens[*pos + 0usize].to_string() == "include" && + tokens[*pos + 1usize].to_string() == "(" && + tokens[*pos + 3usize].to_string() == ")" && + tokens[*pos + 4usize].to_string() == ";" + { + return true; + } + + false } -impl Parser +impl<'a> Parser<'a> { /// - pub fn parse(util: &Util, reader: &mut Reader) -> Vec + pub fn new(util_ptr: &'a Util) -> Parser { + Parser + { + util: util_ptr + } + } + + /// + pub fn parse(&mut self, tokens: Vec) -> Vec + { + let mut is_in_code_block: bool; + let mut position: usize; + let mut include_file: PathBuf; + let mut buffer: String; let mut output: Vec; // Create a new set of lines to hold the parsed data. output = Vec::new(); - // Start parsing all the given lines. - while reader.is_eob() == false - { - match reader.consume_line() - { - Ok(line) => - { - process_line(util, &mut output, line) - } + // Setup the String buffer. + buffer = String::new(); - Err(error) => + // Parse the tokens passed in. + is_in_code_block = false; + position = 0usize; + while position < tokens.len() + { + if is_in_code_block == true + { + if is_end_of_code_section(&tokens, &position) == true { - error!("{}", error); + // Flush any previous buffer. + flush_buffer(&mut output, &mut buffer); + + // Mark that we are no longer in a code block. + is_in_code_block = false; + + // Two tokens have been read. + position += 2; + + println!("{}: Is end of code block.", position); + } + else if is_include_statement(&tokens, &position) == true + { + // Flush any previous buffer. + flush_buffer(&mut output, &mut buffer); + + // Convert the String portion to a PathBuf. + include_file = + PathBuf::from( + tokens[position + 2usize].to_string().replace("\"", "")); + + // Try to find the include file in one of the + // include directories. + match self.util.get_include_file_path(&include_file) + { + Some(file) => + { + // Process the include file found and add it to + // the output list. + output.push(read_file(self.util, &file)); + } + + None => + { + error!("Unable to find desired include file: {:?}", + include_file); + } + } + + // Five tokens have been read. + position += 5; + + println!("{}: Is include statement.", position); + } + else + { + // This token is nothing interesting, so + // process it generally and move the position forward. + buffer_token(&mut buffer, &tokens[position]); + + position += 1; + } + } + else + { + if is_start_of_code_section(&tokens, &position) == true + { + // Flush any previous buffer. + flush_buffer(&mut output, &mut buffer); + + // Mark that we are in a code block. + is_in_code_block = true; + + // Two tokens have been read. + position += 2; + + println!("{}: Is start of code block.", position); + } + else + { + // This token is nothing interesting, so + // process it generally and move the position forward. + buffer_token(&mut buffer, &tokens[position]); + + position += 1; } } } + // Flush any left over buffer. + flush_buffer(&mut output, &mut buffer); + // Return the parsed input. output }