Add line and column counting

Signed-off-by: xQuantx <[email protected]>
This commit is contained in:
xQuantx
2024-04-03 15:55:56 +02:00
parent 65c9856762
commit 13bc6f327d
+130 -108
View File
@@ -1,108 +1,130 @@
use regex::Regex; use regex::Regex;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::fmt; use std::fmt;
// Define token types pub struct LexerState {
#[derive(Debug, PartialEq, Clone, Copy)] line: usize,
pub enum TokenType { column: usize
Keyword, }
Newline,
Whitespace, // Define token types
Number, #[derive(Debug, PartialEq, Clone, Copy)]
Identifier, pub enum TokenType {
Ptr, Keyword,
Operator, Newline,
Round, Whitespace,
Curly, Number,
// EOF, Identifier,
} Ptr,
Operator,
#[derive(Clone)] Round,
pub struct Token { Curly,
pub token_type: TokenType, // EOF,
pub token_values: Vec<String> }
}
#[derive(Clone, Debug)]
impl<'a> fmt::Debug for Token { pub struct Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { pub token_type: TokenType,
write!(f, "(TokenType: {:?}, TokenValue: {})", self.token_type, self.token_values.join(", ")) pub token_values: Vec<String>,
} pub line: usize,
} pub column: usize
}
pub struct Node { /*
token_type: TokenType, impl<'a> fmt::Debug for Token {
token_regex: Lazy<Regex> fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
} write!(f, "(TokenType: {:?}, TokenValue: {})", self.token_type, self.token_values.join(", "))
}
const SYNTAX: [Node; 9] = [ }
Node { */
token_type: TokenType::Newline,
token_regex: Lazy::new(|| Regex::new(r"^\n+").unwrap()) pub struct Node {
}, token_type: TokenType,
Node { token_regex: Lazy<Regex>
token_type: TokenType::Whitespace, }
token_regex: Lazy::new(|| Regex::new(r"^\s+").unwrap())
}, const SYNTAX: [Node; 9] = [
Node { Node {
token_type: TokenType::Number, token_type: TokenType::Newline,
token_regex: Lazy::new(|| Regex::new(r"^\b(:?.)?(:?0[x|X])?\d+(:?.\d+)?\b").unwrap()) token_regex: Lazy::new(|| Regex::new(r"^\n+").unwrap()),
}, },
Node { Node {
token_type: TokenType::Keyword, token_type: TokenType::Whitespace,
token_regex: Lazy::new(|| Regex::new(r"^mut|try|catch|return|fn").unwrap()) token_regex: Lazy::new(|| Regex::new(r"^\s+").unwrap())
}, },
Node { Node {
token_type: TokenType::Identifier, token_type: TokenType::Number,
token_regex: Lazy::new(|| Regex::new(r"^[._a-zA-Z][a-zA-Z0-9_]*").unwrap()) token_regex: Lazy::new(|| Regex::new(r"^\b(:?.)?(:?0[x|X])?\d+(:?.\d+)?\b").unwrap())
}, },
Node { Node {
token_type: TokenType::Ptr, token_type: TokenType::Keyword,
token_regex: Lazy::new(|| Regex::new(r"^->").unwrap()) token_regex: Lazy::new(|| Regex::new(r"^mut|try|catch|return|fn").unwrap())
}, },
Node { Node {
token_type: TokenType::Operator, token_type: TokenType::Identifier,
token_regex: Lazy::new(|| Regex::new(r"^[\-|\+|\*]").unwrap()) token_regex: Lazy::new(|| Regex::new(r"^[._a-zA-Z][a-zA-Z0-9_]*").unwrap())
}, },
Node { Node {
token_type: TokenType::Round, token_type: TokenType::Ptr,
token_regex: Lazy::new(|| Regex::new(r"\((?:[^()]|(?R))*\)").unwrap()) token_regex: Lazy::new(|| Regex::new(r"^->").unwrap())
}, },
Node { Node {
token_type: TokenType::Curly, token_type: TokenType::Operator,
token_regex: Lazy::new(|| Regex::new(r"^[\{|\}]").unwrap()) token_regex: Lazy::new(|| Regex::new(r"^[\-|\+|\*]").unwrap())
} },
]; Node {
token_type: TokenType::Round,
pub fn lex(mut code: &str, use_whitespace: bool) -> Vec<Token> { token_regex: Lazy::new(|| Regex::new(r"\((?:[^()]|(?R))*\)").unwrap())
let mut tokens: Vec<Token> = Vec::new(); },
while !code.is_empty() { Node {
let mut is_match = false; token_type: TokenType::Curly,
for s in &SYNTAX { token_regex: Lazy::new(|| Regex::new(r"^[\{|\}]").unwrap())
if let Some(caps) = s.token_regex.captures(code) { }
is_match = true; ];
code = code.strip_prefix(&caps[0]).unwrap_or(code);
let mut vcaps: Vec<String> = Vec::new(); pub fn lex(mut code: &str, use_whitespace: bool) -> Vec<Token> {
let capsl = caps.len(); let mut state = LexerState { line: 1, column: 1 };
let mut x = 0; let mut tokens: Vec<Token> = Vec::new();
while x < capsl {
vcaps.push(caps[x].to_string()); while !code.is_empty() {
x+=1; let mut is_match = false;
} for s in &SYNTAX {
if (!use_whitespace && s.token_type!=TokenType::Whitespace) || use_whitespace { if let Some(caps) = s.token_regex.captures(code) {
tokens.push(Token { is_match = true;
token_type: s.token_type, code = code.strip_prefix(&caps[0]).unwrap_or(code);
token_values: vcaps, let mut vcaps: Vec<String> = Vec::new();
}); let capsl = caps.len();
} let mut x = 0;
} else { while x < capsl {
continue; vcaps.push(caps[x].to_string());
}; x+=1;
break; }
}
if !is_match { if (!use_whitespace && s.token_type!=TokenType::Whitespace) || use_whitespace {
println!("Error: syntax -> {code}"); tokens.push(Token {
break; token_type: s.token_type,
} token_values: vcaps,
} line: state.line,
tokens column: state.column
} });
println!("token found {:#?}", tokens.get(tokens.len()-1));
}
match s.token_type {
TokenType::Newline => {
state.line += caps[0].len();
state.column = 1;
},
_ => { state.column += caps[0].len(); }
}
} else {
continue;
};
break;
}
if !is_match {
println!("Error: syntax -> {code}");
break;
}
}
tokens
}