[Compiler] Refactor string lexer to include starting and closing double quotes
This commit is contained in:
parent
ccfb95956c
commit
c445f8bb00
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
- Scan single line comments
|
- Scan single line comments
|
||||||
- Refactor String token to include double quotes (") in its content
|
- Refactor String token to include double quotes (") in its content
|
||||||
|
- Refactor datachecking of semantic analysis
|
||||||
|
|
||||||
## v0.0.4
|
## v0.0.4
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ fn get_line(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
error_handling::{PrintableError, SyntaxError, MistiError},
|
error_handling::{MistiError, PrintableError, SyntaxError},
|
||||||
lexic::get_tokens,
|
lexic::get_tokens,
|
||||||
syntax::construct_ast,
|
syntax::construct_ast,
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,7 @@ use crate::lexic::{token, utils, LexResult};
|
|||||||
/// This function assumes that `start_pos` is after the first double quote,
|
/// This function assumes that `start_pos` is after the first double quote,
|
||||||
/// e.g. if the input is `"hello"`, `start_pos == 1`
|
/// e.g. if the input is `"hello"`, `start_pos == 1`
|
||||||
pub fn scan(chars: &Vec<char>, start_pos: usize) -> LexResult {
|
pub fn scan(chars: &Vec<char>, start_pos: usize) -> LexResult {
|
||||||
scan_impl(chars, start_pos, String::from(""))
|
scan_impl(chars, start_pos, String::from("\""))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursive function that does the scanning
|
/// Recursive function that does the scanning
|
||||||
@ -16,10 +16,11 @@ pub fn scan_impl(chars: &Vec<char>, start_pos: usize, current: String) -> LexRes
|
|||||||
// start_pos is the position where the token ENDS, not where it STARTS,
|
// start_pos is the position where the token ENDS, not where it STARTS,
|
||||||
// so this is used to retrieve the original START position of the token
|
// so this is used to retrieve the original START position of the token
|
||||||
// 1 is added to account for the opening `"`
|
// 1 is added to account for the opening `"`
|
||||||
let current_len = current.len() + 1;
|
let current_len = current.len();
|
||||||
|
|
||||||
|
let final_str = format!("{}\"", current);
|
||||||
LexResult::Some(
|
LexResult::Some(
|
||||||
token::new_string(current, start_pos - current_len),
|
token::new_string(final_str, start_pos - current_len),
|
||||||
start_pos + 1,
|
start_pos + 1,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -77,7 +78,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(2, next);
|
assert_eq!(2, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("", token.value);
|
assert_eq!("\"\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -91,7 +92,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(15, next);
|
assert_eq!(15, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("Hello, world!", token.value);
|
assert_eq!("\"Hello, world!\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -116,7 +117,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(14, next);
|
assert_eq!(14, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("Sample\\ntext", token.value);
|
assert_eq!("\"Sample\\ntext\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -127,7 +128,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(14, next);
|
assert_eq!(14, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("Sample\\\"text", token.value);
|
assert_eq!("\"Sample\\\"text\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -138,7 +139,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(14, next);
|
assert_eq!(14, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("Sample\\rtext", token.value);
|
assert_eq!("\"Sample\\rtext\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -149,7 +150,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(14, next);
|
assert_eq!(14, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("Sample\\\\text", token.value);
|
assert_eq!("\"Sample\\\\text\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -160,7 +161,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(14, next);
|
assert_eq!(14, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("Sample\\ttext", token.value);
|
assert_eq!("\"Sample\\ttext\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -171,7 +172,7 @@ mod tests {
|
|||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(14, next);
|
assert_eq!(14, next);
|
||||||
assert_eq!(TokenType::String, token.token_type);
|
assert_eq!(TokenType::String, token.token_type);
|
||||||
assert_eq!("Sample\\ text", token.value);
|
assert_eq!("\"Sample\\ text\"", token.value);
|
||||||
assert_eq!(0, token.position);
|
assert_eq!(0, token.position);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
|
@ -10,12 +10,12 @@ use super::semantic;
|
|||||||
use super::syntax;
|
use super::syntax;
|
||||||
|
|
||||||
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase
|
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase
|
||||||
fn compile(input: &String) {
|
fn compile(input: &String, symbol_table: &mut SymbolTable) {
|
||||||
let tokens = lexic::get_tokens(input);
|
let tokens = lexic::get_tokens(input);
|
||||||
|
|
||||||
match tokens {
|
match tokens {
|
||||||
Ok(tokens) => {
|
Ok(tokens) => {
|
||||||
build_ast(input, tokens);
|
build_ast(input, tokens, symbol_table);
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let chars: Vec<char> = input.chars().into_iter().collect();
|
let chars: Vec<char> = input.chars().into_iter().collect();
|
||||||
@ -27,13 +27,12 @@ fn compile(input: &String) {
|
|||||||
/// Executes Syntax analysis, and for now, Semantic analysis and Code generation.
|
/// Executes Syntax analysis, and for now, Semantic analysis and Code generation.
|
||||||
///
|
///
|
||||||
/// Prints the generated code in stdin
|
/// Prints the generated code in stdin
|
||||||
fn build_ast(input: &String, tokens: Vec<Token>) {
|
fn build_ast(input: &String, tokens: Vec<Token>, symbol_table: &mut SymbolTable) {
|
||||||
let ast = syntax::construct_ast(&tokens);
|
let ast = syntax::construct_ast(&tokens);
|
||||||
|
|
||||||
match ast {
|
match ast {
|
||||||
Ok(mut ast) => {
|
Ok( ast) => {
|
||||||
let mut symbol_table = SymbolTable::new();
|
semantic::check_ast(& ast, symbol_table);
|
||||||
semantic::check_ast(&mut ast, &mut symbol_table);
|
|
||||||
|
|
||||||
let js_code = codegen::codegen(&ast);
|
let js_code = codegen::codegen(&ast);
|
||||||
println!("{}", js_code)
|
println!("{}", js_code)
|
||||||
@ -45,17 +44,16 @@ fn build_ast(input: &String, tokens: Vec<Token>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Executes the REPL, reading from stdin, compiling and emitting JS to stdout
|
/// Executes the REPL, reading from stdin, compiling and emitting JS to stdout
|
||||||
pub fn run() -> io::Result<()> {
|
pub fn run() -> io::Result<()> {
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
|
let mut repl_symbol_table = SymbolTable::new();
|
||||||
|
|
||||||
println!("REPL: Enter expressions to evaluate. Type Ctrl-D to exit.");
|
println!("REPL: Enter expressions to evaluate. Type Ctrl-D to exit.");
|
||||||
loop {
|
loop {
|
||||||
print!("> ");
|
print!("> ");
|
||||||
let _ = io::stdout().flush();
|
io::stdout().flush()?;
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
let read = stdin.read_line(&mut buffer);
|
let read = stdin.read_line(&mut buffer);
|
||||||
|
|
||||||
@ -65,7 +63,7 @@ pub fn run() -> io::Result<()> {
|
|||||||
break Ok(());
|
break Ok(());
|
||||||
}
|
}
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
compile(&buffer);
|
compile(&buffer, &mut repl_symbol_table);
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
eprintln!("Error reading stdin.");
|
eprintln!("Error reading stdin.");
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/// Represents a qualified datatype of the compiler.
|
/// Represents a qualified datatype of the compiler.
|
||||||
///
|
///
|
||||||
/// A datatype is composed of a path, e.g. `base.Str`, `base.Num`
|
/// A datatype is composed of a path, e.g. `base.Str`, `base.Num`
|
||||||
@ -7,22 +6,27 @@ pub struct Datatype {
|
|||||||
t: String,
|
t: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Datatype {
|
impl Datatype {
|
||||||
pub fn new(t: String) -> Datatype {
|
pub fn new(t: String) -> Datatype {
|
||||||
Datatype { t }
|
Datatype { t }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str() -> Datatype {
|
pub fn str() -> Datatype {
|
||||||
Datatype { t: String::from("base.Str") }
|
Datatype {
|
||||||
|
t: String::from("base.Str"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num() -> Datatype {
|
pub fn num() -> Datatype {
|
||||||
Datatype { t: String::from("base.Num") }
|
Datatype {
|
||||||
|
t: String::from("base.Num"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bool() -> Datatype {
|
pub fn bool() -> Datatype {
|
||||||
Datatype { t: String::from("base.Bool") }
|
Datatype {
|
||||||
|
t: String::from("base.Bool"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone(&self) -> Datatype {
|
pub fn clone(&self) -> Datatype {
|
||||||
@ -30,8 +34,6 @@ impl Datatype {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Datatype;
|
use super::Datatype;
|
||||||
|
@ -1,25 +1,101 @@
|
|||||||
use super::ast_types::{Binding, Expression, ModuleAST};
|
use super::ast_types::{Binding, ModuleAST};
|
||||||
use super::symbol_table::{SymbolTable, _BOOLEAN, _NUMBER, _STRING};
|
use super::symbol_table::SymbolTable;
|
||||||
|
|
||||||
mod datatype;
|
mod datatype;
|
||||||
mod type_check;
|
mod type_check;
|
||||||
|
|
||||||
|
use type_check::Typed;
|
||||||
|
|
||||||
pub use datatype::Datatype;
|
pub use datatype::Datatype;
|
||||||
|
|
||||||
/// Checks the AST. In the future should return a list of errors.
|
/// Checks the AST. In the future should return a list of errors.
|
||||||
pub fn check_ast<'a>(ast: &'a mut ModuleAST, symbol_table: &'a mut SymbolTable) {
|
pub fn check_ast<'a>(ast: &'a ModuleAST, symbol_table: &'a mut SymbolTable) {
|
||||||
|
for binding in ast.bindings.iter() {
|
||||||
|
match binding {
|
||||||
|
Binding::Val(b) => {
|
||||||
|
let datatype = b.expression.t(symbol_table);
|
||||||
|
let identifier = b.identifier;
|
||||||
|
|
||||||
|
// TODO: check datatype of a explicit datatype, e.g. `Str val x = 322`
|
||||||
|
|
||||||
|
symbol_table.insert(identifier.as_str(), datatype);
|
||||||
|
}
|
||||||
|
Binding::Var(b) => {
|
||||||
|
let datatype = b.expression.t(symbol_table);
|
||||||
|
let identifier = b.identifier;
|
||||||
|
|
||||||
|
// TODO: check datatype of a explicit datatype, e.g. `Str val x = 322`
|
||||||
|
|
||||||
|
symbol_table.insert(identifier.as_str(), datatype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod t {
|
||||||
use crate::lexic;
|
use crate::ast_types::Expression;
|
||||||
use crate::symbol_table::_BOOLEAN;
|
|
||||||
use crate::symbol_table::_STRING;
|
|
||||||
use crate::syntax;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_insert_into_symbol_table() {
|
||||||
|
let s1 = String::from("id");
|
||||||
|
let s2 = String::from("322");
|
||||||
|
let binding = Binding::Val(crate::ast_types::ValBinding {
|
||||||
|
datatype: None,
|
||||||
|
identifier: &s1,
|
||||||
|
expression: Expression::Number(&s2),
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut table = SymbolTable::new();
|
||||||
|
|
||||||
|
check_ast(
|
||||||
|
&ModuleAST {
|
||||||
|
bindings: vec![binding],
|
||||||
|
},
|
||||||
|
&mut table,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(table.has_id(&String::from("id")));
|
||||||
|
assert!(table.check_type(&String::from("id"), Datatype::num()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_insert_id_reference() {
|
||||||
|
let s1 = String::from("id");
|
||||||
|
let s2 = String::from("322");
|
||||||
|
let binding = Binding::Val(crate::ast_types::ValBinding {
|
||||||
|
datatype: None,
|
||||||
|
identifier: &s1,
|
||||||
|
expression: Expression::Number(&s2),
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut table = SymbolTable::new();
|
||||||
|
|
||||||
|
check_ast(
|
||||||
|
&ModuleAST {
|
||||||
|
bindings: vec![binding],
|
||||||
|
},
|
||||||
|
&mut table,
|
||||||
|
);
|
||||||
|
|
||||||
|
let s1 = String::from("id2");
|
||||||
|
let s2 = String::from("id");
|
||||||
|
let binding = Binding::Val(crate::ast_types::ValBinding {
|
||||||
|
datatype: None,
|
||||||
|
identifier: &s1,
|
||||||
|
expression: Expression::Identifier(&s2),
|
||||||
|
});
|
||||||
|
|
||||||
|
check_ast(
|
||||||
|
&ModuleAST {
|
||||||
|
bindings: vec![binding],
|
||||||
|
},
|
||||||
|
&mut table,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(table.has_id(&String::from("id2")));
|
||||||
|
assert!(table.check_type(&String::from("id2"), Datatype::num()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,27 @@ use crate::{ast_types::Expression, symbol_table::SymbolTable};
|
|||||||
|
|
||||||
use super::datatype::Datatype;
|
use super::datatype::Datatype;
|
||||||
|
|
||||||
trait Typed<'a> {
|
pub trait Typed<'a> {
|
||||||
fn t(&self, symbol_table: &'a mut SymbolTable) -> Datatype;
|
fn t(&self, symbol_table: &'a mut SymbolTable) -> Datatype;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Typed<'a> for Expression<'a> {
|
impl<'a> Typed<'a> for Expression<'a> {
|
||||||
|
/// Returns the Datatype of this Expression
|
||||||
fn t(&self, symbol_table: &'a mut SymbolTable) -> Datatype {
|
fn t(&self, symbol_table: &'a mut SymbolTable) -> Datatype {
|
||||||
match self {
|
match self {
|
||||||
Expression::Number(_) => Datatype::num(),
|
Expression::Number(_) => Datatype::num(),
|
||||||
Expression::String(_) => Datatype::str(),
|
Expression::String(_) => Datatype::str(),
|
||||||
Expression::Boolean(_) => Datatype::bool(),
|
Expression::Boolean(_) => Datatype::bool(),
|
||||||
Expression::Identifier(id) => {
|
Expression::Identifier(id) => {
|
||||||
let res = symbol_table.get_type(id).unwrap();
|
let res = symbol_table
|
||||||
|
.get_type(id)
|
||||||
|
.expect("SEMANTIC: identifier doesn't exist in Symbol table");
|
||||||
res.clone()
|
res.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod t {
|
mod t {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -59,4 +60,3 @@ mod t {
|
|||||||
assert!(exp.t(&mut table) == Datatype::num());
|
assert!(exp.t(&mut table) == Datatype::num());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,6 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use crate::semantic::Datatype;
|
use crate::semantic::Datatype;
|
||||||
|
|
||||||
// Primitive datatypes
|
|
||||||
pub const _NUMBER: &str = "Num";
|
|
||||||
pub const _STRING: &str = "Str";
|
|
||||||
pub const _BOOLEAN: &str = "Bool";
|
|
||||||
|
|
||||||
pub struct SymbolTable {
|
pub struct SymbolTable {
|
||||||
/// For now just stores identifiers and datatypes
|
/// For now just stores identifiers and datatypes
|
||||||
table: HashMap<String, Datatype>,
|
table: HashMap<String, Datatype>,
|
||||||
@ -22,8 +17,7 @@ impl SymbolTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, identifier: &str, datatype: Datatype) {
|
pub fn insert(&mut self, identifier: &str, datatype: Datatype) {
|
||||||
self.table
|
self.table.insert(String::from(identifier), datatype);
|
||||||
.insert(String::from(identifier), datatype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_id(&self, identifier: &String) -> bool {
|
pub fn has_id(&self, identifier: &String) -> bool {
|
||||||
@ -45,9 +39,7 @@ impl SymbolTable {
|
|||||||
|
|
||||||
/// Returns the Datatype of a given identifier
|
/// Returns the Datatype of a given identifier
|
||||||
pub fn get_type(&self, identifier: &String) -> Option<&Datatype> {
|
pub fn get_type(&self, identifier: &String) -> Option<&Datatype> {
|
||||||
self.table
|
self.table.get(identifier).and_then(|value| Some(value))
|
||||||
.get(identifier)
|
|
||||||
.and_then(|value| Some(value))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ mod tests {
|
|||||||
let expression = try_parse(&tokens, 0).unwrap();
|
let expression = try_parse(&tokens, 0).unwrap();
|
||||||
|
|
||||||
match expression {
|
match expression {
|
||||||
Expression::String(value) => assert_eq!("Hello", value),
|
Expression::String(value) => assert_eq!("\"Hello\"", value),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::ast_types::Binding;
|
use crate::ast_types::Binding;
|
||||||
use crate::error_handling::{SyntaxError, MistiError};
|
use crate::error_handling::{MistiError, SyntaxError};
|
||||||
|
|
||||||
use super::token::Token;
|
use super::token::Token;
|
||||||
|
|
||||||
@ -41,13 +41,8 @@ pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST<'a>, MistiE
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_construct<'a>(tokens: &'a Vec<Token>, current_pos: usize) -> SyntaxResult {
|
fn next_construct<'a>(tokens: &'a Vec<Token>, current_pos: usize) -> SyntaxResult {
|
||||||
None.or_else(|| binding::try_parse(tokens, 0))
|
None.or_else(|| binding::try_parse(tokens, current_pos))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
SyntaxResult::Err(SyntaxError {
|
SyntaxResult::None
|
||||||
reason: String::from("Unrecognized token"),
|
|
||||||
// FIXME: This should get the position of the _token_ that current_pos points to
|
|
||||||
error_start: current_pos,
|
|
||||||
error_end: current_pos,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,7 @@ pub struct Token {
|
|||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
pub fn get_end_position(&self) -> usize {
|
pub fn get_end_position(&self) -> usize {
|
||||||
match self.token_type {
|
self.position + self.value.len()
|
||||||
TokenType::String => self.position + self.value.len() + 2,
|
|
||||||
_ => self.position + self.value.len(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user