Conlang v0.0.5: Pratternization

cl-token:
- Minimize data redundancy by consolidating TokenKind::Literal; TokenData::{String, Identifier}
- Rename Op to Punct

cl-ast:
- Remove ExprKind::{Member, Call} in favor of making them
'binary' operators
- Consolidate boxes (TODO: consolidate more boxes)
- Remove repetition vecs in favor of boxes (this may come with performance tradeoffs!)

cl-lexer:
- Reflect changes from cl-token

cl-interpret, cl-repl/src/examples:
- Reflect changes from cl-ast

cl-parser:
- Switch to Pratt parsing for expressions
  - TODO: Code cleanup
  - TODO: Use total ordering for Precedence instead of binding powers (that's what the binding powers are there for anyway)
- Switch functional parsers to take Punct instead of TokenKind
  - It's not like we need a `for`-separated list
- Remove `binary` macro. No longer needed with precedence climbing.
- Repurpose `operator` macro to produce both the operator and the respective Precedence
- Remove several of the smaller parser functions, since they've been consolidated into the larger `exprkind`
This commit is contained in:
2024-04-13 03:33:26 -05:00
parent 2c36ccc0cf
commit fc3cbbf450
11 changed files with 636 additions and 778 deletions

View File

@@ -5,7 +5,10 @@ mod display {
//! Implements [Display] for [AST](super::super) Types
use super::*;
pub use delimiters::*;
use std::fmt::{Display, Write};
use std::{
borrow::Borrow,
fmt::{Display, Write},
};
mod delimiters {
#![allow(dead_code)]
#[derive(Clone, Copy, Debug)]
@@ -307,13 +310,16 @@ mod display {
impl Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.kind {
self.kind.fmt(f)
}
}
impl Display for ExprKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ExprKind::Assign(v) => v.fmt(f),
ExprKind::Binary(v) => v.fmt(f),
ExprKind::Unary(v) => v.fmt(f),
ExprKind::Index(v) => v.fmt(f),
ExprKind::Call(v) => v.fmt(f),
ExprKind::Member(v) => v.fmt(f),
ExprKind::Path(v) => v.fmt(f),
ExprKind::Literal(v) => v.fmt(f),
ExprKind::Array(v) => v.fmt(f),
@@ -334,8 +340,8 @@ mod display {
}
impl Display for Assign {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { head, op, tail } = self;
write!(f, "{head} {op} {tail}")
let Self { kind, parts } = self;
write!(f, "{} {kind} {}", parts.0, parts.1)
}
}
impl Display for AssignKind {
@@ -358,12 +364,13 @@ mod display {
}
impl Display for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { head, tail } = self;
write!(f, "{head}")?;
for (kind, expr) in tail {
write!(f, " {kind} {expr}")?;
let Self { kind, parts } = self;
let (head, tail) = parts.borrow();
match kind {
BinaryKind::Dot => write!(f, "{head}{kind}{tail}"),
BinaryKind::Call => write!(f, "{head}{tail}"),
_ => write!(f, "{head} {kind} {tail}"),
}
Ok(())
}
}
impl Display for BinaryKind {
@@ -391,17 +398,15 @@ mod display {
BinaryKind::Div => "/",
BinaryKind::Rem => "%",
BinaryKind::Dot => ".",
BinaryKind::Call => "()",
}
.fmt(f)
}
}
impl Display for Unary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { ops: kinds, tail } = self;
for kind in kinds {
kind.fmt(f)?
}
tail.fmt(f)
let Self { kind, tail } = self;
write!(f, "{kind}{tail}")
}
}
impl Display for UnaryKind {
@@ -416,29 +421,11 @@ mod display {
.fmt(f)
}
}
impl Display for Call {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { callee, args } = self;
callee.fmt(f)?;
for args in args {
args.fmt(f)?;
}
Ok(())
}
}
impl Display for Tuple {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
delimit(separate(&self.exprs, ", "), INLINE_PARENS)(f)
}
}
impl Display for Member {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { head: parent, tail: children } = self;
write!(f, "{parent}.")?;
separate(children, ".")(f)?;
Ok(())
}
}
impl Display for Index {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { head, indices } = self;
@@ -449,11 +436,6 @@ mod display {
Ok(())
}
}
impl Display for Indices {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
delimit(separate(&self.exprs, ", "), INLINE_SQUARE)(f)
}
}
impl Display for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { absolute, parts } = self;
@@ -624,8 +606,6 @@ mod convert {
Assign => ExprKind::Assign,
Binary => ExprKind::Binary,
Unary => ExprKind::Unary,
Call => ExprKind::Call,
Member => ExprKind::Member,
Index => ExprKind::Index,
Path => ExprKind::Path,
Literal => ExprKind::Literal,
@@ -646,18 +626,7 @@ mod convert {
bool => Literal::Bool,
char => Literal::Char,
u128 => Literal::Int,
&str => Literal::String,
}
}
impl From<Tuple> for Indices {
fn from(value: Tuple) -> Self {
Self { exprs: value.exprs }
}
}
impl From<Indices> for Tuple {
fn from(value: Indices) -> Self {
Self { exprs: value.exprs }
String => Literal::String,
}
}

View File

@@ -324,10 +324,6 @@ pub enum ExprKind {
Binary(Binary),
/// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
Unary(Unary),
/// A [Member] access expression: [`Expr`] (`.` [`Expr`])+
Member(Member),
/// A [Call] expression, with arguments: a(foo, bar)
Call(Call),
/// An Array [Index] expression: a[10, 20, 30]
Index(Index),
/// A [path expression](Path): `::`? [PathPart] (`::` [PathPart])*
@@ -366,9 +362,8 @@ pub enum ExprKind {
/// An [Assign]ment expression: [`Expr`] ([`AssignKind`] [`Expr`])\+
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Assign {
pub head: Box<Expr>,
pub op: AssignKind,
pub tail: Box<Expr>,
pub kind: AssignKind,
pub parts: Box<(ExprKind, ExprKind)>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -390,8 +385,8 @@ pub enum AssignKind {
/// A [Binary] expression: [`Expr`] ([`BinaryKind`] [`Expr`])\+
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Binary {
pub head: Box<Expr>,
pub tail: Vec<(BinaryKind, Expr)>,
pub kind: BinaryKind,
pub parts: Box<(ExprKind, ExprKind)>,
}
/// A [Binary] operator
@@ -419,17 +414,18 @@ pub enum BinaryKind {
Div,
Rem,
Dot,
Call,
}
/// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Unary {
pub ops: Vec<UnaryKind>,
pub tail: Box<Expr>,
pub kind: UnaryKind,
pub tail: Box<ExprKind>,
}
/// A [Unary] operator
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UnaryKind {
Deref,
Neg,
@@ -439,32 +435,11 @@ pub enum UnaryKind {
/// Unused
Tilde,
}
/// A [Member] access expression: [`Expr`] (`.` [`Expr`])+
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Member {
pub head: Box<Expr>,
pub tail: Vec<Expr>,
}
/// A [Call] expression, with arguments: a(foo, bar)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Call {
pub callee: Box<Expr>,
pub args: Vec<Tuple>,
}
/// A repeated [Index] expression: a[10, 20, 30][40, 50, 60]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Index {
pub head: Box<Expr>,
pub indices: Vec<Indices>,
}
/// A single [Index] expression: a[10, 20, 30]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Indices {
pub exprs: Vec<Expr>,
pub head: Box<ExprKind>,
pub indices: Vec<Expr>,
}
/// A [Literal]: 0x42, 1e123, 2.4, "Hello"
@@ -486,8 +461,8 @@ pub struct Array {
/// `[` [Expr] `;` [Literal] `]`
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ArrayRep {
pub value: Box<Expr>,
pub repeat: Box<Expr>,
pub value: Box<ExprKind>,
pub repeat: Box<ExprKind>,
}
/// An address-of expression: `&` `mut`? [`Expr`]
@@ -495,7 +470,7 @@ pub struct ArrayRep {
pub struct AddrOf {
pub count: usize,
pub mutable: Mutability,
pub expr: Box<Expr>,
pub expr: Box<ExprKind>,
}
/// A [Block] expression: `{` [`Stmt`]\* [`Expr`]? `}`
@@ -507,7 +482,7 @@ pub struct Block {
/// A [Grouping](Group) expression `(` [`Expr`] `)`
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Group {
pub expr: Box<Expr>,
pub expr: Box<ExprKind>,
}
/// A [Tuple] expression: `(` [`Expr`] (`,` [`Expr`])+ `)`