mirror of
https://github.com/Noratrieb/dilaria.git
synced 2026-01-16 18:35:02 +01:00
fix top level
This commit is contained in:
parent
9837713771
commit
c6e5a5d686
5 changed files with 68 additions and 39 deletions
|
|
@ -1,9 +1,11 @@
|
||||||
# todo: calls (property access and function calls)
|
# todo: calls (property access and function calls)
|
||||||
|
|
||||||
|
|
||||||
<program> ::= <block>
|
<program> ::= <statement-list>
|
||||||
|
|
||||||
<block> ::= "{" { <statement> } "}"
|
<statement-list> ::= { <statement> }
|
||||||
|
|
||||||
|
<block> ::= "{" <statement-list> "}"
|
||||||
|
|
||||||
<statement> ::= <declaration>
|
<statement> ::= <declaration>
|
||||||
| <assignment>
|
| <assignment>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use crate::errors::Span;
|
||||||
pub type Symbol = String;
|
pub type Symbol = String;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Program(pub Block);
|
pub struct Program(pub Vec<Stmt>);
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Block(pub Vec<Stmt>);
|
pub struct Block(pub Vec<Stmt>);
|
||||||
|
|
|
||||||
25
src/lib.rs
25
src/lib.rs
|
|
@ -7,24 +7,27 @@ mod parse;
|
||||||
pub fn run_program(program: &str) {
|
pub fn run_program(program: &str) {
|
||||||
let lexer = lex::Lexer::lex(program);
|
let lexer = lex::Lexer::lex(program);
|
||||||
let (success, errors) = lexer.partition::<Vec<_>, _>(|result| result.is_ok());
|
let (success, errors) = lexer.partition::<Vec<_>, _>(|result| result.is_ok());
|
||||||
//
|
|
||||||
// // terrible, but works
|
|
||||||
// let tokens = success.into_iter().collect::<Result<_, _>>();
|
|
||||||
// let _ast = parse::parse(tokens.unwrap());
|
|
||||||
|
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
|
let tokens = success.into_iter().collect::<Result<Vec<_>, _>>().unwrap();
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{:#?}",
|
"{:?}",
|
||||||
success
|
tokens.iter().map(|token| &token.kind).collect::<Vec<_>>()
|
||||||
.into_iter()
|
|
||||||
.map(Result::unwrap)
|
|
||||||
.map(|token| token.kind)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let ast = parse::parse(tokens);
|
||||||
|
|
||||||
|
match ast {
|
||||||
|
Ok(ast) => println!("{:#?}", ast),
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{:?}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
errors
|
errors
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Result::unwrap_err)
|
.map(Result::unwrap_err)
|
||||||
.for_each(|err| crate::errors::display_error(program, err));
|
.for_each(|err| errors::display_error(program, err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
src/parse.rs
64
src/parse.rs
|
|
@ -35,25 +35,25 @@ macro_rules! parse_bin_op {
|
||||||
|
|
||||||
impl<'code> Parser<'code> {
|
impl<'code> Parser<'code> {
|
||||||
fn program(&mut self) -> ParseResult<'code, Program> {
|
fn program(&mut self) -> ParseResult<'code, Program> {
|
||||||
Ok(Program(self.block()?))
|
Ok(Program(self.statement_list()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(&mut self) -> ParseResult<'code, Block> {
|
fn statement_list(&mut self) -> ParseResult<'code, Vec<Stmt>> {
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
if let Some(Token {
|
if let Some(TokenType::BraceC) | None = self.peek().map(|token| &token.kind) {
|
||||||
kind: TokenType::BraceC,
|
|
||||||
..
|
|
||||||
}) = self.peek()
|
|
||||||
{
|
|
||||||
let _ = self.next();
|
let _ = self.next();
|
||||||
return Ok(Block(stmts));
|
return Ok(stmts);
|
||||||
}
|
}
|
||||||
let stmt = self.statement()?;
|
let stmt = self.statement()?;
|
||||||
stmts.push(stmt);
|
stmts.push(stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn block(&mut self) -> ParseResult<'code, Block> {
|
||||||
|
Ok(Block(self.statement_list()?))
|
||||||
|
}
|
||||||
|
|
||||||
fn statement(&mut self) -> ParseResult<'code, Stmt> {
|
fn statement(&mut self) -> ParseResult<'code, Stmt> {
|
||||||
let expr = self.expression()?;
|
let expr = self.expression()?;
|
||||||
self.expect(TokenType::Semi)?;
|
self.expect(TokenType::Semi)?;
|
||||||
|
|
@ -167,13 +167,12 @@ impl<'code> Parser<'code> {
|
||||||
kind: UnaryOpKind::Neg,
|
kind: UnaryOpKind::Neg,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
Some(_) => self.primary(),
|
_ => self.primary(),
|
||||||
None => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primary(&mut self) -> ParseResult<'code, Expr> {
|
fn primary(&mut self) -> ParseResult<'code, Expr> {
|
||||||
let next = self.next().ok_or(ParseErr::EOF)?;
|
let next = self.next().ok_or(ParseErr::EOF("primary"))?;
|
||||||
match next.kind {
|
match next.kind {
|
||||||
TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal, next.span))),
|
TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal, next.span))),
|
||||||
TokenType::Number(literal) => Ok(Expr::Literal(Literal::Number(literal, next.span))),
|
TokenType::Number(literal) => Ok(Expr::Literal(Literal::Number(literal, next.span))),
|
||||||
|
|
@ -194,7 +193,7 @@ impl<'code> Parser<'code> {
|
||||||
|
|
||||||
fn array_literal(&mut self, open_span: Span) -> ParseResult<'code, Expr> {
|
fn array_literal(&mut self, open_span: Span) -> ParseResult<'code, Expr> {
|
||||||
let mut elements = Vec::new();
|
let mut elements = Vec::new();
|
||||||
while self.peek().ok_or(ParseErr::EOF)?.kind != TokenType::BracketC {
|
while self.peek().ok_or(ParseErr::EOF("array literal"))?.kind != TokenType::BracketC {
|
||||||
let expr = self.expression()?;
|
let expr = self.expression()?;
|
||||||
elements.push(expr);
|
elements.push(expr);
|
||||||
self.expect(TokenType::Comma)?;
|
self.expect(TokenType::Comma)?;
|
||||||
|
|
@ -226,7 +225,7 @@ impl<'code> Parser<'code> {
|
||||||
Err(ParseErr::MismatchedKind { expected: kind })
|
Err(ParseErr::MismatchedKind { expected: kind })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(ParseErr::EOF)
|
Err(ParseErr::ExpectedToken(kind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,8 +233,8 @@ impl<'code> Parser<'code> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ParseErr<'code> {
|
pub enum ParseErr<'code> {
|
||||||
MismatchedKind { expected: TokenType<'code> },
|
MismatchedKind { expected: TokenType<'code> },
|
||||||
InvalidToken(TokenType<'code>),
|
ExpectedToken(TokenType<'code>),
|
||||||
EOF,
|
EOF(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompilerError for ParseErr<'_> {
|
impl CompilerError for ParseErr<'_> {
|
||||||
|
|
@ -260,7 +259,7 @@ mod test {
|
||||||
|
|
||||||
mod prelude {
|
mod prelude {
|
||||||
pub(super) use super::{parser, test_literal_bin_op, test_number_literal, token};
|
pub(super) use super::{parser, test_literal_bin_op, test_number_literal, token};
|
||||||
pub(super) use crate::ast::{BinaryOpKind, Expr, Literal};
|
pub(super) use crate::ast::{BinaryOp, BinaryOpKind, Expr, Literal};
|
||||||
pub(super) use crate::errors::Span;
|
pub(super) use crate::errors::Span;
|
||||||
pub(super) use crate::lex::{Token, TokenType};
|
pub(super) use crate::lex::{Token, TokenType};
|
||||||
}
|
}
|
||||||
|
|
@ -304,6 +303,39 @@ mod test {
|
||||||
assert_eq!(Expr::Literal(Literal::Number(10.0, Span::dummy())), unary);
|
assert_eq!(Expr::Literal(Literal::Number(10.0, Span::dummy())), unary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod expr {
|
||||||
|
use super::prelude::*;
|
||||||
|
use TokenType::*;
|
||||||
|
|
||||||
|
fn parse_expr(tokens: Vec<Token>) -> Expr {
|
||||||
|
let mut parser = parser(tokens);
|
||||||
|
parser.expression().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_multiply() {
|
||||||
|
let tokens = [Number(10.0), Plus, Number(20.0), Asterisk, Number(100.0)]
|
||||||
|
.map(token)
|
||||||
|
.into();
|
||||||
|
let expr = parse_expr(tokens);
|
||||||
|
assert_eq!(
|
||||||
|
Expr::BinaryOp(Box::new(BinaryOp {
|
||||||
|
span: Span::dummy(),
|
||||||
|
lhs: Expr::Literal(Literal::Number(10.0, Span::dummy())),
|
||||||
|
rhs: Expr::BinaryOp(Box::new(BinaryOp {
|
||||||
|
span: Span::dummy(),
|
||||||
|
lhs: Expr::Literal(Literal::Number(20.0, Span::dummy())),
|
||||||
|
rhs: Expr::Literal(Literal::Number(100.0, Span::dummy())),
|
||||||
|
|
||||||
|
kind: BinaryOpKind::Mul
|
||||||
|
})),
|
||||||
|
kind: BinaryOpKind::Add
|
||||||
|
})),
|
||||||
|
expr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod logical_or {
|
mod logical_or {
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
|
|
||||||
|
|
|
||||||
10
test.sl
10
test.sl
|
|
@ -1,9 +1 @@
|
||||||
fn main() {
|
1 + 2 * 10;
|
||||||
let number = 57234875;
|
|
||||||
let number2 = 5325;
|
|
||||||
let is_equal = number == number2;
|
|
||||||
|
|
||||||
if !is_equal {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue