Implement basic lexer
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@
|
|||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
.vscode
|
||||||
|
|||||||
16
src/lexer.rs
16
src/lexer.rs
@@ -1,4 +1,4 @@
|
|||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
Identifier(String),
|
Identifier(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
@@ -6,13 +6,19 @@ pub enum Token {
|
|||||||
LeftRoundBracket,
|
LeftRoundBracket,
|
||||||
RightRoundBracket,
|
RightRoundBracket,
|
||||||
Quote,
|
Quote,
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tokens = Vec<Token>;
|
impl Default for Token {
|
||||||
|
fn default() -> Token {
|
||||||
|
Token::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read(code: &str) -> () {
|
pub type Tokens = Vec<Token>;
|
||||||
let tokens = scan(code, 0, vec![]);
|
|
||||||
print!("{:?}", tokens);
|
pub fn read(code: &str) -> Tokens {
|
||||||
|
scan(code, 0, vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
|
fn scan(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
mod lexer;
|
mod lexer;
|
||||||
|
mod parser;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let scm_code = "(+ a 32)";
|
let scm_code = "(+ a (* 32 b) c #t #f)";
|
||||||
lexer::read(scm_code);
|
let tokens = lexer::read(scm_code);
|
||||||
|
let datum = parser::parse(tokens);
|
||||||
|
println!("{:?}", datum);
|
||||||
}
|
}
|
||||||
|
|||||||
39
src/parser.rs
Normal file
39
src/parser.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
use crate::lexer::Token;
|
||||||
|
use crate::lexer::Tokens;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Datum {
|
||||||
|
Boolean(bool),
|
||||||
|
Number(i64),
|
||||||
|
Symbol(String),
|
||||||
|
List(Vec<Datum>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(tokens: Tokens) -> Datum {
|
||||||
|
let (datum, _) = parse_datum(&tokens, 0);
|
||||||
|
datum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_datum(tokens: &Tokens, ix: usize) -> (Datum, usize) {
|
||||||
|
match &tokens[ix] {
|
||||||
|
Token::Identifier(s) => (Datum::Symbol(s.to_string()), ix + 1),
|
||||||
|
Token::Boolean(b) => (Datum::Boolean(*b), ix + 1),
|
||||||
|
Token::Number(n) => (Datum::Number(*n), ix + 1),
|
||||||
|
Token::LeftRoundBracket => parse_list(tokens, ix + 1),
|
||||||
|
_ => panic!("Unexpected token {:?}", tokens[ix])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_list(tokens: &Tokens, mut ix: usize) -> (Datum, usize) {
|
||||||
|
let mut datums = vec![];
|
||||||
|
|
||||||
|
// FIXME: will crash when RightRoundBracket is missing
|
||||||
|
while tokens[ix] != Token::RightRoundBracket {
|
||||||
|
let (datum, new_ix) = parse_datum(tokens, ix);
|
||||||
|
datums.push(datum);
|
||||||
|
ix = new_ix;
|
||||||
|
}
|
||||||
|
|
||||||
|
(Datum::List(datums), ix + 1)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user