The Parser now uses the Lexer Tokens.
The parser can now handle code block start and end, and it can process the include file useing the Lexer Tokens. Previously it was trying to do this by reading lines.
This commit is contained in:
parent
282926f07c
commit
0ee91d15c9
@ -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<String>;
|
||||
|
||||
// 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);
|
||||
|
||||
/*
|
||||
//
|
||||
match Lexer::scan(&mut reader)
|
||||
{
|
||||
Ok(tokens) =>
|
||||
{
|
||||
// Parse the file and turn it into a set of compiled lines.
|
||||
lines = Parser::parse(&util, &mut reader);
|
||||
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
|
||||
}
|
||||
|
213
src/parser.rs
213
src/parser.rs
@ -1,77 +1,158 @@
|
||||
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<String>, line: String)
|
||||
fn flush_buffer(output: &mut Vec<String>, buffer: &mut String)
|
||||
{
|
||||
let start: usize;
|
||||
let end: usize;
|
||||
// Put the buffer into the output list.
|
||||
output.push(buffer.clone());
|
||||
|
||||
// Clear the buffer out.
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
///
|
||||
fn buffer_token(buffer: &mut String, token: &Token)
|
||||
{
|
||||
buffer.push_str(&token.to_string());
|
||||
}
|
||||
|
||||
///
|
||||
fn is_start_of_code_section(tokens: &Vec<Token>, 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() == "@"
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
///
|
||||
fn is_end_of_code_section(tokens: &Vec<Token>, 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() == "}"
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
///
|
||||
fn is_include_statement(tokens: &Vec<Token>, 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<'a> Parser<'a>
|
||||
{
|
||||
///
|
||||
pub fn new(util_ptr: &'a Util) -> Parser
|
||||
{
|
||||
Parser
|
||||
{
|
||||
util: util_ptr
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn parse(&mut self, tokens: Vec<Token>) -> Vec<String>
|
||||
{
|
||||
let mut is_in_code_block: bool;
|
||||
let mut position: usize;
|
||||
let mut include_file: PathBuf;
|
||||
let mut processed_line: String;
|
||||
let mut buffer: String;
|
||||
let mut output: Vec<String>;
|
||||
|
||||
// Copy the given line.
|
||||
processed_line = line.clone();
|
||||
// Create a new set of lines to hold the parsed data.
|
||||
output = Vec::new();
|
||||
|
||||
// Remove any code block brackets.
|
||||
processed_line = processed_line.replace("{@", "");
|
||||
processed_line = processed_line.replace("@}", "");
|
||||
// Setup the String buffer.
|
||||
buffer = String::new();
|
||||
|
||||
// Just handling the include code right now.
|
||||
if processed_line.contains("include") == true
|
||||
// Parse the tokens passed in.
|
||||
is_in_code_block = false;
|
||||
position = 0usize;
|
||||
while position < tokens.len()
|
||||
{
|
||||
// Parse one or more include statements on a line.
|
||||
if is_in_code_block == true
|
||||
{
|
||||
if is_end_of_code_section(&tokens, &position) == true
|
||||
{
|
||||
// Flush any previous buffer.
|
||||
flush_buffer(&mut output, &mut buffer);
|
||||
|
||||
// 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;
|
||||
// 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);
|
||||
}
|
||||
|
||||
None =>
|
||||
else if is_include_statement(&tokens, &position) == true
|
||||
{
|
||||
start = 0usize;
|
||||
}
|
||||
}
|
||||
// Flush any previous buffer.
|
||||
flush_buffer(&mut output, &mut buffer);
|
||||
|
||||
match processed_line[start..].find("\"")
|
||||
{
|
||||
Some(location) =>
|
||||
{
|
||||
end = start + location;
|
||||
}
|
||||
|
||||
None =>
|
||||
{
|
||||
end = start + 0usize;
|
||||
}
|
||||
}
|
||||
|
||||
include_file = PathBuf::from(&processed_line[start..end]);
|
||||
// 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 util.get_include_file_path(&include_file)
|
||||
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(util, &file));
|
||||
output.push(read_file(self.util, &file));
|
||||
}
|
||||
|
||||
None =>
|
||||
@ -80,42 +161,50 @@ fn process_line(util: &Util, output: &mut Vec<String>, line: String)
|
||||
include_file);
|
||||
}
|
||||
}
|
||||
|
||||
// Five tokens have been read.
|
||||
position += 5;
|
||||
|
||||
println!("{}: Is include statement.", position);
|
||||
}
|
||||
else
|
||||
{
|
||||
output.push(processed_line);
|
||||
// This token is nothing interesting, so
|
||||
// process it generally and move the position forward.
|
||||
buffer_token(&mut buffer, &tokens[position]);
|
||||
|
||||
position += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Parser
|
||||
else
|
||||
{
|
||||
///
|
||||
pub fn parse(util: &Util, reader: &mut Reader) -> Vec<String>
|
||||
if is_start_of_code_section(&tokens, &position) == true
|
||||
{
|
||||
let mut output: Vec<String>;
|
||||
// Flush any previous buffer.
|
||||
flush_buffer(&mut output, &mut buffer);
|
||||
|
||||
// Create a new set of lines to hold the parsed data.
|
||||
output = Vec::new();
|
||||
// Mark that we are in a code block.
|
||||
is_in_code_block = true;
|
||||
|
||||
// Start parsing all the given lines.
|
||||
while reader.is_eob() == false
|
||||
{
|
||||
match reader.consume_line()
|
||||
{
|
||||
Ok(line) =>
|
||||
{
|
||||
process_line(util, &mut output, line)
|
||||
// Two tokens have been read.
|
||||
position += 2;
|
||||
|
||||
println!("{}: Is start of code block.", position);
|
||||
}
|
||||
|
||||
Err(error) =>
|
||||
else
|
||||
{
|
||||
error!("{}", error);
|
||||
// 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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user