conlang: RIP THE EXPRKIND BANDAGE OFF
cl-ast: No more bare ExprKind: every Expr has a Span cl-interpret: Give errors a span cl-repl: Print eval errors in load_file, instead of returning them. These changes are relevant.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
|
||||
use cl_ast::ExprKind;
|
||||
use cl_ast::Expr;
|
||||
use cl_lexer::error::{Error as LexError, Reason};
|
||||
use std::fmt::Display;
|
||||
pub type PResult<T> = Result<T, Error>;
|
||||
@@ -30,7 +30,7 @@ pub enum ErrorKind {
|
||||
ExpectedParsing {
|
||||
want: Parsing,
|
||||
},
|
||||
InvalidPattern(Box<ExprKind>),
|
||||
InvalidPattern(Box<Expr>),
|
||||
/// Indicates unfinished code
|
||||
Todo(&'static str),
|
||||
}
|
||||
@@ -135,7 +135,7 @@ impl Display for Error {
|
||||
ErrorKind::Todo(_) => write!(f, "{loc} {reason} {while_parsing:?}"),
|
||||
// lexical errors print their own higher-resolution loc info
|
||||
ErrorKind::Lexical(e) => write!(f, "{e} (while parsing {while_parsing})"),
|
||||
_ => write!(f, "{loc} {reason} while parsing {while_parsing}"),
|
||||
_ => write!(f, "{loc}: {reason} while parsing {while_parsing}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,26 +888,15 @@ impl Parse<'_> for StmtKind {
|
||||
|
||||
impl Parse<'_> for Expr {
|
||||
/// Parses an [Expr]
|
||||
///
|
||||
/// See also: [ExprKind::parse]
|
||||
fn parse(p: &mut Parser) -> PResult<Expr> {
|
||||
let start = p.loc();
|
||||
Ok(Expr { kind: ExprKind::parse(p)?, extents: Span(start, p.loc()) })
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse<'_> for ExprKind {
|
||||
/// Parses an [ExprKind] at the lowest precedence level
|
||||
// Implementer's note: Do not call this from within [prec::exprkind]
|
||||
fn parse(p: &mut Parser<'_>) -> PResult<ExprKind> {
|
||||
prec::exprkind(p, 0)
|
||||
prec::expr(p, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse<'_> for Quote {
|
||||
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
|
||||
let quote = delim(
|
||||
ExprKind::parse,
|
||||
Expr::parse,
|
||||
(TokenKind::Grave, TokenKind::Grave),
|
||||
Parsing::ExprKind,
|
||||
)(p)?
|
||||
@@ -981,16 +970,20 @@ impl Parse<'_> for AddrOf {
|
||||
match p.peek_kind(P)? {
|
||||
TokenKind::Amp => {
|
||||
p.consume_peeked();
|
||||
Ok(AddrOf { mutable: Mutability::parse(p)?, expr: ExprKind::parse(p)?.into() })
|
||||
Ok(AddrOf { mutable: Mutability::parse(p)?, expr: Expr::parse(p)?.into() })
|
||||
}
|
||||
TokenKind::AmpAmp => {
|
||||
let start = p.loc();
|
||||
p.consume_peeked();
|
||||
Ok(AddrOf {
|
||||
mutable: Mutability::Not,
|
||||
expr: ExprKind::AddrOf(AddrOf {
|
||||
mutable: Mutability::parse(p)?,
|
||||
expr: ExprKind::parse(p)?.into(),
|
||||
})
|
||||
expr: Expr {
|
||||
kind: ExprKind::AddrOf(AddrOf {
|
||||
mutable: Mutability::parse(p)?,
|
||||
expr: Expr::parse(p)?.into(),
|
||||
}),
|
||||
extents: Span(start, p.loc()),
|
||||
}
|
||||
.into(),
|
||||
})
|
||||
}
|
||||
@@ -1009,9 +1002,7 @@ impl Parse<'_> for Block {
|
||||
|
||||
/// Conditions (which precede curly-braced blocks) get special treatment
|
||||
fn condition(p: &mut Parser) -> PResult<Expr> {
|
||||
let start = p.loc();
|
||||
let kind = prec::exprkind(p, prec::Precedence::Condition.level())?;
|
||||
Ok(Expr { kind, extents: Span(start, p.loc()) })
|
||||
prec::expr(p, prec::Precedence::Condition.level())
|
||||
}
|
||||
|
||||
impl Parse<'_> for While {
|
||||
@@ -1088,7 +1079,7 @@ impl Parse<'_> for Return {
|
||||
|
||||
impl Parse<'_> for Pattern {
|
||||
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
|
||||
let value = prec::exprkind(p, prec::Precedence::Pattern.level())?;
|
||||
let value = prec::expr(p, prec::Precedence::Pattern.level())?;
|
||||
Pattern::try_from(value).map_err(|e| p.error(InvalidPattern(e.into()), Parsing::Pattern))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,36 +8,40 @@
|
||||
use super::{Parse, *};
|
||||
|
||||
/// Parses an [ExprKind]
|
||||
pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
|
||||
pub fn expr(p: &mut Parser, power: u8) -> PResult<Expr> {
|
||||
let parsing = Parsing::ExprKind;
|
||||
|
||||
let start = p.loc();
|
||||
// Prefix expressions
|
||||
let mut head = match p.peek_kind(Parsing::Unary)? {
|
||||
literal_like!() => Literal::parse(p)?.into(),
|
||||
path_like!() => exprkind_pathlike(p)?,
|
||||
TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(),
|
||||
TokenKind::Grave => Quote::parse(p)?.into(),
|
||||
TokenKind::LCurly => Block::parse(p)?.into(),
|
||||
TokenKind::LBrack => exprkind_arraylike(p)?,
|
||||
TokenKind::LParen => exprkind_tuplelike(p)?,
|
||||
TokenKind::Let => Let::parse(p)?.into(),
|
||||
TokenKind::Match => Match::parse(p)?.into(),
|
||||
TokenKind::While => ExprKind::While(While::parse(p)?),
|
||||
TokenKind::If => ExprKind::If(If::parse(p)?),
|
||||
TokenKind::For => ExprKind::For(For::parse(p)?),
|
||||
TokenKind::Break => ExprKind::Break(Break::parse(p)?),
|
||||
TokenKind::Return => ExprKind::Return(Return::parse(p)?),
|
||||
TokenKind::Continue => {
|
||||
p.consume_peeked();
|
||||
ExprKind::Continue
|
||||
}
|
||||
let mut head = Expr {
|
||||
kind: match p.peek_kind(Parsing::Unary)? {
|
||||
literal_like!() => Literal::parse(p)?.into(),
|
||||
path_like!() => exprkind_pathlike(p)?,
|
||||
TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(),
|
||||
TokenKind::Grave => Quote::parse(p)?.into(),
|
||||
TokenKind::LCurly => Block::parse(p)?.into(),
|
||||
TokenKind::LBrack => exprkind_arraylike(p)?,
|
||||
TokenKind::LParen => exprkind_tuplelike(p)?,
|
||||
TokenKind::Let => Let::parse(p)?.into(),
|
||||
TokenKind::Match => Match::parse(p)?.into(),
|
||||
TokenKind::While => ExprKind::While(While::parse(p)?),
|
||||
TokenKind::If => ExprKind::If(If::parse(p)?),
|
||||
TokenKind::For => ExprKind::For(For::parse(p)?),
|
||||
TokenKind::Break => ExprKind::Break(Break::parse(p)?),
|
||||
TokenKind::Return => ExprKind::Return(Return::parse(p)?),
|
||||
TokenKind::Continue => {
|
||||
p.consume_peeked();
|
||||
ExprKind::Continue
|
||||
}
|
||||
|
||||
op => {
|
||||
let (kind, prec) = from_prefix(op).ok_or_else(|| p.error(Unexpected(op), parsing))?;
|
||||
let ((), after) = prec.prefix().expect("should have a precedence");
|
||||
p.consume_peeked();
|
||||
Unary { kind, tail: exprkind(p, after)?.into() }.into()
|
||||
}
|
||||
op => {
|
||||
let (kind, prec) =
|
||||
from_prefix(op).ok_or_else(|| p.error(Unexpected(op), parsing))?;
|
||||
let ((), after) = prec.prefix().expect("should have a precedence");
|
||||
p.consume_peeked();
|
||||
Unary { kind, tail: expr(p, after)?.into() }.into()
|
||||
}
|
||||
},
|
||||
extents: Span(start, p.loc()),
|
||||
};
|
||||
|
||||
fn from_postfix(op: TokenKind) -> Option<Precedence> {
|
||||
@@ -58,36 +62,50 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
|
||||
break;
|
||||
}
|
||||
|
||||
head = match op {
|
||||
TokenKind::LBrack => {
|
||||
p.consume_peeked();
|
||||
let indices =
|
||||
sep(Expr::parse, TokenKind::Comma, TokenKind::RBrack, parsing)(p)?;
|
||||
p.match_type(TokenKind::RBrack, parsing)?;
|
||||
ExprKind::Index(Index { head: head.into(), indices })
|
||||
}
|
||||
TokenKind::LParen => {
|
||||
p.consume_peeked();
|
||||
let exprs = sep(Expr::parse, TokenKind::Comma, TokenKind::RParen, parsing)(p)?;
|
||||
p.match_type(TokenKind::RParen, parsing)?;
|
||||
Binary { kind: BinaryKind::Call, parts: (head, Tuple { exprs }.into()).into() }
|
||||
head = Expr {
|
||||
kind: match op {
|
||||
TokenKind::LBrack => {
|
||||
p.consume_peeked();
|
||||
let indices =
|
||||
sep(Expr::parse, TokenKind::Comma, TokenKind::RBrack, parsing)(p)?;
|
||||
p.match_type(TokenKind::RBrack, parsing)?;
|
||||
ExprKind::Index(Index { head: head.into(), indices })
|
||||
}
|
||||
TokenKind::LParen => {
|
||||
p.consume_peeked();
|
||||
let exprs =
|
||||
sep(Expr::parse, TokenKind::Comma, TokenKind::RParen, parsing)(p)?;
|
||||
p.match_type(TokenKind::RParen, parsing)?;
|
||||
Binary {
|
||||
kind: BinaryKind::Call,
|
||||
parts: (
|
||||
head,
|
||||
Expr {
|
||||
kind: Tuple { exprs }.into(),
|
||||
extents: Span(start, p.loc()),
|
||||
},
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
TokenKind::LCurly => match head {
|
||||
ExprKind::Path(path) => ExprKind::Structor(structor_body(p, path)?),
|
||||
_ => break,
|
||||
}
|
||||
TokenKind::LCurly => match head.kind {
|
||||
ExprKind::Path(path) => ExprKind::Structor(structor_body(p, path)?),
|
||||
_ => break,
|
||||
},
|
||||
TokenKind::Dot => {
|
||||
p.consume_peeked();
|
||||
let kind = MemberKind::parse(p)?;
|
||||
Member { head: Box::new(head), kind }.into()
|
||||
}
|
||||
TokenKind::As => {
|
||||
p.consume_peeked();
|
||||
let ty = Ty::parse(p)?;
|
||||
Cast { head: head.into(), ty }.into()
|
||||
}
|
||||
_ => Err(p.error(Unexpected(op), parsing))?,
|
||||
},
|
||||
TokenKind::Dot => {
|
||||
p.consume_peeked();
|
||||
let kind = MemberKind::parse(p)?;
|
||||
Member { head: Box::new(head), kind }.into()
|
||||
}
|
||||
TokenKind::As => {
|
||||
p.consume_peeked();
|
||||
let ty = Ty::parse(p)?;
|
||||
Cast { head: head.into(), ty }.into()
|
||||
}
|
||||
_ => Err(p.error(Unexpected(op), parsing))?,
|
||||
extents: Span(start, p.loc()),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
@@ -99,8 +117,11 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
|
||||
}
|
||||
p.consume_peeked();
|
||||
|
||||
let tail = exprkind(p, after)?;
|
||||
head = Binary { kind, parts: (head, tail).into() }.into();
|
||||
let tail = expr(p, after)?;
|
||||
head = Expr {
|
||||
kind: Binary { kind, parts: (head, tail).into() }.into(),
|
||||
extents: Span(start, p.loc()),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -111,8 +132,11 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
|
||||
}
|
||||
p.consume_peeked();
|
||||
|
||||
let tail = exprkind(p, after)?;
|
||||
head = Modify { kind, parts: (head, tail).into() }.into();
|
||||
let tail = expr(p, after)?;
|
||||
head = Expr {
|
||||
kind: Modify { kind, parts: (head, tail).into() }.into(),
|
||||
extents: Span(start, p.loc()),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -125,8 +149,12 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
|
||||
}
|
||||
p.consume_peeked();
|
||||
|
||||
let tail = exprkind(p, after)?;
|
||||
head = Assign { parts: (head, tail).into() }.into();
|
||||
let tail = expr(p, after)?;
|
||||
head = Expr {
|
||||
kind: Assign { parts: (head, tail).into() }.into(),
|
||||
extents: Span(start, p.loc()),
|
||||
};
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -138,7 +166,9 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
|
||||
p.consume_peeked();
|
||||
|
||||
let ty = Ty::parse(p)?;
|
||||
head = Cast { head: head.into(), ty }.into();
|
||||
head =
|
||||
Expr { kind: Cast { head: head.into(), ty }.into(), extents: Span(start, p.loc()) };
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -174,10 +204,10 @@ fn exprkind_array_rep(p: &mut Parser) -> PResult<ExprKind> {
|
||||
let first = Expr::parse(p)?;
|
||||
Ok(match p.peek_kind(P)? {
|
||||
TokenKind::Semi => ArrayRep {
|
||||
value: first.kind.into(),
|
||||
value: first.into(),
|
||||
repeat: {
|
||||
p.consume_peeked();
|
||||
Box::new(exprkind(p, 0)?)
|
||||
Box::new(expr(p, 0)?)
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
@@ -224,7 +254,7 @@ fn exprkind_group(p: &mut Parser) -> PResult<ExprKind> {
|
||||
}
|
||||
Ok(Tuple { exprs }.into())
|
||||
}
|
||||
_ => Ok(Group { expr: first.kind.into() }.into()),
|
||||
_ => Ok(Group { expr: first.into() }.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user