jugando
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
#![feature(box_patterns)]
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
mod v1;
|
mod v1;
|
||||||
mod v2;
|
mod v2;
|
||||||
|
|||||||
@@ -2,38 +2,30 @@ use std::io::{stdout, BufRead, BufReader};
|
|||||||
|
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
use parser::{Module, Node, NodeContainer, Statement, TokenCursor};
|
use parser::{Module, Node, ParserErrors, Statement, TokenCursor};
|
||||||
|
|
||||||
pub fn parse_file(file: &str) {
|
pub fn parse_file(file: &str) {
|
||||||
let node = Node::<Module>::parse(&mut TokenCursor::from(file));
|
let mut errors = ParserErrors::new();
|
||||||
match node.inner {
|
let node = Node::<Module>::parse(&mut TokenCursor::from(file), &mut errors);
|
||||||
Err(err) => err.write_for(&mut stdout(), file).unwrap(),
|
if let Ok(module) = node.as_ref() {
|
||||||
Ok(module) => {
|
|
||||||
println!("{module:#?}");
|
println!("{module:#?}");
|
||||||
print_errors(module.children(), file)
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
for err in errors.errs {
|
||||||
|
|
||||||
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();
|
err.write_for(&mut stdout(), file).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for node in nodes {
|
|
||||||
print_errors(node.children(), file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_stdin() {
|
pub fn run_stdin() {
|
||||||
for line in BufReader::new(std::io::stdin()).lines() {
|
for line in BufReader::new(std::io::stdin()).lines() {
|
||||||
|
let mut errors = ParserErrors::new();
|
||||||
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 Node::<Statement>::parse(&mut cursor).inner {
|
if let Ok(expr) = Node::<Statement>::parse(&mut cursor, &mut errors).as_ref() {
|
||||||
Ok(expr) => println!("{:?}", expr),
|
println!("{:?}", expr);
|
||||||
Err(err) => err.write_for(out, str).unwrap(),
|
}
|
||||||
|
for err in errors.errs {
|
||||||
|
err.write_for(&mut stdout(), str).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use std::fmt::{Debug, Write};
|
use std::fmt::{Debug, Write};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
token::{Keyword, Symbol, Token}, Node, NodeContainer, Parsable
|
token::{Keyword, Symbol, Token},
|
||||||
|
Node, Parsable, ParserErrors,
|
||||||
};
|
};
|
||||||
use crate::util::Padder;
|
use crate::util::Padder;
|
||||||
|
|
||||||
@@ -19,8 +20,19 @@ pub enum Statement {
|
|||||||
Expr(Node<Expr>),
|
Expr(Node<Expr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Statement {
|
||||||
|
pub fn ended_with_error(&self) -> bool {
|
||||||
|
let expr = match self {
|
||||||
|
Statement::Let(_, e) => e,
|
||||||
|
Statement::Return(e) => e,
|
||||||
|
Statement::Expr(e) => e,
|
||||||
|
};
|
||||||
|
expr.is_err() || expr.as_ref().is_ok_and(|e| e.ended_with_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parsable for Body {
|
impl Parsable for Body {
|
||||||
fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
|
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
|
let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
|
||||||
cursor.expect_sym(Symbol::OpenCurly)?;
|
cursor.expect_sym(Symbol::OpenCurly)?;
|
||||||
@@ -28,54 +40,51 @@ impl Parsable for Body {
|
|||||||
cursor.next();
|
cursor.next();
|
||||||
return Ok(Self { statements });
|
return Ok(Self { statements });
|
||||||
}
|
}
|
||||||
|
let mut expect_semi = false;
|
||||||
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(Node::parse(cursor));
|
if next.is_symbol(Symbol::Semicolon) {
|
||||||
let next = cursor.expect_next()?;
|
cursor.next();
|
||||||
match next.token {
|
expect_semi = false;
|
||||||
Token::Symbol(Symbol::Semicolon) => continue,
|
continue;
|
||||||
Token::Symbol(Symbol::CloseCurly) => return Ok(Self { statements }),
|
} else if expect_semi {
|
||||||
_ => {
|
errors.add(ParserError {
|
||||||
let start = next.span.start;
|
msg: "expected ';'".to_string(),
|
||||||
cursor
|
spans: vec![cursor.next_pos().char_span()],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let statement: Node<Statement> = Node::parse(cursor, errors);
|
||||||
|
expect_semi = true;
|
||||||
|
if statement.is_err() || statement.as_ref().is_ok_and(|s| s.ended_with_error()) {
|
||||||
|
let res = cursor
|
||||||
.seek(|t| t.is_symbol_and(|s| statement_end.contains(&s)))
|
.seek(|t| t.is_symbol_and(|s| statement_end.contains(&s)))
|
||||||
.ok_or(ParserError::unexpected_end())?;
|
.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 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
statements.push(statement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parsable for Statement {
|
impl Parsable for Statement {
|
||||||
fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
|
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> 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 = Node::parse(cursor);
|
let expr = Node::parse(cursor, errors);
|
||||||
Self::Let(name, expr)
|
Self::Let(name, expr)
|
||||||
}
|
}
|
||||||
Token::Keyword(Keyword::Return) => {
|
Token::Keyword(Keyword::Return) => {
|
||||||
cursor.next();
|
cursor.next();
|
||||||
Self::Return(Node::parse(cursor))
|
Self::Return(Node::parse(cursor, errors))
|
||||||
}
|
}
|
||||||
_ => Self::Expr(Node::parse(cursor)),
|
_ => Self::Expr(Node::parse(cursor, errors)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,19 +129,3 @@ 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()],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ impl ParserError {
|
|||||||
let t = &inst.token;
|
let t = &inst.token;
|
||||||
ParserError::from_instances(
|
ParserError::from_instances(
|
||||||
&[inst],
|
&[inst],
|
||||||
format!("Unexpected token {t:?}; expected {expected}"),
|
format!("unexpected token {t:?}; expected {expected}"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
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<()> {
|
||||||
@@ -53,6 +53,9 @@ impl ParserError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ParserErrors {
|
impl ParserErrors {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { errs: Vec::new() }
|
||||||
|
}
|
||||||
pub fn add(&mut self, err: ParserError) {
|
pub fn add(&mut self, err: ParserError) {
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
use std::fmt::{Debug, Write};
|
use std::fmt::{Debug, Write};
|
||||||
|
|
||||||
use super::token::{Symbol, Token};
|
use super::token::{Symbol, Token};
|
||||||
use super::{Body, Node, NodeContainer, Parsable, ParserError, TokenCursor, Val};
|
use super::{Body, Node, Parsable, ParserError, ParserErrors, TokenCursor, Val};
|
||||||
|
|
||||||
|
pub type ExprNode = Node<Box<Expr>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Val(Node<Val>),
|
Val(Node<Val>),
|
||||||
Ident(String),
|
Ident(String),
|
||||||
BinaryOp(Operator, Node<Box<Expr>>, Node<Box<Expr>>),
|
BinaryOp(Operator, ExprNode, ExprNode),
|
||||||
Block(Node<Body>),
|
Block(Node<Body>),
|
||||||
Call(Node<Box<Expr>>, Vec<Node<Expr>>),
|
Call(ExprNode, Vec<Node<Expr>>),
|
||||||
|
Group(ExprNode),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
@@ -21,29 +24,44 @@ pub enum Operator {
|
|||||||
LessThan,
|
LessThan,
|
||||||
GreaterThan,
|
GreaterThan,
|
||||||
Access,
|
Access,
|
||||||
|
Assign,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Expr {
|
||||||
|
pub fn ended_with_error(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Expr::Val(_) => false,
|
||||||
|
Expr::Ident(_) => false,
|
||||||
|
Expr::BinaryOp(_, _, e) => e.is_err() || e.as_ref().is_ok_and(|e| e.ended_with_error()),
|
||||||
|
Expr::Block(b) => b.is_err(),
|
||||||
|
Expr::Call(_, _) => false,
|
||||||
|
Expr::Group(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parsable for Expr {
|
impl Parsable for Expr {
|
||||||
fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
|
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError> {
|
||||||
let start = cursor.next_pos();
|
let start = cursor.next_pos();
|
||||||
let Some(next) = cursor.peek() else {
|
let next = cursor.expect_peek()?;
|
||||||
|
let mut e1 = if next.is_symbol(Symbol::OpenParen) {
|
||||||
|
cursor.next();
|
||||||
|
if cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
|
||||||
|
cursor.next();
|
||||||
return Ok(Expr::Val(Node::new(
|
return Ok(Expr::Val(Node::new(
|
||||||
Val::Unit,
|
Val::Unit,
|
||||||
cursor.next_pos().char_span(),
|
cursor.next_pos().char_span(),
|
||||||
)));
|
)));
|
||||||
};
|
}
|
||||||
let mut e1 = if next.is_symbol(Symbol::OpenParen) {
|
let expr = Node::parse(cursor, errors).bx();
|
||||||
cursor.next();
|
if expr.is_err() {
|
||||||
let expr = Node::parse(cursor);
|
|
||||||
if expr.is_ok() {
|
|
||||||
cursor.expect_sym(Symbol::CloseParen)?;
|
|
||||||
} else {
|
|
||||||
cursor.seek_sym(Symbol::CloseParen);
|
cursor.seek_sym(Symbol::CloseParen);
|
||||||
}
|
}
|
||||||
expr.take()?
|
cursor.expect_sym(Symbol::CloseParen)?;
|
||||||
|
Self::Group(expr)
|
||||||
} else if next.is_symbol(Symbol::OpenCurly) {
|
} else if next.is_symbol(Symbol::OpenCurly) {
|
||||||
Self::Block(Node::parse(cursor))
|
Self::Block(Node::parse(cursor, errors))
|
||||||
} else if let Some(val) = Node::maybe_parse(cursor) {
|
} else if let Some(val) = Node::maybe_parse(cursor, errors) {
|
||||||
Self::Val(val)
|
Self::Val(val)
|
||||||
} else {
|
} else {
|
||||||
let next = cursor.peek().unwrap();
|
let next = cursor.peek().unwrap();
|
||||||
@@ -54,10 +72,7 @@ impl Parsable for Expr {
|
|||||||
Self::Ident(name)
|
Self::Ident(name)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Ok(Expr::Val(Node::new(
|
return Err(ParserError::unexpected_token(next, "an expression"));
|
||||||
Val::Unit,
|
|
||||||
cursor.next_pos().char_span(),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -66,7 +81,7 @@ impl Parsable for Expr {
|
|||||||
};
|
};
|
||||||
while next.is_symbol(Symbol::OpenParen) {
|
while next.is_symbol(Symbol::OpenParen) {
|
||||||
cursor.next();
|
cursor.next();
|
||||||
let inner = Node::parse(cursor);
|
let inner = Node::parse(cursor, errors);
|
||||||
cursor.expect_sym(Symbol::CloseParen)?;
|
cursor.expect_sym(Symbol::CloseParen)?;
|
||||||
let end = cursor.prev_end();
|
let end = cursor.prev_end();
|
||||||
e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), vec![inner]);
|
e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), vec![inner]);
|
||||||
@@ -79,18 +94,18 @@ impl Parsable for Expr {
|
|||||||
Ok(if let Some(mut op) = Operator::from_token(&next.token) {
|
Ok(if let Some(mut op) = Operator::from_token(&next.token) {
|
||||||
cursor.next();
|
cursor.next();
|
||||||
let mut n1 = Node::new(Box::new(e1), start.to(end));
|
let mut n1 = Node::new(Box::new(e1), start.to(end));
|
||||||
let mut n2 = Node::<Self>::parse(cursor);
|
let mut n2 = Node::parse(cursor, errors).bx();
|
||||||
if let Ok(Self::BinaryOp(op2, n21, n22)) = &*n2 {
|
if let Ok(box Self::BinaryOp(op2, n21, n22)) = n2.as_ref() {
|
||||||
if op.presedence() > op2.presedence() {
|
if op.presedence() > op2.presedence() {
|
||||||
n1 = Node::new(
|
n1 = Node::new(
|
||||||
Box::new(Self::BinaryOp(op, n1, n21.clone())),
|
Box::new(Self::BinaryOp(op, n1, n21.clone())),
|
||||||
start.to(n21.span.end),
|
start.to(n21.span.end),
|
||||||
);
|
);
|
||||||
op = *op2;
|
op = *op2;
|
||||||
n2 = n22.clone().unbx();
|
n2 = n22.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::BinaryOp(op, n1, n2.bx())
|
Self::BinaryOp(op, n1, n2)
|
||||||
} else {
|
} else {
|
||||||
e1
|
e1
|
||||||
})
|
})
|
||||||
@@ -100,13 +115,14 @@ impl Parsable for Expr {
|
|||||||
impl Operator {
|
impl Operator {
|
||||||
pub fn presedence(&self) -> u32 {
|
pub fn presedence(&self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
Operator::LessThan => 0,
|
Operator::Assign => 0,
|
||||||
Operator::GreaterThan => 0,
|
Operator::LessThan => 1,
|
||||||
Operator::Add => 1,
|
Operator::GreaterThan => 1,
|
||||||
Operator::Sub => 2,
|
Operator::Add => 2,
|
||||||
Operator::Mul => 3,
|
Operator::Sub => 3,
|
||||||
Operator::Div => 4,
|
Operator::Mul => 4,
|
||||||
Operator::Access => 5,
|
Operator::Div => 5,
|
||||||
|
Operator::Access => 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn str(&self) -> &str {
|
pub fn str(&self) -> &str {
|
||||||
@@ -118,6 +134,7 @@ impl Operator {
|
|||||||
Self::LessThan => "<",
|
Self::LessThan => "<",
|
||||||
Self::GreaterThan => ">",
|
Self::GreaterThan => ">",
|
||||||
Self::Access => ".",
|
Self::Access => ".",
|
||||||
|
Self::Assign => "=",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn from_token(token: &Token) -> Option<Self> {
|
pub fn from_token(token: &Token) -> Option<Self> {
|
||||||
@@ -132,6 +149,7 @@ impl Operator {
|
|||||||
Symbol::Asterisk => Operator::Mul,
|
Symbol::Asterisk => Operator::Mul,
|
||||||
Symbol::Slash => Operator::Div,
|
Symbol::Slash => Operator::Div,
|
||||||
Symbol::Dot => Operator::Access,
|
Symbol::Dot => Operator::Access,
|
||||||
|
Symbol::Equals => Operator::Assign,
|
||||||
_ => {
|
_ => {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -139,13 +157,14 @@ impl Operator {
|
|||||||
}
|
}
|
||||||
pub fn pad(&self) -> bool {
|
pub fn pad(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Operator::Add => true,
|
Self::Add => true,
|
||||||
Operator::Sub => true,
|
Self::Sub => true,
|
||||||
Operator::Mul => true,
|
Self::Mul => true,
|
||||||
Operator::Div => true,
|
Self::Div => true,
|
||||||
Operator::LessThan => true,
|
Self::LessThan => true,
|
||||||
Operator::GreaterThan => true,
|
Self::GreaterThan => true,
|
||||||
Operator::Access => false,
|
Self::Access => false,
|
||||||
|
Self::Assign => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,22 +196,8 @@ impl Debug for Expr {
|
|||||||
}
|
}
|
||||||
f.write_char(')')?;
|
f.write_char(')')?;
|
||||||
}
|
}
|
||||||
|
Expr::Group(inner) => inner.fmt(f)?,
|
||||||
}
|
}
|
||||||
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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ pub struct Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Parsable for Module {
|
impl Parsable for Module {
|
||||||
fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
|
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> 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(Node::parse(cursor));
|
functions.push(Node::parse(cursor, errors));
|
||||||
} else {
|
} else {
|
||||||
return Err(ParserError::unexpected_token(next, "fn"));
|
return Err(ParserError::unexpected_token(next, "fn"));
|
||||||
}
|
}
|
||||||
@@ -45,12 +45,12 @@ impl Parsable for Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Parsable for Function {
|
impl Parsable for Function {
|
||||||
fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError> {
|
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> 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 = Node::parse(cursor);
|
let body = Node::parse(cursor, errors);
|
||||||
Ok(Self { name, body })
|
Ok(Self { name, body })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,14 +65,3 @@ impl Debug for Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,39 +3,29 @@ use std::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{FileSpan, ParserError, TokenCursor};
|
use super::{FileSpan, ParserError, ParserErrors, TokenCursor};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Node<T> {
|
pub struct Node<T> {
|
||||||
pub inner: Result<T, ParserError>,
|
pub inner: Result<T, ()>,
|
||||||
pub span: FileSpan,
|
pub span: FileSpan,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Parsable: Sized {
|
pub trait Parsable: Sized {
|
||||||
fn parse(cursor: &mut TokenCursor) -> Result<Self, ParserError>;
|
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result<Self, ParserError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MaybeParsable: Sized {
|
pub trait MaybeParsable: Sized {
|
||||||
fn maybe_parse(cursor: &mut TokenCursor) -> Result<Option<Self>, ParserError>;
|
fn maybe_parse(
|
||||||
}
|
cursor: &mut TokenCursor,
|
||||||
|
errors: &mut ParserErrors,
|
||||||
pub trait NodeContainer {
|
) -> Result<Option<Self>, ParserError>;
|
||||||
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> {
|
impl<T: Parsable> Node<T> {
|
||||||
pub fn parse(cursor: &mut TokenCursor) -> Self {
|
pub fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Self {
|
||||||
let start = cursor.next_pos();
|
let start = cursor.next_pos();
|
||||||
let inner = T::parse(cursor);
|
let inner = T::parse(cursor, errors).map_err(|e| errors.add(e));
|
||||||
let end = cursor.prev_end();
|
let end = cursor.prev_end();
|
||||||
Self {
|
Self {
|
||||||
inner,
|
inner,
|
||||||
@@ -45,11 +35,14 @@ impl<T: Parsable> Node<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: MaybeParsable> Node<T> {
|
impl<T: MaybeParsable> Node<T> {
|
||||||
pub fn maybe_parse(cursor: &mut TokenCursor) -> Option<Self> {
|
pub fn maybe_parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Option<Self> {
|
||||||
let start = cursor.next_pos();
|
let start = cursor.next_pos();
|
||||||
let inner = match T::maybe_parse(cursor) {
|
let inner = match T::maybe_parse(cursor, errors) {
|
||||||
Ok(v) => Ok(v?),
|
Ok(v) => Ok(v?),
|
||||||
Err(e) => Err(e),
|
Err(e) => {
|
||||||
|
errors.add(e);
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let end = cursor.prev_end();
|
let end = cursor.prev_end();
|
||||||
Some(Self {
|
Some(Self {
|
||||||
@@ -66,15 +59,6 @@ impl<T> Node<T> {
|
|||||||
span,
|
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>> {
|
pub fn bx(self) -> Node<Box<T>> {
|
||||||
Node {
|
Node {
|
||||||
inner: self.inner.map(|v| Box::new(v)),
|
inner: self.inner.map(|v| Box::new(v)),
|
||||||
@@ -83,15 +67,6 @@ impl<T> Node<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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>> {
|
impl<T> Node<Box<T>> {
|
||||||
pub fn unbx(self) -> Node<T> {
|
pub fn unbx(self) -> Node<T> {
|
||||||
Node {
|
Node {
|
||||||
@@ -100,17 +75,8 @@ impl<T> Node<Box<T>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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> {
|
impl<T> Deref for Node<T> {
|
||||||
type Target = Result<T, ParserError>;
|
type Target = Result<T, ()>;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.inner
|
&self.inner
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ impl FilePos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const BEFORE: usize = 1;
|
const BEFORE: usize = 1;
|
||||||
const AFTER: usize = 1;
|
const AFTER: usize = 0;
|
||||||
|
|
||||||
impl FileSpan {
|
impl FileSpan {
|
||||||
pub fn at(pos: FilePos) -> Self {
|
pub fn at(pos: FilePos) -> Self {
|
||||||
@@ -70,11 +70,11 @@ impl FileSpan {
|
|||||||
"^".repeat(self.end.col + 1)
|
"^".repeat(self.end.col + 1)
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
for i in 0..AFTER {
|
// for i in 0..AFTER {
|
||||||
if let Some(next) = lines.next() {
|
// if let Some(next) = lines.next() {
|
||||||
writeln!(writer, "{:>width$} | {}", self.end.line + i + 1, next)?;
|
// writeln!(writer, "{:>width$} | {}", self.end.line + i + 1, next)?;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub enum Token {
|
|||||||
Keyword(Keyword),
|
Keyword(Keyword),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TokenInstance {
|
pub struct TokenInstance {
|
||||||
pub token: Token,
|
pub token: Token,
|
||||||
pub span: FileSpan,
|
pub span: FileSpan,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ pub enum Symbol {
|
|||||||
CloseAngle,
|
CloseAngle,
|
||||||
SingleQuote,
|
SingleQuote,
|
||||||
DoubleQuote,
|
DoubleQuote,
|
||||||
|
Bang,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Symbol {
|
impl Symbol {
|
||||||
@@ -57,6 +58,7 @@ impl Symbol {
|
|||||||
'.' => Self::Dot,
|
'.' => Self::Dot,
|
||||||
'\'' => Self::SingleQuote,
|
'\'' => Self::SingleQuote,
|
||||||
'"' => Self::DoubleQuote,
|
'"' => Self::DoubleQuote,
|
||||||
|
'!' => Self::Bang,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -88,30 +90,30 @@ impl Symbol {
|
|||||||
}
|
}
|
||||||
pub fn str(&self) -> &str {
|
pub fn str(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
Symbol::Semicolon => ";",
|
Self::Semicolon => ";",
|
||||||
Symbol::Colon => ":",
|
Self::Colon => ":",
|
||||||
Symbol::DoubleColon => "::",
|
Self::DoubleColon => "::",
|
||||||
Symbol::Equals => "=",
|
Self::Equals => "=",
|
||||||
Symbol::DoubleEquals => "==",
|
Self::DoubleEquals => "==",
|
||||||
Symbol::Arrow => "->",
|
Self::Arrow => "->",
|
||||||
Symbol::DoubleArrow => "=>",
|
Self::DoubleArrow => "=>",
|
||||||
Symbol::Plus => "+",
|
Self::Plus => "+",
|
||||||
Symbol::Minus => "-",
|
Self::Minus => "-",
|
||||||
Symbol::Asterisk => "*",
|
Self::Asterisk => "*",
|
||||||
Symbol::Slash => "/",
|
Self::Slash => "/",
|
||||||
Symbol::DoubleSlash => "//",
|
Self::DoubleSlash => "//",
|
||||||
Symbol::Dot => ".",
|
Self::Dot => ".",
|
||||||
Symbol::OpenParen => "(",
|
Self::OpenParen => "(",
|
||||||
Symbol::CloseParen => ")",
|
Self::CloseParen => ")",
|
||||||
Symbol::OpenCurly => "{",
|
Self::OpenCurly => "{",
|
||||||
Symbol::CloseCurly => "}",
|
Self::CloseCurly => "}",
|
||||||
Symbol::OpenSquare => "[",
|
Self::OpenSquare => "[",
|
||||||
Symbol::CloseSquare => "]",
|
Self::CloseSquare => "]",
|
||||||
Symbol::OpenAngle => "<",
|
Self::OpenAngle => "<",
|
||||||
Symbol::CloseAngle => ">",
|
Self::CloseAngle => ">",
|
||||||
Symbol::SingleQuote => "'",
|
Self::SingleQuote => "'",
|
||||||
Symbol::DoubleQuote => "\"",
|
Self::DoubleQuote => "\"",
|
||||||
|
Self::Bang => "!",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::{CharCursor, MaybeParsable, NodeContainer, ParserError, Symbol, Token, TokenCursor};
|
use super::{CharCursor, MaybeParsable, ParserError, ParserErrors, Symbol, Token, TokenCursor};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
@@ -17,7 +17,7 @@ pub struct Number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MaybeParsable for Val {
|
impl MaybeParsable for Val {
|
||||||
fn maybe_parse(cursor: &mut TokenCursor) -> Result<Option<Self>, ParserError> {
|
fn maybe_parse(cursor: &mut TokenCursor, _: &mut ParserErrors) -> 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) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user