Start implementing lexer
This commit is contained in:
parent
41348cf4c2
commit
01729beb5f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "nek-lang"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
67
src/lexer.rs
Normal file
67
src/lexer.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
use std::{iter::Peekable, str::Chars};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Token {
|
||||||
|
I64(i64),
|
||||||
|
|
||||||
|
Add,
|
||||||
|
|
||||||
|
Mul,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Lexer<'a> {
|
||||||
|
code: Peekable<Chars<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Lexer<'a> {
|
||||||
|
fn new(code: &'a str) -> Self {
|
||||||
|
let code = code.chars().peekable();
|
||||||
|
Self { code }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lex(&mut self) -> Vec<Token> {
|
||||||
|
let mut tokens = Vec::new();
|
||||||
|
|
||||||
|
while let Some(ch) = self.next() {
|
||||||
|
match ch {
|
||||||
|
' ' => (),
|
||||||
|
'0'..='9' => {
|
||||||
|
let mut sval = String::from(ch);
|
||||||
|
|
||||||
|
// Do as long as a next char exists and it is a numeric char
|
||||||
|
while let Some('0'..='9') = self.peek() {
|
||||||
|
// The next char is verified to be Some, so unwrap is safe
|
||||||
|
sval.push(self.next().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: We only added numeric chars to the string, but the conversion could still fail
|
||||||
|
tokens.push(Token::I64(sval.parse().unwrap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
'+' => tokens.push(Token::Add),
|
||||||
|
'*' => tokens.push(Token::Mul),
|
||||||
|
|
||||||
|
//TODO: Don't panic, keep calm
|
||||||
|
_ => panic!("Lexer encountered unexpected char: '{}'", ch),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Advance to next character and return the removed char
|
||||||
|
fn next(&mut self) -> Option<char> {
|
||||||
|
self.code.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shows next character
|
||||||
|
fn peek(&mut self) -> Option<char> {
|
||||||
|
self.code.peek().copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lex(code: &str) -> Vec<Token> {
|
||||||
|
let mut lexer = Lexer::new(code);
|
||||||
|
lexer.lex()
|
||||||
|
}
|
||||||
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod lexer;
|
||||||
|
|
||||||
12
src/main.rs
Normal file
12
src/main.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use nek_lang::lexer::lex;
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let code = "33 +5*2";
|
||||||
|
|
||||||
|
let tokens = lex(code);
|
||||||
|
|
||||||
|
println!("{:?}", tokens);
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user