Add import statement parsing

This commit is contained in:
Sofia 2023-07-27 21:47:50 +03:00
parent 6170eb0990
commit 40f3738719
4 changed files with 81 additions and 12 deletions

View File

@ -2,6 +2,7 @@
import std::print; import std::print;
let test = 5;
let arithmetic = 3 + 2 * 5 + 1 * 2; let arithmetic = 3 + 2 * 5 + 1 * 2;
let multiplier = 5 * 2; let multiplier = 5 * 2;

View File

@ -1,10 +1,5 @@
use std::{fmt::Debug, iter::Peekable, str::Chars}; use std::{fmt::Debug, iter::Peekable, str::Chars};
pub static EASIEST: &str = include_str!("../easiest.reid");
// pub static EASY: &str = include_str!("../easy.reid");
// pub static MEDIUM: &str = include_str!("../medium.reid");
// pub static HARD: &str = include_str!("../hard.reid");
static DECIMAL_NUMERICS: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; static DECIMAL_NUMERICS: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, String> { pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, String> {
@ -50,6 +45,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Strin
// Check for keywords // Check for keywords
let variant = match value.as_str() { let variant = match value.as_str() {
"let" => Token::LetKeyword, "let" => Token::LetKeyword,
"import" => Token::ImportKeyword,
_ => Token::Identifier(value), _ => Token::Identifier(value),
}; };
variant variant
@ -69,6 +65,11 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Strin
// Single character tokens // Single character tokens
'=' => Token::Equals, '=' => Token::Equals,
';' => Token::Semicolon, ';' => Token::Semicolon,
':' => Token::Colon,
'+' => Token::Plus,
'*' => Token::Times,
'(' => Token::ParenOpen,
')' => Token::ParenClose,
// Invalid token // Invalid token
_ => Err(format!( _ => Err(format!(
"Unknown token '{}' at {}, {}", "Unknown token '{}' at {}, {}",
@ -110,12 +111,24 @@ pub type Position = (u32, u32);
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub enum Token { pub enum Token {
LetKeyword, // Values
Semicolon,
Equals,
Identifier(String), Identifier(String),
/// Number with at most one decimal point /// Number with at most one decimal point
DecimalValue(String), DecimalValue(String),
// Keywords
LetKeyword,
ImportKeyword,
// Symbols
Semicolon,
Equals,
Colon,
Plus,
Times,
ParenOpen, // (
ParenClose, // )
Eof, Eof,
} }

View File

@ -1,13 +1,24 @@
use crate::{lexer::EASIEST, parser::LetStatement, token_stream::TokenStream}; use crate::{lexer::Token, parser::TopLevelStatement, token_stream::TokenStream};
pub static EASIEST: &str = include_str!("../easiest.reid");
pub static EASY: &str = include_str!("../easy.reid");
pub static MEDIUM: &str = include_str!("../medium.reid");
pub static HARD: &str = include_str!("../hard.reid");
mod lexer; mod lexer;
mod parser; mod parser;
mod token_stream; mod token_stream;
fn main() { fn main() {
let tokens = lexer::tokenize(EASIEST).unwrap(); let tokens = lexer::tokenize(EASY).unwrap();
dbg!(&tokens);
let mut token_stream = TokenStream::from(&tokens); let mut token_stream = TokenStream::from(&tokens);
dbg!(token_stream.parse::<LetStatement>().ok()); while let Ok(statement) = token_stream.parse::<TopLevelStatement>() {
dbg!(token_stream.parse::<LetStatement>().ok()); dbg!(&statement);
}
dbg!(token_stream.expect(Token::Eof).ok());
} }

View File

@ -27,6 +27,22 @@ impl Parseable for Expression {
} }
} }
#[derive(Debug)]
pub enum TopLevelStatement {
Let(LetStatement),
Import(ImportStatement),
}
impl Parseable for TopLevelStatement {
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
Ok(match stream.peek() {
Some(Token::LetKeyword) => TopLevelStatement::Let(stream.parse()?),
Some(Token::ImportKeyword) => TopLevelStatement::Import(stream.parse()?),
_ => Err(())?,
})
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct LetStatement(String, Expression); pub struct LetStatement(String, Expression);
@ -45,3 +61,31 @@ impl Parseable for LetStatement {
} }
} }
} }
#[derive(Debug)]
pub struct ImportStatement(Vec<String>);
impl Parseable for ImportStatement {
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
stream.expect(Token::ImportKeyword)?;
let mut import_list = Vec::new();
if let Some(Token::Identifier(name)) = stream.next() {
import_list.push(name);
while stream.expect(Token::Colon).is_ok() && stream.expect(Token::Colon).is_ok() {
if let Some(Token::Identifier(name)) = stream.next() {
import_list.push(name);
} else {
Err(())?
}
}
} else {
Err(())?
}
stream.expect(Token::Semicolon)?;
Ok(ImportStatement(import_list))
}
}