add lexer
This commit is contained in:
parent
05ad6afe72
commit
ad7a8ad879
3 changed files with 120 additions and 2 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
/target
|
||||
/res
|
||||
96
src/lexer.rs
Normal file
96
src/lexer.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#[derive(Debug, PartialEq)]
|
||||
pub enum Token {
|
||||
Number(i64),
|
||||
Ident(String),
|
||||
|
||||
// Operators
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
|
||||
// Parentheses
|
||||
LParen,
|
||||
RParen,
|
||||
LBrace,
|
||||
RBrace,
|
||||
LBracket,
|
||||
RBracket,
|
||||
|
||||
Semicolon
|
||||
}
|
||||
|
||||
pub struct Lexer {
|
||||
source: Vec<u8>,
|
||||
pos: usize
|
||||
}
|
||||
|
||||
impl Lexer {
|
||||
pub fn new(source: &str) -> Self {
|
||||
Self {
|
||||
source: source.as_bytes().to_vec(),
|
||||
pos: 0
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_whitespace(&mut self) {
|
||||
while matches!(self.peek(), Some(c) if c.is_ascii_whitespace()) {
|
||||
self.advance();
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(&mut self) {
|
||||
self.pos += 1;
|
||||
}
|
||||
|
||||
fn peek(&self) -> Option<u8> {
|
||||
self.source.get(self.pos).copied()
|
||||
}
|
||||
|
||||
fn number(&mut self) -> Option<Token> {
|
||||
let mut num = String::new();
|
||||
|
||||
while matches!(self.peek(), Some(b'0' ..= b'9')) {
|
||||
num.push(self.peek().unwrap() as char);
|
||||
self.advance();
|
||||
}
|
||||
|
||||
Some(Token::Number(num.parse().unwrap()))
|
||||
}
|
||||
|
||||
fn ident(&mut self) -> Option<Token> {
|
||||
let mut ident = String::new();
|
||||
|
||||
while matches!(self.peek(), Some(b'a' ..= b'z' | b'A' ..= b'Z')) {
|
||||
ident.push(self.peek().unwrap() as char);
|
||||
}
|
||||
|
||||
Some(Token::Ident(ident))
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> Option<Token> {
|
||||
self.skip_whitespace();
|
||||
match self.peek() {
|
||||
Some(b'0' ..= b'9') => self.number(),
|
||||
Some(b'a' ..= b'z' | b'A' ..= b'Z') => self.ident(),
|
||||
|
||||
Some(b'+') => {self.advance(); Some(Token::Add)},
|
||||
Some(b'-') => {self.advance(); Some(Token::Sub)},
|
||||
Some(b'*') => {self.advance(); Some(Token::Mul)},
|
||||
Some(b'/') => {self.advance(); Some(Token::Div)},
|
||||
Some(b'%') => {self.advance(); Some(Token::Mod)},
|
||||
|
||||
Some(b'(') => {self.advance(); Some(Token::LParen)},
|
||||
Some(b')') => {self.advance(); Some(Token::RParen)},
|
||||
Some(b'[') => {self.advance(); Some(Token::LBracket)},
|
||||
Some(b']') => {self.advance(); Some(Token::RBracket)},
|
||||
Some(b'{') => {self.advance(); Some(Token::LBrace)},
|
||||
Some(b'}') => {self.advance(); Some(Token::RBrace)},
|
||||
|
||||
Some(b';') => {self.advance(); Some(Token::Semicolon)}
|
||||
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/main.rs
25
src/main.rs
|
|
@ -1,3 +1,24 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use std::{fs::File, io::Read};
|
||||
|
||||
mod lexer;
|
||||
use lexer::Lexer;
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let args = std::env::args().collect::<Vec<String>>();
|
||||
|
||||
let mut source = String::new();
|
||||
File::open(&args[1])?.read_to_string(&mut source)?;
|
||||
|
||||
println!("{:?}", source);
|
||||
|
||||
let mut lexer = Lexer::new(&source);
|
||||
|
||||
loop {
|
||||
match lexer.next() {
|
||||
Some(tok) => print!("{tok:?}, "),
|
||||
None => break
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue