doughlang: Expressions in patterns
ast: - Document operators - Parameterize Pat with Annotation - Consolidate Path and Lit into "Value" (Expr) - Consolidate NamedRecord/Namedtuple into PatOp::TypePrefixed - Allow Pat<Pat,*> patterns - Additional helper functions on Expr and Pat lexer: - Support inner-doc comment syntax `//!` - Cleans up `///` or `//!` prefix parser: - Make Parse::Prec `Default` - Allow expression elision after `..`/`..=` - Fix Parser::consume not updating elide_do state - Add token splitting, to make `&&Expr` and `&&Pat` easier - error: Embed Pat precedence in ParseError
This commit is contained in:
225
src/ast.rs
225
src/ast.rs
@@ -65,78 +65,137 @@ pub enum Expr<A: Annotation = Span> {
|
||||
/// - Traditional binary and unary operators (add, sub, neg, assign)
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Op {
|
||||
// -- true operators
|
||||
Do, // Expr ; Expr
|
||||
As, // Expr as Expr
|
||||
Macro, // macro { (Pat => Expr)* }
|
||||
Block, // { Expr }
|
||||
Array, // [ Expr,* ]
|
||||
ArRep, // [ Expr ; Expr ]
|
||||
Group, // ( Expr ,?)
|
||||
Tuple, // Expr (, Expr)*
|
||||
Meta, // #[ Expr ]
|
||||
/// `Expr (; Expr)*`
|
||||
Do,
|
||||
/// `Expr as Expr`
|
||||
As,
|
||||
/// `macro { (Pat => Expr)* }`
|
||||
Macro,
|
||||
/// `{ Expr }`
|
||||
Block,
|
||||
/// `[ Expr,* ]`
|
||||
Array,
|
||||
/// `[ Expr ; Expr ]`
|
||||
ArRep,
|
||||
/// `( Expr )`
|
||||
Group,
|
||||
/// `Expr (, Expr)*`
|
||||
Tuple,
|
||||
/// `#[ Expr ]`
|
||||
Meta,
|
||||
|
||||
Try, // Expr '?'
|
||||
Index, // Expr [ Expr,* ]
|
||||
Call, // Expr ( Expr,* )
|
||||
/// `Expr '?'`
|
||||
Try,
|
||||
/// `Expr [ Expr,* ]`
|
||||
Index,
|
||||
/// `Expr ( Expr,* )`
|
||||
Call,
|
||||
|
||||
Pub, // pub Expr
|
||||
Const, // const Expr
|
||||
Static, // static Expr
|
||||
Loop, // loop Expr
|
||||
Match, // match Expr { <Bind(Match, ..)>,* }
|
||||
If, // if Expr Expr (else Expr)?
|
||||
While, // while Expr Expr (else Expr)?
|
||||
Break, // break Expr
|
||||
Return, // return Expr
|
||||
Continue, // continue
|
||||
/// `pub Expr`
|
||||
Pub,
|
||||
/// `const Expr`
|
||||
Const,
|
||||
/// `static Expr`
|
||||
Static,
|
||||
/// `loop Expr`
|
||||
Loop,
|
||||
/// `match Expr { <Bind(Match, ..)>,* }`
|
||||
Match,
|
||||
/// `if Expr Expr (else Expr)?`
|
||||
If,
|
||||
/// `while Expr Expr (else Expr)?`
|
||||
While,
|
||||
/// `break Expr`
|
||||
Break,
|
||||
/// `return Expr`
|
||||
Return,
|
||||
/// `continue`
|
||||
Continue,
|
||||
|
||||
Dot, // Expr . Expr
|
||||
/// `Expr . Expr`
|
||||
Dot,
|
||||
|
||||
RangeEx, // Expr? ..Expr
|
||||
RangeIn, // Expr? ..=Expr
|
||||
Neg, // -Expr
|
||||
Not, // !Expr
|
||||
Identity, // !!Expr
|
||||
Refer, // &Expr
|
||||
Deref, // *Expr
|
||||
/// `Expr? ..Expr`
|
||||
RangeEx,
|
||||
/// `Expr? ..=Expr`
|
||||
RangeIn,
|
||||
/// `-Expr`
|
||||
Neg,
|
||||
/// `!Expr`
|
||||
Not,
|
||||
/// `!!Expr`
|
||||
Identity,
|
||||
/// `&Expr`
|
||||
Refer,
|
||||
/// `*Expr`
|
||||
Deref,
|
||||
|
||||
Mul, // Expr * Expr
|
||||
Div, // Expr / Expr
|
||||
Rem, // Expr % Expr
|
||||
/// `Expr * Expr`
|
||||
Mul,
|
||||
/// `Expr / Expr`
|
||||
Div,
|
||||
/// `Expr % Expr`
|
||||
Rem,
|
||||
|
||||
Add, // Expr + Expr
|
||||
Sub, // Expr - Expr
|
||||
/// `Expr + Expr`
|
||||
Add,
|
||||
/// `Expr - Expr`
|
||||
Sub,
|
||||
|
||||
Shl, // Expr << Expr
|
||||
Shr, // Expr >> Expr
|
||||
/// `Expr << Expr`
|
||||
Shl,
|
||||
/// `Expr >> Expr`
|
||||
Shr,
|
||||
|
||||
And, // Expr & Expr
|
||||
Xor, // Expr ^ Expr
|
||||
Or, // Expr | Expr
|
||||
/// `Expr & Expr`
|
||||
And,
|
||||
/// `Expr ^ Expr`
|
||||
Xor,
|
||||
/// `Expr | Expr`
|
||||
Or,
|
||||
|
||||
Lt, // Expr < Expr
|
||||
Leq, // Expr <= Expr
|
||||
Eq, // Expr == Expr
|
||||
Neq, // Expr != Expr
|
||||
Geq, // Expr >= Expr
|
||||
Gt, // Expr > Expr
|
||||
/// `Expr < Expr`
|
||||
Lt,
|
||||
/// `Expr <= Expr`
|
||||
Leq,
|
||||
/// `Expr == Expr`
|
||||
Eq,
|
||||
/// `Expr != Expr`
|
||||
Neq,
|
||||
/// `Expr >= Expr`
|
||||
Geq,
|
||||
/// `Expr > Expr`
|
||||
Gt,
|
||||
|
||||
LogAnd, // Expr && Expr
|
||||
LogXor, // Expr ^^ Expr
|
||||
LogOr, // Expr || Expr
|
||||
/// `Expr && Expr`
|
||||
LogAnd,
|
||||
/// `Expr ^^ Expr`
|
||||
LogXor,
|
||||
/// `Expr || Expr`
|
||||
LogOr,
|
||||
|
||||
Set, // Expr = Expr
|
||||
MulSet, // Expr *= Expr
|
||||
DivSet, // Expr /= Expr
|
||||
RemSet, // Expr %= Expr
|
||||
AddSet, // Expr += Expr
|
||||
SubSet, // Expr -= Expr
|
||||
ShlSet, // Expr <<= Expr
|
||||
ShrSet, // Expr >>= Expr
|
||||
AndSet, // Expr &= Expr
|
||||
XorSet, // Expr ^= Expr
|
||||
OrSet, // Expr |= Expr
|
||||
/// `Expr = Expr`
|
||||
Set,
|
||||
/// `Expr *= Expr`
|
||||
MulSet,
|
||||
/// `Expr /= Expr`
|
||||
DivSet,
|
||||
/// `Expr %= Expr`
|
||||
RemSet,
|
||||
/// `Expr += Expr`
|
||||
AddSet,
|
||||
/// `Expr -= Expr`
|
||||
SubSet,
|
||||
/// `Expr <<= Expr`
|
||||
ShlSet,
|
||||
/// `Expr >>= Expr`
|
||||
ShrSet,
|
||||
/// `Expr &= Expr`
|
||||
AndSet,
|
||||
/// `Expr ^= Expr`
|
||||
XorSet,
|
||||
/// `Expr |= Expr`
|
||||
OrSet,
|
||||
}
|
||||
|
||||
/// A qualified identifier
|
||||
@@ -181,11 +240,11 @@ pub enum Use {
|
||||
/// ```ignore
|
||||
/// let Pat (= Expr (else Expr)?)?
|
||||
/// type Pat (= Expr)?
|
||||
/// struct Pat
|
||||
/// enum Pat
|
||||
/// fn Pat Expr
|
||||
/// mod Pat Expr
|
||||
/// impl Pat Expr
|
||||
/// struct Pat
|
||||
/// enum Pat
|
||||
/// for Pat in Expr Expr (else Expr)?
|
||||
/// Pat => Expr // in match
|
||||
/// ```
|
||||
@@ -193,7 +252,7 @@ pub enum Use {
|
||||
pub struct Bind<A: Annotation = Span>(
|
||||
pub BindOp,
|
||||
pub Vec<Path>,
|
||||
pub Pat,
|
||||
pub Pat<A>,
|
||||
pub Vec<Anno<Expr<A>, A>>,
|
||||
);
|
||||
|
||||
@@ -237,7 +296,7 @@ pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>
|
||||
///
|
||||
/// This covers both patterns in Match expressions, and type annotations.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Pat {
|
||||
pub enum Pat<A: Annotation = Span> {
|
||||
/// Matches anything without binding
|
||||
Ignore,
|
||||
/// Matches nothing, ever
|
||||
@@ -246,16 +305,10 @@ pub enum Pat {
|
||||
MetId(String),
|
||||
/// Matches anything, and binds it to a name
|
||||
Name(String),
|
||||
/// Matches against a named const value
|
||||
Path(Path),
|
||||
/// Matches a Struct Expression `Ident { Pat }`
|
||||
NamedRecord(Path, Box<Pat>),
|
||||
/// Matches a Tuple Struct Expression `Ident ( Pat )`
|
||||
NamedTuple(Path, Box<Pat>),
|
||||
/// Matches a literal value by equality comparison
|
||||
Lit(Literal),
|
||||
/// Matches a value by equality comparison
|
||||
Value(Box<Anno<Expr<A>, A>>),
|
||||
/// Matches a compound pattern
|
||||
Op(PatOp, Vec<Pat>),
|
||||
Op(PatOp, Vec<Pat<A>>),
|
||||
}
|
||||
|
||||
/// Operators on lists of patterns
|
||||
@@ -285,6 +338,10 @@ pub enum PatOp {
|
||||
ArRep,
|
||||
/// Matches a type annotation or struct member
|
||||
Typed,
|
||||
/// Matches a prefix-type-annotated structure
|
||||
TypePrefixed,
|
||||
/// Matches a generic specialization annotation
|
||||
Generic,
|
||||
/// Changes the binding mode to "function-body"
|
||||
Fn,
|
||||
/// Matches one of a list of alternatives
|
||||
@@ -321,6 +378,13 @@ impl<A: Annotation> Expr<A> {
|
||||
Self::Op(Op::Do, exprs)
|
||||
}
|
||||
|
||||
pub fn to_tuple(self, annotation: A) -> Self {
|
||||
match self {
|
||||
Self::Op(Op::Tuple, _) => self,
|
||||
_ => Self::Op(Op::Tuple, vec![self.anno(annotation)]),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn is_place(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
@@ -328,6 +392,10 @@ impl<A: Annotation> Expr<A> {
|
||||
)
|
||||
}
|
||||
|
||||
pub const fn is_value(&self) -> bool {
|
||||
!self.is_place()
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub const fn as_slice(&self) -> Option<(Op, &[Anno<Expr<A>, A>])> {
|
||||
match self {
|
||||
@@ -337,6 +405,15 @@ impl<A: Annotation> Expr<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Pat<A> {
|
||||
pub fn to_tuple(self) -> Self {
|
||||
match self {
|
||||
Self::Op(PatOp::Tuple, _) => self,
|
||||
_ => Self::Op(PatOp::Tuple, vec![self]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Path {
|
||||
fn from(value: &str) -> Self {
|
||||
Self { parts: vec![value.to_owned()] }
|
||||
|
||||
Reference in New Issue
Block a user