use crate::leaf::*;
use crate::span::Span;
use newer_type::implement;
use syan::parse::{Parse, Unparse};
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct File {
pub headers: Vec<Header>,
pub prelude: Vec<TopBinding>,
pub in_kw: Option<KwIn>,
pub body: Option<ast::Expr>,
pub eoi: EoiTok,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum Header {
Require(HeaderRequireTok),
Import(HeaderImportTok),
Stage(HeaderStageTok),
}
#[derive(Debug, Clone, PartialEq)]
pub struct BindName {
pub name: String,
pub span: Span,
repr: BindNameRepr,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
enum BindNameRepr {
Op(OpNameTok),
Var(VarTok),
}
impl Parse<crate::token::Atom> for BindName {
type Error = syan::error::ParseError<crate::span::Span>;
fn parse_stream<S: syan::parse::ParseStream<Atom = crate::token::Atom>>(
stream: &mut S,
) -> Result<Self, Self::Error> {
let repr = BindNameRepr::parse_stream(stream)?;
let (name, span) = match &repr {
BindNameRepr::Op(op) => (op.name.clone(), op.span),
BindNameRepr::Var(v) => (v.name.clone(), v.span),
};
Ok(BindName { name, span, repr })
}
}
impl Unparse<crate::token::Atom> for BindName {
fn unparse<S: syan::parse::unparse::Emitter<crate::token::Atom>>(
&self,
sink: &mut S,
) -> Result<(), S::Error> {
self.repr.unparse(sink)
}
}
impl From<VarTok> for BindName {
fn from(v: VarTok) -> BindName {
BindName {
name: v.name.clone(),
span: v.span,
repr: BindNameRepr::Var(v),
}
}
}
#[cfg(test)]
mod bind_name_tests {
use super::*;
#[test]
fn from_var_tok_preserves_name_and_span() {
let v = VarTok {
name: "foo".to_string(),
span: Span::default(),
};
let bn: BindName = v.clone().into();
assert_eq!(bn.name, v.name);
assert_eq!(bn.span, v.span);
}
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TopLet {
pub let_kw: KwLet,
pub stage: Option<TopStage>,
pub name: BindName,
pub ascription: Option<ast::RecAscription>,
pub leading_bar: Option<BarTok>,
pub params: Vec<ast::Param>,
pub eq: DefEqTok,
pub value: ast::Expr,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TopStage {
pub persistent: Option<KwPersistent>,
pub tilde: ExactTildeTok,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum TopBinding {
LetRec {
kw: KwLetRec,
stage: Option<TopStage>,
first: ast::RecBinding,
ands: Vec<ast::AndBinding>,
},
Let(TopLet),
LetPattern {
let_kw: KwLet,
pat: PatErased,
eq: DefEqTok,
value: ast::Expr,
},
LetInline {
kw: KwLetHorz,
stage: Option<TopStage>,
ctx: Option<VarTok>,
cmd: HorzCmdTok,
params: Vec<ast::Param>,
eq: DefEqTok,
value: ast::Expr,
},
LetBlock {
kw: KwLetVert,
stage: Option<TopStage>,
ctx: Option<VarTok>,
cmd: VertCmdTok,
params: Vec<ast::Param>,
eq: DefEqTok,
value: ast::Expr,
},
LetMath {
kw: KwLetMath,
stage: Option<TopStage>,
cmd: HorzCmdTok,
params: Vec<ast::Param>,
eq: DefEqTok,
value: ast::Expr,
},
Type(TypeDecl),
LetMutable {
kw: KwLetMutable,
stage: Option<TopStage>,
name: VarTok,
arrow: OverwriteEqTok,
value: ast::Expr,
},
Module {
kw: KwModule,
name: CtorTok,
sig: Option<SigAnnot>,
eq: DefEqTok,
struct_kw: KwStruct,
decls: Vec<StructDecl>,
end_kw: KwEnd,
},
Open { kw: KwOpen, name: CtorTok },
}
#[derive(Debug, Clone, PartialEq)]
pub struct StructDecl(pub Box<TopBinding>);
impl Parse<crate::token::Atom> for StructDecl {
type Error = syan::error::ParseError<crate::span::Span>;
fn parse_stream<S: syan::parse::ParseStream<Atom = crate::token::Atom>>(
stream: &mut S,
) -> Result<Self, Self::Error> {
let value = <TopBinding as Parse<_>>::parse_stream(stream)?;
Ok(StructDecl(Box::new(value)))
}
}
impl Unparse<crate::token::Atom> for StructDecl {
fn unparse<S: syan::parse::unparse::Emitter<crate::token::Atom>>(
&self,
sink: &mut S,
) -> Result<(), S::Error> {
self.0.unparse(sink)
}
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct SigAnnot {
pub colon: ColonTok,
pub sig_kw: KwSig,
pub items: Vec<SigItem>,
pub end_kw: KwEnd,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum SigItem {
ValHorzCmd {
kw: KwVal,
name: HorzCmdTok,
colon: ColonTok,
ty: ast::TypeExpr,
constraints: Vec<SigConstraint>,
},
ValVertCmd {
kw: KwVal,
name: VertCmdTok,
colon: ColonTok,
ty: ast::TypeExpr,
constraints: Vec<SigConstraint>,
},
Val {
kw: KwVal,
name: BindName,
colon: ColonTok,
ty: ast::TypeExpr,
constraints: Vec<SigConstraint>,
},
DirectHorzCmd {
kw: KwDirect,
name: HorzCmdTok,
colon: ColonTok,
ty: ast::TypeExpr,
constraints: Vec<SigConstraint>,
},
DirectVertCmd {
kw: KwDirect,
name: VertCmdTok,
colon: ColonTok,
ty: ast::TypeExpr,
constraints: Vec<SigConstraint>,
},
Type {
kw: KwType,
tyvars: Vec<TypeVarTok>,
name: VarTok,
constraints: Vec<SigConstraint>,
},
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct SigConstraint {
pub kw: ConstraintTok,
pub tyvar: TypeVarTok,
pub cons: ConsTok,
pub kind: RecordKind,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct RecordKind {
pub rec: RecordGroup<()>,
#[group(self.rec)]
pub fields: Vec<RecordKindField>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct RecordKindField {
pub name: VarTok,
pub colon: ColonTok,
pub ty: ast::TypeExpr,
pub semi: Option<ListPunctTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TypeDecl {
pub kw: KwType,
pub tyvars: Vec<TypeVarTok>,
pub name: VarTok,
pub eq: DefEqTok,
pub body: TypeDeclBody,
pub ands: Vec<AndTypeClause>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct AndTypeClause {
pub and_kw: KwAnd,
pub tyvars: Vec<TypeVarTok>,
pub name: VarTok,
pub eq: DefEqTok,
pub body: TypeDeclBody,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum TypeDeclBody {
Variant {
leading_bar: Option<BarTok>,
first: VariantDef,
rest: Vec<BarVariantDef>,
},
Synonym(ast::TypeExpr),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct VariantDef {
pub ctor: CtorTok,
pub of_ty: Option<OfType>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct OfType {
pub of_kw: KwOf,
pub ty: ast::TypeExpr,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct BarVariantDef {
pub bar: BarTok,
pub def: VariantDef,
}
macro_rules! erased_leaf {
($($(#[$doc:meta])* $name:ident => $target:ty;)*) => {
$(
$(#[$doc])*
#[implement(newer_type_std::ops::Deref)]
#[derive(Debug, Clone, PartialEq)]
pub struct $name(pub Box<$target>);
impl Parse<crate::token::Atom> for $name {
type Error = syan::error::ParseError<crate::span::Span>;
fn parse_stream<S: syan::parse::ParseStream<Atom = crate::token::Atom>>(
stream: &mut S,
) -> Result<Self, Self::Error> {
let value = <$target as Parse<_>>::parse_stream(stream)?;
Ok($name(Box::new(value)))
}
}
impl Unparse<crate::token::Atom> for $name {
fn unparse<S: syan::parse::unparse::Emitter<crate::token::Atom>>(
&self,
sink: &mut S,
) -> Result<(), S::Error> {
self.0.unparse(sink)
}
}
)*
};
}
erased_leaf! {
ExprErased => ast::Expr;
PatErased => ast::Pattern;
PatBotErased => ast::PatBot;
TyErased => ast::TypeExpr;
MathErased => ast::MathElemCst;
AppArgErased => ast::AppArg;
}
#[syan::parse::recurse]
pub mod ast {
use super::super::leaf::*;
use syan::parse::{Parse, Unparse};
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum Expr {
LetRecIn {
kw: KwLetRec,
first: RecBinding,
ands: Vec<AndBinding>,
in_kw: KwIn,
body: Box<Expr>,
},
LetIn {
kw: KwLet,
name: super::BindName,
ascription: Option<RecAscription>,
leading_bar: Option<BarTok>,
params: Vec<Param>,
eq: DefEqTok,
value: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
LetPatternIn {
kw: KwLet,
pat: super::PatErased,
eq: DefEqTok,
value: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
If {
kw: KwIf,
cond: Box<Expr>,
then_kw: KwThen,
then_branch: Box<Expr>,
else_kw: KwElse,
else_branch: Box<Expr>,
},
Fun {
kw: KwFun,
params: Vec<PatBot>,
arrow: ArrowTok,
body: Box<Expr>,
},
FunRows {
kw: KwFun,
opts: CstOptBinders,
param: PatBot,
arrow: ArrowTok,
body: Box<Expr>,
},
Match {
kw: KwMatch,
scrutinee: Box<Expr>,
with_kw: KwWith,
leading_bar: Option<BarTok>,
first: MatchArm,
rest: Vec<BarArm>,
},
LetMutableIn {
kw: KwLetMutable,
name: VarTok,
arrow: OverwriteEqTok,
init: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
LetMathIn {
kw: KwLetMath,
cmd: HorzCmdTok,
params: Vec<Param>,
eq: DefEqTok,
value: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
OpenIn {
kw: KwOpen,
name: CtorTok,
in_kw: KwIn,
body: Box<Expr>,
},
WhileDo {
kw: KwWhile,
cond: Box<Expr>,
do_kw: KwDo,
body: Box<Expr>,
},
Overwrite {
name: VarTok,
arrow: OverwriteEqTok,
value: super::ExprErased,
},
Ops(OpChain),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct RecBinding {
pub name: super::BindName,
pub ascription: Option<RecAscription>,
pub leading_bar: Option<BarTok>,
pub params: Vec<PatBot>,
pub eq: DefEqTok,
pub value: super::ExprErased,
pub extra: Vec<RecClause>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct RecAscription {
pub colon: ColonTok,
pub ty: TypeExpr,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct RecClause {
pub bar: BarTok,
pub params: Vec<PatBot>,
pub eq: DefEqTok,
pub value: super::ExprErased,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct AndBinding {
pub and_kw: KwAnd,
pub binding: RecBinding,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct MatchArm {
pub pat: super::PatErased,
pub guard: Option<Guard>,
pub arrow: ArrowTok,
pub body: super::ExprErased,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct Guard {
pub when_kw: KwWhen,
pub cond: super::ExprErased,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct BarArm {
pub bar: BarTok,
pub arm: MatchArm,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct OpChain {
pub head: AppExpr,
pub tail: Vec<OpRhs>,
pub before: Option<BeforeTail>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct BeforeTail {
pub kw: KwBefore,
pub body: super::ExprErased,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct OpRhs {
pub op: BinOpTok,
pub rhs: AppExpr,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct AppExpr {
pub minus: Option<ExactMinusTok>,
pub stage: Option<StagePrefix>,
pub excl: Option<UnopExclamTok>,
pub head: Atomic,
pub head_accesses: Vec<AccessSeg>,
pub args: Vec<AppArg>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum StagePrefix {
Next(ExactAmpTok),
Prev(ExactTildeTok),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct AccessSeg {
pub hash: AccessTok,
pub label: VarTok,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum AppArg {
Optional { q: OptionalTok, value: Atomic },
Omission(OmissionTok),
Atom {
stage: Option<StagePrefix>,
excl: Option<UnopExclamTok>,
atom: Atomic,
accesses: Vec<AccessSeg>,
},
Ctor(CtorTok),
Bundled {
opts: CstOptArgs,
excl: Option<UnopExclamTok>,
atom: Atomic,
accesses: Vec<AccessSeg>,
},
BundledCtor { opts: CstOptArgs, ctor: CtorTok },
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstOptBinders {
pub q: OptionalTypeTok,
pub paren: ParenGroup<()>,
#[group(self.paren)]
pub entries: Vec<CstOptBinderEntry>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstOptBinderEntry {
pub label: VarTok,
pub eq: DefEqTok,
pub var: VarTok,
pub comma: Option<CommaTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstOptArgs {
pub q: OptionalTypeTok,
pub paren: ParenGroup<()>,
#[group(self.paren)]
pub entries: Vec<CstOptArgEntry>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstOptArgEntry {
pub label: VarTok,
pub eq: DefEqTok,
pub value: super::ExprErased,
pub comma: Option<CommaTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum Atomic {
Length(LengthTok),
Float(FloatTok),
Int(IntTok),
Literal(LiteralTok),
True(KwTrue),
False(KwFalse),
Ctor(CtorTok),
Var(VarTok),
VarWithMod(VarWithModTok),
OpRef(OpNameTok),
Command { kw: CommandTok, name: AnyHorzCmdTok },
Unit { paren: UnitParen },
Paren {
paren: ParenGroup<()>,
#[group(self.paren)]
inner: Box<ParenBody>,
},
OpenModule {
grp: OpenModuleGroup<()>,
#[group(self.grp)]
body: Box<ParenBody>,
},
Record {
rec: RecordGroup<()>,
#[group(self.rec)]
body: RecordBody,
},
List {
list: ListGroup<()>,
#[group(self.list)]
items: Vec<ListItem>,
},
InlineText {
igrp: InlineGroup<()>,
#[group(self.igrp)]
elems: Vec<InlineElem>,
},
BlockText {
bgrp: BlockGroup<()>,
#[group(self.bgrp)]
elems: Vec<BlockElem>,
},
MathText {
mgrp: MathGroup<()>,
#[group(self.mgrp)]
elems: Vec<super::MathErased>,
},
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum RecordBody {
Update {
base: super::ExprErased,
with_kw: KwWith,
fields: Vec<RecordField>,
},
Fields(Vec<RecordField>),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct ParenBody {
pub first: super::ExprErased,
pub rest: Vec<CommaExpr>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CommaExpr {
pub comma: CommaTok,
pub value: super::ExprErased,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct RecordField {
pub name: VarTok,
pub eq: DefEqTok,
pub value: super::ExprErased,
pub semi: Option<ListPunctTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct ListItem {
pub value: super::ExprErased,
pub semi: Option<ListPunctTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum InlineElem {
Char(CharTok),
CodeText(CodeTextTok),
Space(SpaceTok),
Break(BreakTok),
Embed { var: VarInHorzTok, semi: EndActiveTok },
EmbedMath {
mgrp: MathGroup<()>,
#[group(self.mgrp)]
elems: Vec<super::MathErased>,
},
Cmd { name: AnyHorzCmdTok, tail: CmdTail },
ItemBullet(ItemTok),
Sep(SepTok),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum BlockElem {
Embed { var: VarInVertTok, semi: EndActiveTok },
Cmd { name: AnyVertCmdTok, tail: CmdTail },
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum CmdTail {
Semi(EndActiveTok),
Args {
first: super::AppArgErased,
rest: Vec<super::AppArgErased>,
semi: Option<EndActiveTok>,
},
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct Pattern {
pub head: PatCons,
pub as_clause: Option<AsClause>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct AsClause {
pub as_kw: KwAs,
pub name: VarTok,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum Param {
Optional { q: OptionalTok, name: VarTok },
Pat(PatBot),
Bundled { opts: CstOptBinders, body: PatBot },
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct PatCons {
pub head: PatBot,
pub tail: Vec<ConsSeg>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct ConsSeg {
pub cons: ConsTok,
pub tail: PatBot,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum PatBot {
CtorApplied { ctor: CtorTok, arg: Box<PatBot> },
Ctor(CtorTok),
Int(IntTok),
True(KwTrue),
False(KwFalse),
Str(LiteralTok),
Wild(WildcardTok),
Var(VarTok),
Unit { paren: UnitParen },
Paren {
paren: ParenGroup<()>,
#[group(self.paren)]
inner: Box<PatternParenBody>,
},
List {
plist: ListGroup<()>,
#[group(self.plist)]
items: Vec<PatListItem>,
},
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct PatternParenBody {
pub first: super::PatErased,
pub rest: Vec<CommaPattern>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CommaPattern {
pub comma: CommaTok,
pub value: super::PatErased,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct PatListItem {
pub value: super::PatErased,
pub semi: Option<ListPunctTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum TypeExpr {
Fun {
opts: Vec<OptArrowDom>,
dom: TypeProd,
arrow: ArrowTok,
cod: Box<TypeExpr>,
},
Atom(TypeProd),
OptRowFun {
opt_dom: CstTypeOptDom,
dom: TypeProd,
arrow: ArrowTok,
cod: Box<TypeExpr>,
},
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstTypeOptDom {
pub q: OptionalTypeTok,
pub paren: ParenGroup<()>,
#[group(self.paren)]
pub entries: Vec<CstTypeOptEntry>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstTypeOptEntry {
pub label: VarTok,
pub colon: ColonTok,
pub ty: super::TyErased,
pub comma: Option<CommaTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct OptArrowDom {
pub ty: TypeProd,
pub arrow: OptionalArrowTok,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TypeProd {
pub first: TypeApp,
pub rest: Vec<StarType>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct StarType {
pub star: ExactTimesTok,
pub ty: TypeApp,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TypeApp {
pub head: TypeAtom,
pub rest: Vec<TypeAtom>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum TypeAtom {
Cmd {
list: ListGroup<()>,
#[group(self.list)]
args: Vec<TypeCmdArgItem>,
kind: CmdTypeKind,
},
Paren {
paren: ParenGroup<()>,
#[group(self.paren)]
inner: super::TyErased,
},
Record {
rec: RecordGroup<()>,
#[group(self.rec)]
fields: Vec<TypeRecordField>,
},
Var(TypeVarTok),
Name(VarTok),
NameMod(VarWithModTok),
RecordOpen {
orec: RecordGroup<()>,
#[group(self.orec)]
inner: CstRecordOpenInner,
},
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstRecordOpenInner {
pub fields: Vec<CstRecordOpenField>,
pub bar: BarTok,
pub var: RowVarTok,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct CstRecordOpenField {
pub name: VarTok,
pub colon: ColonTok,
pub ty: super::TyErased,
pub comma: Option<CommaTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TypeRecordField {
pub name: VarTok,
pub colon: ColonTok,
pub ty: super::TyErased,
pub semi: Option<ListPunctTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TypeCmdArgItem {
pub opt_labels: Vec<TypeCmdOptField>,
pub ty: super::TyErased,
pub opt: Option<OptionalTypeTok>,
pub semi: Option<ListPunctTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct TypeCmdOptField {
pub label: VarTok,
pub colon: ColonTok,
pub ty: super::TyErased,
pub comma: Option<CommaTok>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum CmdTypeKind {
Inline(HorzCmdTypeTok),
Block(VertCmdTypeTok),
Math(MathCmdTypeTok),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub struct MathElemCst {
pub base: MathBot,
pub scripts: Vec<MathScript>,
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum MathBot {
Cmd { name: AnyMathCmdTok, args: Vec<MathArg> },
Chars(MathCharTok),
Embed(VarInMathTok),
Sep(SepTok),
Group {
mgrp: MathGroup<()>,
#[group(self.mgrp)]
elems: Vec<super::MathErased>,
},
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum MathScript {
Super { hat: SuperscriptTok, group: MathGroupArg },
Sub { under: SubscriptTok, group: MathGroupArg },
Primes(PrimesTok),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum MathGroupArg {
Group {
mgrp: MathGroup<()>,
#[group(self.mgrp)]
elems: Vec<super::MathErased>,
},
Bot(Box<MathBot>),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum MathArg {
Optional { q: OptionalTok, body: MathArgBody },
Omission(OmissionTok),
Plain(MathArgBody),
}
#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
pub enum MathArgBody {
Math {
mgrp: MathGroup<()>,
#[group(self.mgrp)]
elems: Vec<super::MathErased>,
},
Inline {
igrp: InlineGroup<()>,
#[group(self.igrp)]
elems: Vec<InlineElem>,
},
Block {
bgrp: BlockGroup<()>,
#[group(self.bgrp)]
elems: Vec<BlockElem>,
},
ParenEscape {
paren: ParenGroup<()>,
#[group(self.paren)]
inner: Box<ParenBody>,
},
ListEscape {
list: ListGroup<()>,
#[group(self.list)]
items: Vec<ListItem>,
},
RecordEscape {
rec: RecordGroup<()>,
#[group(self.rec)]
body: RecordBody,
},
}
}
pub use crate::parse_error::ParseFileError;
pub fn parse_file(src: &str) -> Result<File, ParseFileError> {
let atoms = crate::lexer::lex(src).map_err(ParseFileError::from_lex)?;
let mut stream = crate::stream::AtomStream::new(atoms);
match <File as Parse<_>>::parse(&mut stream) {
Ok(file) => Ok(file),
Err(e) => Err(crate::parse_error::locate(src, &stream, &e)),
}
}