add spans to AST

This commit is contained in:
nora 2021-10-31 00:40:18 +02:00
parent d848818824
commit 8f99a1d630
4 changed files with 155 additions and 61 deletions

View file

@ -1,8 +1,9 @@
//! //!
//! The AST module contains all structs and enums for the abstract syntax tree generated by the parser //! The AST module contains all structs and enums for the abstract syntax tree generated by the parser
#![allow(dead_code)] #![allow(dead_code)]
use crate::errors::Span;
/// imagine interning or something here /// imagine interning or something here
pub type Symbol = String; pub type Symbol = String;
@ -20,25 +21,28 @@ pub enum Stmt {
If(IfStmt), If(IfStmt),
Loop(Block), Loop(Block),
While(WhileStmt), While(WhileStmt),
Break, Break(Break),
Return(Option<Expr>), Return(Option<Expr>),
Expr(Expr), Expr(Expr),
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Declaration { pub struct Declaration {
pub span: Span,
name: Symbol, name: Symbol,
init: Expr, init: Expr,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Assignment { pub struct Assignment {
pub span: Span,
pub lhs: Symbol, pub lhs: Symbol,
pub rhs: Expr, pub rhs: Expr,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct FnDecl { pub struct FnDecl {
pub span: Span,
pub name: Symbol, pub name: Symbol,
pub params: Vec<Symbol>, pub params: Vec<Symbol>,
pub body: Block, pub body: Block,
@ -46,6 +50,7 @@ pub struct FnDecl {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct IfStmt { pub struct IfStmt {
pub span: Span,
pub condition: Expr, pub condition: Expr,
pub body: Block, pub body: Block,
pub else_part: Box<ElsePart>, pub else_part: Box<ElsePart>,
@ -59,29 +64,59 @@ pub enum ElsePart {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct WhileStmt { pub struct WhileStmt {
pub span: Span,
pub cond: Expr, pub cond: Expr,
pub body: Block, pub body: Block,
} }
#[derive(Debug, Clone, PartialEq)]
pub struct Break {
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Expr { pub enum Expr {
Literal(Literal), Literal(Literal),
UnaryOp, UnaryOp(Box<UnaryOp>),
BinaryOp, BinaryOp(Box<BinaryOp>),
}
impl Expr {
pub fn span(&self) -> Span {
match self {
Expr::Literal(lit) => lit.span(),
Expr::UnaryOp(unary) => unary.span,
Expr::BinaryOp(binary) => binary.span,
}
}
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Literal { pub enum Literal {
String(String), String(String, Span),
Number(f64), Number(f64, Span),
Array(Vec<Expr>), Array(Vec<Expr>, Span),
Object, Object(Span),
Boolean(bool), Boolean(bool, Span),
Null, Null(Span),
}
impl Literal {
pub fn span(&self) -> Span {
match self {
Literal::String(_, span) => *span,
Literal::Number(_, span) => *span,
Literal::Array(_, span) => *span,
Literal::Object(span) => *span,
Literal::Boolean(_, span) => *span,
Literal::Null(span) => *span,
}
}
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct UnaryOp { pub struct UnaryOp {
pub span: Span,
pub expr: Expr, pub expr: Expr,
pub kind: UnaryOpKind, pub kind: UnaryOpKind,
} }
@ -94,6 +129,7 @@ pub enum UnaryOpKind {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct BinaryOp { pub struct BinaryOp {
pub span: Span,
pub lhs: Expr, pub lhs: Expr,
pub rhs: Expr, pub rhs: Expr,
pub kind: BinaryOpKind, pub kind: BinaryOpKind,
@ -115,9 +151,3 @@ pub enum BinaryOpKind {
Div, Div,
Mod, Mod,
} }
#[derive(Debug, Clone, PartialEq)]
pub enum Call {
Function(Expr, Vec<Expr>),
Field(Expr, Vec<Expr>),
}

View file

@ -3,27 +3,53 @@
use std::fmt::Debug; use std::fmt::Debug;
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)] pub use span::Span;
pub struct Span {
start: usize,
len: usize,
}
impl Span { mod span {
pub fn new(start: usize, len: usize) -> Self {
Self { start, len } #[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
pub struct Span {
pub start: usize,
pub end: usize,
} }
pub fn start_end(start: usize, end: usize) -> Self { impl Span {
Self::new(start, end - start) pub fn new(start: usize, len: usize) -> Self {
} Self {
start,
end: start + len,
}
}
pub fn single(start: usize) -> Self { pub fn start_end(start: usize, end: usize) -> Self {
Self { start, len: 1 } Self::new(start, end)
} }
pub fn dummy() -> Self { pub fn single(start: usize) -> Self {
Self { start: 0, len: 0 } Self {
start,
end: start + 1,
}
}
pub fn dummy() -> Self {
Self { start: 0, end: 0 }
}
/// Extends the span by the second one
/// The other one has to be after the current one
pub fn extend(&self, other: Span) -> Span {
debug_assert!(self.start <= other.start);
debug_assert!(self.end <= other.end);
Span {
start: self.start,
end: other.end,
}
}
pub fn len(&self) -> usize {
self.end - self.start
}
} }
} }
@ -57,7 +83,7 @@ where
"{}{}{}{}", "{}{}{}{}",
" ".repeat(offset_on_line), " ".repeat(offset_on_line),
RED, RED,
"^".repeat(error.span().len), "^".repeat(error.span().len()),
RESET, RESET,
); );
if let Some(note) = error.note() { if let Some(note) = error.note() {

View file

@ -126,7 +126,7 @@ impl<'code> Lexer<'code> {
if self.expect(expect_char) { if self.expect(expect_char) {
let _ = self.code.next(); // consume first one let _ = self.code.next(); // consume first one
Token { Token {
span: Span::new(start, 2), span: Span::new(start, start + 2),
kind: true_type, kind: true_type,
} }
} else { } else {
@ -191,7 +191,7 @@ impl<'code> Iterator for Lexer<'code> {
if self.expect('=') { if self.expect('=') {
let _ = self.code.next(); // consume =; let _ = self.code.next(); // consume =;
break Token { break Token {
span: Span::new(start, 2), span: Span::new(start, start + 2),
kind: TokenType::BangEqual, kind: TokenType::BangEqual,
}; };
} else { } else {

View file

@ -96,23 +96,39 @@ impl<'code> Parser<'code> {
} }
fn unary(&mut self) -> ParseResult<'code, Expr> { fn unary(&mut self) -> ParseResult<'code, Expr> {
match self.next().ok_or(ParseErr::EOF)?.kind { let next = self.next().ok_or(ParseErr::EOF)?;
TokenType::Not => todo!(), match next.kind {
TokenType::Minus => todo!(), TokenType::Not => {
let expr = self.expression()?;
Ok(Expr::UnaryOp(Box::new(UnaryOp {
span: next.span,
expr,
kind: UnaryOpKind::Not,
})))
}
TokenType::Minus => {
let expr = self.expression()?;
Ok(Expr::UnaryOp(Box::new(UnaryOp {
span: next.span,
expr,
kind: UnaryOpKind::Neg,
})))
}
_ => todo!(), _ => todo!(),
} }
} }
fn primary(&mut self) -> ParseResult<'code, Expr> { fn primary(&mut self) -> ParseResult<'code, Expr> {
match self.next().ok_or(ParseErr::EOF)?.kind { let next = self.next().ok_or(ParseErr::EOF)?;
TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal))), match next.kind {
TokenType::Number(literal) => Ok(Expr::Literal(Literal::Number(literal))), TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal, next.span))),
TokenType::False => Ok(Expr::Literal(Literal::Boolean(false))), TokenType::Number(literal) => Ok(Expr::Literal(Literal::Number(literal, next.span))),
TokenType::True => Ok(Expr::Literal(Literal::Boolean(true))), TokenType::False => Ok(Expr::Literal(Literal::Boolean(false, next.span))),
TokenType::Null => Ok(Expr::Literal(Literal::Null)), TokenType::True => Ok(Expr::Literal(Literal::Boolean(true, next.span))),
TokenType::Null => Ok(Expr::Literal(Literal::Null(next.span))),
TokenType::BraceO => { TokenType::BraceO => {
self.expect(TokenType::BraceC)?; self.expect(TokenType::BraceC)?;
Ok(Expr::Literal(Literal::Object)) Ok(Expr::Literal(Literal::Object(next.span)))
} }
TokenType::BracketO => { TokenType::BracketO => {
let mut elements = Vec::new(); let mut elements = Vec::new();
@ -121,8 +137,11 @@ impl<'code> Parser<'code> {
elements.push(expr); elements.push(expr);
self.expect(TokenType::Comma)?; self.expect(TokenType::Comma)?;
} }
self.expect(TokenType::BracketC); let closing_bracket = self.expect(TokenType::BracketC)?;
Ok(Expr::Literal(Literal::Array(elements))) Ok(Expr::Literal(Literal::Array(
elements,
next.span.extend(closing_bracket.span),
)))
} }
TokenType::ParenO => todo!(), TokenType::ParenO => todo!(),
_ => todo!(), _ => todo!(),
@ -130,9 +149,9 @@ impl<'code> Parser<'code> {
} }
fn object_literal(&mut self) -> ParseResult<'code, Expr> { fn object_literal(&mut self) -> ParseResult<'code, Expr> {
self.expect(TokenType::BraceO)?; let open_span = self.expect(TokenType::BraceO)?.span;
self.expect(TokenType::BraceC)?; let close_span = self.expect(TokenType::BraceC)?.span;
Ok(Expr::Literal(Literal::Object)) Ok(Expr::Literal(Literal::Object(open_span.extend(close_span))))
} }
fn array_literal(&mut self) -> ParseResult<'code, Expr> { fn array_literal(&mut self) -> ParseResult<'code, Expr> {
@ -149,10 +168,10 @@ impl<'code> Parser<'code> {
self.tokens.peek() self.tokens.peek()
} }
fn expect(&mut self, kind: TokenType<'code>) -> ParseResult<'code, ()> { fn expect(&mut self, kind: TokenType<'code>) -> ParseResult<'code, Token> {
if let Some(token) = self.next() { if let Some(token) = self.next() {
if token.kind == kind { if token.kind == kind {
Ok(()) Ok(token)
} else { } else {
Err(ParseErr::MismatchedKind { expected: kind }) Err(ParseErr::MismatchedKind { expected: kind })
} }
@ -200,10 +219,17 @@ mod test {
} }
} }
mod primary { mod unary {
use super::{parser, token};
use crate::ast::{Expr, Literal}; use crate::ast::{Expr, Literal};
use crate::lex::{Token, TokenType}; use crate::lex::{Token, TokenType};
use crate::parse::test::{parser, token}; }
mod primary {
use super::{parser, token};
use crate::ast::{Expr, Literal};
use crate::errors::Span;
use crate::lex::{Token, TokenType};
fn parse_primary<'a, T: Into<Vec<Token<'a>>>>(tokens: T) -> Expr { fn parse_primary<'a, T: Into<Vec<Token<'a>>>>(tokens: T) -> Expr {
let mut parser = parser(tokens); let mut parser = parser(tokens);
@ -214,49 +240,61 @@ mod test {
fn string() { fn string() {
let tokens = [TokenType::Number(10.0)].map(token); let tokens = [TokenType::Number(10.0)].map(token);
let literal = parse_primary(tokens); let literal = parse_primary(tokens);
assert_eq!(Expr::Literal(Literal::Number(10.0)), literal); assert_eq!(Expr::Literal(Literal::Number(10.0, Span::dummy())), literal);
} }
#[test] #[test]
fn number() { fn number() {
let tokens = [TokenType::String("uwu".to_string())].map(token); let tokens = [TokenType::String("uwu".to_string())].map(token);
let literal = parse_primary(tokens); let literal = parse_primary(tokens);
assert_eq!(Expr::Literal(Literal::String("uwu".to_string())), literal); assert_eq!(
Expr::Literal(Literal::String("uwu".to_string(), Span::dummy())),
literal
);
} }
#[test] #[test]
fn empty_object() { fn empty_object() {
let tokens = [TokenType::BraceO, TokenType::BraceC].map(token); let tokens = [TokenType::BraceO, TokenType::BraceC].map(token);
let literal = parse_primary(tokens); let literal = parse_primary(tokens);
assert_eq!(Expr::Literal(Literal::Object), literal); assert_eq!(Expr::Literal(Literal::Object(Span::dummy())), literal);
} }
#[test] #[test]
fn empty_array() { fn empty_array() {
let tokens = [TokenType::BracketO, TokenType::BracketC].map(token); let tokens = [TokenType::BracketO, TokenType::BracketC].map(token);
let literal = parse_primary(tokens); let literal = parse_primary(tokens);
assert_eq!(Expr::Literal(Literal::Array(Vec::new())), literal); assert_eq!(
Expr::Literal(Literal::Array(Vec::new(), Span::dummy())),
literal
);
} }
#[test] #[test]
fn r#false() { fn r#false() {
let tokens = [TokenType::False].map(token); let tokens = [TokenType::False].map(token);
let literal = parse_primary(tokens); let literal = parse_primary(tokens);
assert_eq!(Expr::Literal(Literal::Boolean(false)), literal); assert_eq!(
Expr::Literal(Literal::Boolean(false, Span::dummy())),
literal
);
} }
#[test] #[test]
fn r#true() { fn r#true() {
let tokens = [TokenType::True].map(token); let tokens = [TokenType::True].map(token);
let literal = parse_primary(tokens); let literal = parse_primary(tokens);
assert_eq!(Expr::Literal(Literal::Boolean(true)), literal); assert_eq!(
Expr::Literal(Literal::Boolean(true, Span::dummy())),
literal
);
} }
#[test] #[test]
fn null() { fn null() {
let tokens = [TokenType::Null].map(token); let tokens = [TokenType::Null].map(token);
let literal = parse_primary(tokens); let literal = parse_primary(tokens);
assert_eq!(Expr::Literal(Literal::Null), literal); assert_eq!(Expr::Literal(Literal::Null(Span::dummy())), literal);
} }
} }
} }