Initial commit. Working on lexer
This commit is contained in:
commit
c84e73756f
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
target/
|
14
Cargo.lock
generated
Normal file
14
Cargo.lock
generated
Normal file
|
@ -0,0 +1,14 @@
|
|||
[[package]]
|
||||
name = "interpreter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "interpreter"
|
||||
version = "0.1.0"
|
||||
authors = ["ishanjain28 <ishanjain28@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.2.0"
|
104
src/lexer/mod.rs
Normal file
104
src/lexer/mod.rs
Normal file
|
@ -0,0 +1,104 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
lazy_static! {
|
||||
static ref IDENTMAP: HashMap<&'static str, Token> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert("fn", Token::Function);
|
||||
m.insert("let", Token::Let);
|
||||
m
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Token {
|
||||
Illegal,
|
||||
EOF,
|
||||
|
||||
// Identifiers
|
||||
Int(i64),
|
||||
|
||||
// Operators
|
||||
Assign,
|
||||
Plus,
|
||||
Multiply,
|
||||
Divide,
|
||||
Subtract,
|
||||
|
||||
// Delimiter
|
||||
Comma,
|
||||
Semicolon,
|
||||
LParen,
|
||||
RParen,
|
||||
LBrace,
|
||||
RBrace,
|
||||
|
||||
// Keywords
|
||||
Function,
|
||||
Let,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lexer {
|
||||
input: Vec<char>,
|
||||
position: usize,
|
||||
read_position: usize,
|
||||
ch: char,
|
||||
}
|
||||
|
||||
impl Lexer {
|
||||
pub fn new(input: &str) -> Lexer {
|
||||
Lexer {
|
||||
input: input.chars().collect::<Vec<char>>(),
|
||||
position: 0,
|
||||
read_position: 0,
|
||||
ch: '0',
|
||||
}
|
||||
}
|
||||
|
||||
fn read_char(&mut self) {
|
||||
if self.read_position >= self.input.len() {
|
||||
self.ch = '0';
|
||||
} else {
|
||||
self.ch = self.input[self.read_position];
|
||||
}
|
||||
|
||||
self.position = self.read_position;
|
||||
self.read_position += 1;
|
||||
}
|
||||
|
||||
fn read_identifier(&mut self) -> String {
|
||||
let pos = self.position;
|
||||
while is_letter(self.ch) {
|
||||
self.read_char();
|
||||
}
|
||||
|
||||
self.input[pos..self.position].iter().collect::<String>()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Lexer {
|
||||
type Item = Token;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.read_char();
|
||||
|
||||
match self.ch {
|
||||
'=' => Some(Token::Assign),
|
||||
'+' => Some(Token::Plus),
|
||||
'*' => Some(Token::Multiply),
|
||||
'/' => Some(Token::Divide),
|
||||
'-' => Some(Token::Subtract),
|
||||
',' => Some(Token::Comma),
|
||||
';' => Some(Token::Semicolon),
|
||||
'(' => Some(Token::LParen),
|
||||
')' => Some(Token::RParen),
|
||||
'[' => Some(Token::LBrace),
|
||||
']' => Some(Token::RBrace),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_letter(c: char) -> bool {
|
||||
c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'
|
||||
}
|
34
src/main.rs
Normal file
34
src/main.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
mod lexer;
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use lexer::{Lexer, Token};
|
||||
#[test]
|
||||
fn new_token() {
|
||||
let input = "=+()[],;";
|
||||
let expected = vec![
|
||||
Token::Assign,
|
||||
Token::Plus,
|
||||
Token::LParen,
|
||||
Token::RParen,
|
||||
Token::Comma,
|
||||
Token::Semicolon,
|
||||
Token::EOF,
|
||||
];
|
||||
|
||||
let tokenized_output = Lexer::new(input).collect::<Vec<Token>>();
|
||||
|
||||
println!("{:?}", tokenized_output);
|
||||
assert_eq!(expected.len(), tokenized_output.len());
|
||||
|
||||
for (exp, actual) in expected.into_iter().zip(tokenized_output) {
|
||||
assert_eq!(actual, exp);
|
||||
println!("{:?} {:?}", actual, exp);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user