nodes + dyn stuff which is dumb and I'ma replace

This commit is contained in:
2024-10-07 13:53:33 -04:00
parent e5aea8b24e
commit ca52443f81
13 changed files with 408 additions and 125 deletions

View File

@@ -2,12 +2,27 @@ use std::io::{stdout, BufRead, BufReader};
mod parser; mod parser;
use parser::{Module, Statement, TokenCursor}; use parser::{Module, Node, NodeContainer, Statement, TokenCursor};
pub fn parse_file(file: &str) { pub fn parse_file(file: &str) {
match Module::parse(&mut TokenCursor::from(file)) { let node = Node::<Module>::parse(&mut TokenCursor::from(file));
match node.inner {
Err(err) => err.write_for(&mut stdout(), file).unwrap(), Err(err) => err.write_for(&mut stdout(), file).unwrap(),
Ok(module) => println!("{module:#?}"), Ok(module) => {
println!("{module:#?}");
print_errors(module.children(), file)
},
};
}
pub fn print_errors(nodes: Vec<Node<Box<dyn NodeContainer>>>, file: &str) {
for node in &nodes {
if let Err(err) = &node.inner {
err.write_for(&mut stdout(), file).unwrap();
}
}
for node in nodes {
print_errors(node.children(), file)
} }
} }
@@ -16,7 +31,7 @@ pub fn run_stdin() {
let str = &line.expect("failed to read line"); let str = &line.expect("failed to read line");
let mut cursor = TokenCursor::from(&str[..]); let mut cursor = TokenCursor::from(&str[..]);
let out = &mut stdout(); let out = &mut stdout();
match Statement::parse(&mut cursor) { match Node::<Statement>::parse(&mut cursor).inner {
Ok(expr) => println!("{:?}", expr), Ok(expr) => println!("{:?}", expr),
Err(err) => err.write_for(out, str).unwrap(), Err(err) => err.write_for(out, str).unwrap(),
} }

View File

@@ -1,65 +1,81 @@
use std::fmt::{Debug, Write}; use std::fmt::{Debug, Write};
use super::token::{Keyword, Symbol, Token}; use super::{
token::{Keyword, Symbol, Token}, Node, NodeContainer, Parsable
};
use crate::util::Padder; use crate::util::Padder;
use super::{Expr, ParserError, TokenCursor}; use super::{Expr, ParserError, TokenCursor};
#[derive(Clone)]
pub struct Body { pub struct Body {
statements: Vec<Statement>, statements: Vec<Node<Statement>>,
} }
#[derive(Clone)]
pub enum Statement { pub enum Statement {
Let(String, Expr), Let(String, Node<Expr>),
Return(Expr), Return(Node<Expr>),
Expr(Expr), Expr(Node<Expr>),
} }
impl Body { impl Parsable for Body {
pub fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
let mut statements = Vec::new(); let mut statements = Vec::new();
let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
cursor.expect_sym(Symbol::OpenCurly)?; cursor.expect_sym(Symbol::OpenCurly)?;
if cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) {
cursor.next();
return Ok(Self { statements });
}
loop { loop {
let next = cursor.expect_peek()?; let next = cursor.expect_peek()?;
if next.is_symbol(Symbol::CloseCurly) { if next.is_symbol(Symbol::CloseCurly) {
cursor.next(); cursor.next();
return Ok(Self { statements }); return Ok(Self { statements });
} }
statements.push(Statement::parse(cursor)?); statements.push(Node::parse(cursor));
let next = cursor.expect_next()?;
match next.token {
Token::Symbol(Symbol::Semicolon) => continue,
Token::Symbol(Symbol::CloseCurly) => return Ok(Self { statements }),
_ => {
let start = next.span.start;
cursor
.seek(|t| t.is_symbol_and(|s| statement_end.contains(&s)))
.ok_or(ParserError::unexpected_end())?;
let end = cursor.prev_end();
let next = cursor.expect_next()?;
let span = start.to(end);
statements.push(Node::err(ParserError {
msg: "Unexpected tokens".to_string(),
spans: vec![span],
}, span));
if next.is_symbol(Symbol::CloseCurly) {
return Ok(Self { statements });
}
}
}
} }
} }
} }
impl Statement { impl Parsable for Statement {
pub fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
let next = cursor.expect_peek()?; let next = cursor.expect_peek()?;
Ok(match next.token { Ok(match next.token {
Token::Keyword(Keyword::Let) => { Token::Keyword(Keyword::Let) => {
cursor.next(); cursor.next();
let name = cursor.expect_ident()?; let name = cursor.expect_ident()?;
cursor.expect_sym(Symbol::Equals)?; cursor.expect_sym(Symbol::Equals)?;
let expr = Expr::parse(cursor)?; let expr = Node::parse(cursor);
cursor.expect_sym(Symbol::Semicolon)?;
Self::Let(name, expr) Self::Let(name, expr)
} }
Token::Keyword(Keyword::Return) => { Token::Keyword(Keyword::Return) => {
cursor.next(); cursor.next();
let expr = Expr::parse(cursor)?; Self::Return(Node::parse(cursor))
cursor.expect_sym(Symbol::Semicolon)?;
Self::Return(expr)
}
_ => {
let expr = Expr::parse(cursor)?;
let next = cursor.expect_peek()?;
if next.is_symbol(Symbol::Semicolon) {
cursor.next();
Self::Expr(expr)
} else if next.is_symbol(Symbol::CloseCurly) {
Self::Return(expr)
} else {
return Err(ParserError::unexpected_token(next, "a ';' or '}'"));
}
} }
_ => Self::Expr(Node::parse(cursor)),
}) })
} }
} }
@@ -104,3 +120,19 @@ impl Debug for Body {
Ok(()) Ok(())
} }
} }
impl NodeContainer for Body {
fn children(&self) -> Vec<Node<Box<dyn NodeContainer>>> {
self.statements.iter().map(|f| f.containerr()).collect()
}
}
impl NodeContainer for Statement {
fn children(&self) -> Vec<Node<Box<dyn NodeContainer>>> {
match self {
Statement::Let(_, e) => vec![e.containerr()],
Statement::Return(e) => vec![e.containerr()],
Statement::Expr(e) => vec![e.containerr()],
}
}
}

View File

@@ -1,19 +1,23 @@
use std::ops::{Deref, DerefMut};
use super::error::ParserError; use super::error::ParserError;
use super::token::{CharCursor, Keyword, Symbol, Token, TokenInstance}; use super::token::{CharCursor, Keyword, Symbol, Token, TokenInstance};
use super::FilePos;
pub struct TokenCursor<'a> { pub struct TokenCursor<'a> {
cursor: CharCursor<'a>, cursor: CharCursor<'a>,
next: Option<TokenInstance>, next: Option<TokenInstance>,
next_pos: FilePos,
prev_end: FilePos,
} }
impl<'a> TokenCursor<'a> { impl<'a> TokenCursor<'a> {
pub fn next(&mut self) -> Option<TokenInstance> { pub fn next(&mut self) -> Option<TokenInstance> {
self.prev_end = self.cursor.prev_pos();
self.next_pos = self.cursor.next_pos();
std::mem::replace(&mut self.next, TokenInstance::parse(&mut self.cursor)) std::mem::replace(&mut self.next, TokenInstance::parse(&mut self.cursor))
} }
pub fn expect_next(&mut self) -> Result<TokenInstance, ParserError> { pub fn expect_next(&mut self) -> Result<TokenInstance, ParserError> {
self.next().ok_or(ParserError::unexpected_end()) self.peek().ok_or(ParserError::unexpected_end())?;
Ok(self.next().unwrap())
} }
pub fn expect_token(&mut self, t: Token) -> Result<(), ParserError> { pub fn expect_token(&mut self, t: Token) -> Result<(), ParserError> {
let next = self.expect_next()?; let next = self.expect_next()?;
@@ -26,6 +30,20 @@ impl<'a> TokenCursor<'a> {
pub fn expect_sym(&mut self, symbol: Symbol) -> Result<(), ParserError> { pub fn expect_sym(&mut self, symbol: Symbol) -> Result<(), ParserError> {
self.expect_token(Token::Symbol(symbol)) self.expect_token(Token::Symbol(symbol))
} }
pub fn seek_sym(&mut self, symbol: Symbol) {
while self
.next()
.is_some_and(|n| n.token != Token::Symbol(symbol))
{}
}
pub fn seek(&mut self, f: impl Fn(&TokenInstance) -> bool) -> Option<&TokenInstance> {
loop {
if f(self.peek()?) {
return self.peek();
}
self.next();
}
}
pub fn expect_kw(&mut self, kw: Keyword) -> Result<(), ParserError> { pub fn expect_kw(&mut self, kw: Keyword) -> Result<(), ParserError> {
self.expect_token(Token::Keyword(kw)) self.expect_token(Token::Keyword(kw))
} }
@@ -45,6 +63,12 @@ impl<'a> TokenCursor<'a> {
pub fn chars(&mut self) -> &mut CharCursor<'a> { pub fn chars(&mut self) -> &mut CharCursor<'a> {
&mut self.cursor &mut self.cursor
} }
pub fn prev_end(&self) -> FilePos {
self.prev_end
}
pub fn next_pos(&self) -> FilePos {
self.next_pos
}
} }
impl<'a> From<&'a str> for TokenCursor<'a> { impl<'a> From<&'a str> for TokenCursor<'a> {
@@ -56,6 +80,11 @@ impl<'a> From<&'a str> for TokenCursor<'a> {
impl<'a> From<CharCursor<'a>> for TokenCursor<'a> { impl<'a> From<CharCursor<'a>> for TokenCursor<'a> {
fn from(mut cursor: CharCursor<'a>) -> Self { fn from(mut cursor: CharCursor<'a>) -> Self {
let cur = TokenInstance::parse(&mut cursor); let cur = TokenInstance::parse(&mut cursor);
Self { cursor, next: cur } Self {
cursor,
next: cur,
next_pos: FilePos::start(),
prev_end: FilePos::start(),
}
} }
} }

View File

@@ -1,31 +1,35 @@
use super::{token::{FileRegion, TokenInstance}, FilePos}; use super::{
token::{FileSpan, TokenInstance},
FilePos,
};
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ParserError { pub struct ParserError {
pub msg: String, pub msg: String,
pub regions: Vec<FileRegion>, pub spans: Vec<FileSpan>,
}
pub struct ParserErrors {
pub errs: Vec<ParserError>,
} }
impl ParserError { impl ParserError {
pub fn from_instances(instances: &[&TokenInstance], msg: String) -> Self { pub fn from_instances(instances: &[&TokenInstance], msg: String) -> Self {
ParserError { ParserError {
msg, msg,
regions: instances.iter().map(|i| i.region).collect(), spans: instances.iter().map(|i| i.span).collect(),
} }
} }
pub fn from_msg(msg: String) -> Self { pub fn from_msg(msg: String) -> Self {
Self { Self {
msg, msg,
regions: Vec::new(), spans: Vec::new(),
} }
} }
pub fn at(pos: FilePos, msg: String) -> Self { pub fn at(pos: FilePos, msg: String) -> Self {
Self { Self {
msg, msg,
regions: vec![FileRegion { spans: vec![FileSpan::at(pos)],
start: pos,
end: pos,
}],
} }
} }
pub fn unexpected_end() -> Self { pub fn unexpected_end() -> Self {
@@ -39,12 +43,17 @@ impl ParserError {
) )
} }
pub fn write_for(&self, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> { pub fn write_for(&self, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> {
let after = if self.regions.is_empty() { "" } else { ":" }; let after = if self.spans.is_empty() { "" } else { ":" };
writeln!(writer, "error: {}{}", self.msg, after)?; writeln!(writer, "error: {}{}", self.msg, after)?;
for reg in &self.regions { for span in &self.spans {
reg.write_for(writer, file)?; span.write_for(writer, file)?;
} }
Ok(()) Ok(())
} }
} }
impl ParserErrors {
pub fn add(&mut self, err: ParserError) {
self.errs.push(err);
}
}

View File

@@ -1,14 +1,15 @@
use std::fmt::{Debug, Write}; use std::fmt::{Debug, Write};
use super::token::{Symbol, Token}; use super::token::{Symbol, Token};
use super::{Body, Number, ParserError, TokenCursor, Val}; use super::{Body, Node, NodeContainer, Parsable, ParserError, TokenCursor, Val};
#[derive(Clone)]
pub enum Expr { pub enum Expr {
Val(Val), Val(Node<Val>),
Ident(String), Ident(String),
BinaryOp(Operator, Box<Expr>, Box<Expr>), BinaryOp(Operator, Node<Box<Expr>>, Node<Box<Expr>>),
Block(Body), Block(Node<Body>),
Call(Box<Expr>, Vec<Expr>), Call(Node<Box<Expr>>, Vec<Node<Expr>>),
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -22,64 +23,78 @@ pub enum Operator {
Access, Access,
} }
impl Expr { impl Parsable for Expr {
pub fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
let start = cursor.next_pos();
let Some(next) = cursor.peek() else { let Some(next) = cursor.peek() else {
return Ok(Expr::Val(Val::Unit)); return Ok(Expr::Val(Node::new(
Val::Unit,
cursor.next_pos().char_span(),
)));
}; };
let mut e1 = if next.is_symbol(Symbol::OpenParen) { let mut e1 = if next.is_symbol(Symbol::OpenParen) {
cursor.next(); cursor.next();
let expr = Self::parse(cursor)?; let expr = Node::parse(cursor);
cursor.expect_sym(Symbol::CloseParen)?; if expr.is_ok() {
expr cursor.expect_sym(Symbol::CloseParen)?;
} else {
cursor.seek_sym(Symbol::CloseParen);
}
expr.take()?
} else if next.is_symbol(Symbol::OpenCurly) { } else if next.is_symbol(Symbol::OpenCurly) {
let expr = Body::parse(cursor)?; Self::Block(Node::parse(cursor))
Expr::Block(expr) } else if let Some(val) = Node::maybe_parse(cursor) {
Self::Val(val)
} else { } else {
Self::parse_unit(cursor)? let next = cursor.peek().unwrap();
match &next.token {
Token::Ident(name) => {
let name = name.to_string();
cursor.next();
Self::Ident(name)
}
_ => {
return Ok(Expr::Val(Node::new(
Val::Unit,
cursor.next_pos().char_span(),
)))
}
}
}; };
let Some(mut next) = cursor.peek() else { let Some(mut next) = cursor.peek() else {
return Ok(e1); return Ok(e1);
}; };
while next.is_symbol(Symbol::OpenParen) { while next.is_symbol(Symbol::OpenParen) {
cursor.next(); cursor.next();
let inner = Self::parse(cursor)?; let inner = Node::parse(cursor);
cursor.expect_sym(Symbol::CloseParen)?; cursor.expect_sym(Symbol::CloseParen)?;
e1 = Self::Call(Box::new(e1), vec![inner]); let end = cursor.prev_end();
e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), vec![inner]);
let Some(next2) = cursor.peek() else { let Some(next2) = cursor.peek() else {
return Ok(e1); return Ok(e1);
}; };
next = next2 next = next2
} }
Ok(if let Some(op) = Operator::from_token(&next.token) { let end = cursor.prev_end();
Ok(if let Some(mut op) = Operator::from_token(&next.token) {
cursor.next(); cursor.next();
let e2 = Self::parse(cursor)?; let mut n1 = Node::new(Box::new(e1), start.to(end));
if let Self::BinaryOp(op_next, e3, e4) = e2 { let mut n2 = Node::<Self>::parse(cursor);
if op.presedence() > op_next.presedence() { if let Ok(Self::BinaryOp(op2, n21, n22)) = &*n2 {
Self::BinaryOp(op_next, Box::new(Self::BinaryOp(op, Box::new(e1), e3)), e4) if op.presedence() > op2.presedence() {
} else { n1 = Node::new(
Self::BinaryOp(op, Box::new(e1), Box::new(Self::BinaryOp(op_next, e3, e4))) Box::new(Self::BinaryOp(op, n1, n21.clone())),
start.to(n21.span.end),
);
op = *op2;
n2 = n22.clone().unbx();
} }
} else {
Self::BinaryOp(op, Box::new(e1), Box::new(e2))
} }
Self::BinaryOp(op, n1, n2.bx())
} else { } else {
e1 e1
}) })
} }
fn parse_unit(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
if let Some(val) = Val::parse(cursor)? {
return Ok(Self::Val(val));
}
let inst = cursor.expect_next()?;
match &inst.token {
Token::Ident(name) => Ok(Self::Ident(name.to_string())),
_ => Err(ParserError::unexpected_token(
&inst,
"an identifier or value",
)),
}
}
} }
impl Operator { impl Operator {
@@ -166,3 +181,18 @@ impl Debug for Expr {
Ok(()) Ok(())
} }
} }
impl NodeContainer for Expr {
fn children(&self) -> Vec<Node<Box<dyn NodeContainer>>> {
match self {
Expr::Val(_) => Vec::new(),
Expr::Ident(_) => Vec::new(),
Expr::BinaryOp(_, e1, e2) => vec![e1.container(), e2.container()],
Expr::Block(b) => vec![b.containerr()],
Expr::Call(e1, rest) => [e1.container()]
.into_iter()
.chain(rest.iter().map(|e| e.containerr()))
.collect(),
}
}
}

View File

@@ -6,34 +6,37 @@ mod error;
mod expr; mod expr;
mod token; mod token;
mod val; mod val;
mod node;
pub use body::*; pub use body::*;
pub use cursor::*; pub use cursor::*;
pub use error::*; pub use error::*;
pub use expr::*; pub use expr::*;
pub use val::*; pub use val::*;
pub use node::*;
use token::*; use token::*;
#[derive(Debug)] #[derive(Debug)]
pub struct Module { pub struct Module {
functions: Vec<Function>, functions: Vec<Node<Function>>,
} }
#[derive(Clone)]
pub struct Function { pub struct Function {
pub name: String, pub name: String,
pub body: Body, pub body: Node<Body>,
} }
impl Module { impl Parsable for Module {
pub fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
let mut functions = Vec::new(); let mut functions = Vec::new();
loop { loop {
let Some(next) = cursor.peek() else { let Some(next) = cursor.peek() else {
return Ok(Self { functions }); return Ok(Self { functions });
}; };
if next.is_keyword(Keyword::Fn) { if next.is_keyword(Keyword::Fn) {
functions.push(Function::parse(cursor)?); functions.push(Node::parse(cursor));
} else { } else {
return Err(ParserError::unexpected_token(next, "fn")); return Err(ParserError::unexpected_token(next, "fn"));
} }
@@ -41,13 +44,13 @@ impl Module {
} }
} }
impl Function { impl Parsable for Function {
pub fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> { fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
cursor.expect_kw(Keyword::Fn)?; cursor.expect_kw(Keyword::Fn)?;
let name = cursor.expect_ident()?; let name = cursor.expect_ident()?;
cursor.expect_sym(Symbol::OpenParen)?; cursor.expect_sym(Symbol::OpenParen)?;
cursor.expect_sym(Symbol::CloseParen)?; cursor.expect_sym(Symbol::CloseParen)?;
let body = Body::parse(cursor)?; let body = Node::parse(cursor);
Ok(Self { name, body }) Ok(Self { name, body })
} }
} }
@@ -61,3 +64,15 @@ impl Debug for Function {
Ok(()) Ok(())
} }
} }
impl NodeContainer for Module {
fn children(&self) -> Vec<Node<Box<dyn NodeContainer>>> {
self.functions.iter().map(|f| f.containerr()).collect()
}
}
impl NodeContainer for Function {
fn children(&self) -> Vec<Node<Box<dyn NodeContainer>>> {
vec![self.body.containerr()]
}
}

132
src/v1/parser/node.rs Normal file
View File

@@ -0,0 +1,132 @@
use std::{
fmt::Debug,
ops::{Deref, DerefMut},
};
use super::{FileSpan, ParserError, TokenCursor};
#[derive(Clone)]
pub struct Node<T> {
pub inner: Result<T, ParserError>,
pub span: FileSpan,
}
pub trait Parsable: Sized {
fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError>;
}
pub trait MaybeParsable: Sized {
fn maybe_parse(cursor: &mut TokenCursor) -> Result<Option<Self>, ParserError>;
}
pub trait NodeContainer {
fn children(&self) -> Vec<Node<Box<dyn NodeContainer>>>;
}
impl<T: NodeContainer + ?Sized> NodeContainer for Node<Box<T>> {
fn children(&self) -> Vec<Node<Box<dyn NodeContainer>>> {
match &self.inner {
Ok(v) => v.children(),
Err(_) => Vec::new(),
}
}
}
impl<T: Parsable> Node<T> {
pub fn parse(cursor: &mut TokenCursor) -> Self {
let start = cursor.next_pos();
let inner = T::parse(cursor);
let end = cursor.prev_end();
Self {
inner,
span: start.to(end),
}
}
}
impl<T: MaybeParsable> Node<T> {
pub fn maybe_parse(cursor: &mut TokenCursor) -> Option<Self> {
let start = cursor.next_pos();
let inner = match T::maybe_parse(cursor) {
Ok(v) => Ok(v?),
Err(e) => Err(e),
};
let end = cursor.prev_end();
Some(Self {
inner,
span: start.to(end),
})
}
}
impl<T> Node<T> {
pub fn new(inner: T, span: FileSpan) -> Self {
Self {
inner: Ok(inner),
span,
}
}
pub fn err(inner: ParserError, span: FileSpan) -> Self {
Self {
inner: Err(inner),
span,
}
}
pub fn take(self) -> Result<T, ParserError> {
self.inner
}
pub fn bx(self) -> Node<Box<T>> {
Node {
inner: self.inner.map(|v| Box::new(v)),
span: self.span,
}
}
}
impl<T: NodeContainer + Clone + 'static> Node<T> {
pub fn containerr(&self) -> Node<Box<dyn NodeContainer>> {
Node {
inner: self.clone().inner.map(|v| Box::new(v) as Box<dyn NodeContainer>),
span: self.span,
}
}
}
impl<T> Node<Box<T>> {
pub fn unbx(self) -> Node<T> {
Node {
inner: self.inner.map(|v| *v),
span: self.span,
}
}
}
impl<T: NodeContainer + Clone + 'static> Node<Box<T>> {
pub fn container(&self) -> Node<Box<dyn NodeContainer>> {
Node {
inner: self.clone().inner.map(|v| v as Box<dyn NodeContainer>),
span: self.span,
}
}
}
impl<T> Deref for Node<T> {
type Target = Result<T, ParserError>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T> DerefMut for Node<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<T: Debug> Debug for Node<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.inner {
Ok(v) => v.fmt(f),
Err(_) => f.write_str("{error}"),
}
}
}

View File

@@ -1,12 +1,11 @@
use std::{iter::Peekable, str::Chars}; use std::{iter::Peekable, str::Chars};
use crate::v1::parser::ParserError; use super::super::ParserError;
use super::FilePos; use super::FilePos;
pub struct CharCursor<'a> { pub struct CharCursor<'a> {
chars: Peekable<Chars<'a>>, chars: Peekable<Chars<'a>>,
pos: FilePos, next_pos: FilePos,
prev_pos: FilePos, prev_pos: FilePos,
} }
@@ -39,12 +38,12 @@ impl CharCursor<'_> {
let Some(next) = self.chars.next() else { let Some(next) = self.chars.next() else {
return; return;
}; };
self.prev_pos = self.pos; self.prev_pos = self.next_pos;
if next == '\n' { if next == '\n' {
self.pos.col = 0; self.next_pos.col = 0;
self.pos.line += 1; self.next_pos.line += 1;
} else { } else {
self.pos.col += 1; self.next_pos.col += 1;
} }
} }
pub fn advance_if(&mut self, c: char) -> bool { pub fn advance_if(&mut self, c: char) -> bool {
@@ -57,11 +56,10 @@ impl CharCursor<'_> {
false false
} }
pub fn expect_next(&mut self) -> Result<char, ParserError> { pub fn expect_next(&mut self) -> Result<char, ParserError> {
self.next() self.next().ok_or(ParserError::unexpected_end())
.ok_or(ParserError::from_msg("Unexpected end of input".to_string()))
} }
pub fn pos(&self) -> FilePos { pub fn next_pos(&self) -> FilePos {
self.pos self.next_pos
} }
pub fn prev_pos(&self) -> FilePos { pub fn prev_pos(&self) -> FilePos {
self.prev_pos self.prev_pos
@@ -72,7 +70,7 @@ impl<'a> From<&'a str> for CharCursor<'a> {
fn from(value: &'a str) -> Self { fn from(value: &'a str) -> Self {
Self { Self {
chars: value.chars().peekable(), chars: value.chars().peekable(),
pos: FilePos::start(), next_pos: FilePos::start(),
prev_pos: FilePos::start(), prev_pos: FilePos::start(),
} }
} }

View File

@@ -5,7 +5,7 @@ pub struct FilePos {
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct FileRegion { pub struct FileSpan {
pub start: FilePos, pub start: FilePos,
pub end: FilePos, pub end: FilePos,
} }
@@ -16,10 +16,25 @@ impl FilePos {
} }
} }
impl FilePos {
pub fn to(self, end: FilePos) -> FileSpan {
FileSpan { start: self, end }
}
pub fn char_span(self) -> FileSpan {
FileSpan::at(self)
}
}
const BEFORE: usize = 1; const BEFORE: usize = 1;
const AFTER: usize = 1; const AFTER: usize = 1;
impl FileRegion { impl FileSpan {
pub fn at(pos: FilePos) -> Self {
Self {
start: pos,
end: pos,
}
}
pub fn write_for(&self, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> { pub fn write_for(&self, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> {
let start = self.start.line.saturating_sub(BEFORE); let start = self.start.line.saturating_sub(BEFORE);
let num_before = self.start.line - start; let num_before = self.start.line - start;

View File

@@ -3,6 +3,8 @@ mod file;
mod keyword; mod keyword;
mod symbol; mod symbol;
use std::ops::Deref;
pub use cursor::*; pub use cursor::*;
pub use file::*; pub use file::*;
pub use keyword::*; pub use keyword::*;
@@ -15,17 +17,17 @@ pub enum Token {
Keyword(Keyword), Keyword(Keyword),
} }
#[derive(Debug)] #[derive(Clone)]
pub struct TokenInstance { pub struct TokenInstance {
pub token: Token, pub token: Token,
pub region: FileRegion, pub span: FileSpan,
} }
impl TokenInstance { impl TokenInstance {
pub fn parse(cursor: &mut CharCursor) -> Option<TokenInstance> { pub fn parse(cursor: &mut CharCursor) -> Option<TokenInstance> {
cursor.skip_whitespace(); cursor.skip_whitespace();
cursor.peek()?; cursor.peek()?;
let start = cursor.pos(); let start = cursor.next_pos();
if let Some(s) = Symbol::parse(cursor) { if let Some(s) = Symbol::parse(cursor) {
if s == Symbol::DoubleSlash { if s == Symbol::DoubleSlash {
while cursor.next() != Some('\n') {} while cursor.next() != Some('\n') {}
@@ -34,7 +36,7 @@ impl TokenInstance {
let end = cursor.prev_pos(); let end = cursor.prev_pos();
return Some(Self { return Some(Self {
token: Token::Symbol(s), token: Token::Symbol(s),
region: FileRegion { start, end }, span: FileSpan { start, end },
}); });
} }
let mut word = String::new(); let mut word = String::new();
@@ -53,7 +55,7 @@ impl TokenInstance {
}; };
Some(Self { Some(Self {
token, token,
region: FileRegion { start, end }, span: FileSpan { start, end },
}) })
} }
} }
@@ -65,6 +67,12 @@ impl Token {
_ => false, _ => false,
} }
} }
pub fn is_symbol_and(&self, f: impl Fn(Symbol) -> bool) -> bool {
match self {
Token::Symbol(s) => f(*s),
_ => false,
}
}
pub fn is_keyword(&self, kw: Keyword) -> bool { pub fn is_keyword(&self, kw: Keyword) -> bool {
match self { match self {
Token::Keyword(k) => *k == kw, Token::Keyword(k) => *k == kw,
@@ -73,11 +81,10 @@ impl Token {
} }
} }
impl TokenInstance { impl Deref for TokenInstance {
pub fn is_keyword(&self, kw: Keyword) -> bool { type Target = Token;
self.token.is_keyword(kw)
} fn deref(&self) -> &Self::Target {
pub fn is_symbol(&self, symbol: Symbol) -> bool { &self.token
self.token.is_symbol(symbol)
} }
} }

View File

@@ -1,7 +1,7 @@
use super::{CharCursor, ParserError, Symbol, Token, TokenCursor}; use super::{CharCursor, MaybeParsable, NodeContainer, ParserError, Symbol, Token, TokenCursor};
use std::fmt::Debug; use std::fmt::Debug;
#[derive(PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub enum Val { pub enum Val {
String(String), String(String),
Char(char), Char(char),
@@ -9,15 +9,15 @@ pub enum Val {
Unit, Unit,
} }
#[derive(PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct Number { pub struct Number {
pub whole: String, pub whole: String,
pub decimal: Option<String>, pub decimal: Option<String>,
pub ty: Option<String>, pub ty: Option<String>,
} }
impl Val { impl MaybeParsable for Val {
pub fn parse(cursor: &mut TokenCursor) -> Result<Option<Self>, ParserError> { fn maybe_parse(cursor: &mut TokenCursor) -> Result<Option<Self>, ParserError> {
let inst = cursor.expect_peek()?; let inst = cursor.expect_peek()?;
let mut res = match &inst.token { let mut res = match &inst.token {
Token::Symbol(Symbol::SingleQuote) => { Token::Symbol(Symbol::SingleQuote) => {
@@ -108,3 +108,4 @@ impl Debug for Number {
Ok(()) Ok(())
} }
} }

View File

@@ -109,7 +109,7 @@ impl Debug for Body {
let mut padder = Padder::new(f); let mut padder = Padder::new(f);
for s in &self.statements { for s in &self.statements {
// they don't expose wrap_buf :grief: // they don't expose wrap_buf :grief:
write!(padder, "{s:?}\n")?; writeln!(padder, "{s:?}")?;
} }
write!(f, "}}")?; write!(f, "}}")?;
} else { } else {

View File

@@ -3,7 +3,7 @@ fn main() {
let y = 4 + 4 + 5; let y = 4 + 4 + 5;
let z = 1 * 2 - 3 / test * 4; let z = 1 * 2 - 3 / test * 4;
let r = 1-2.5 + 3; let r = 1-2.5 + 3;
let w = 1 * (2 - 3) / "test" - 7; let w = 1 * (2 - 3) / "test" - 7
let a = test('3'); let a = test('3');
let c = '3' ; let c = '3' ;
test(5); test(5);