Initial commit. Working on lexer

This commit is contained in:
Ishan Jain 2019-01-14 00:39:27 +05:30
commit c84e73756f
5 changed files with 160 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/

14
Cargo.lock generated Normal file
View 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
View 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
View 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
View 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);
}
}
}