Expand description
The SATySFi 0.0.6 surface grammar (a subset of the v0.0.6 parser.mly),
parsed with syan derives over the SATySFi token atoms.
Application and the nxlor..nxrtimes binary-operator levels are
left-recursive in the Menhir grammar; here they are head-plus-arguments
Vecs, folded left during elaboration — recursive descent must never see
left recursion. All ten binop precedence levels are flattened into one
OpChain, deferring precedence/associativity to the elaborator — a
deliberate deviation from parser.mly’s structure, not its token set
(every operator it accepts is accepted here too).
let-inline/let-block are top-level-only, matching parser.mly:
LETHORZ/LETVERT only appear in nxtoplevel/nxstruct (via
nxhorzdec/nxvertdec), never in nxletsub — unlike let/let-rec they
have no local (in-bodied) form, only as one of a file’s leading
TopBindings.
Re-exports§
pub use crate::parse_error::ParseFileError;
Modules§
- ast
- The recursive expression/pattern/type/text grammar. Program expressions
embed inline/block text (
{…},'<…>), text embeds commands, and command arguments re-enter program expressions.
Structs§
- AndType
Clause - One
and 'a name = bodycontinuation of aTypeDecl’s mutual-recursion chain (mirrorsast::AndBindingforlet-rec). - AppArg
Erased - An
ast::AppArgbehind a stream-erasing parse (see above). Bridges a command tail’s argument chain (CmdTail::Args, below) intoAppArg’s own parser without a direct field reference:CmdTailis reached fromExpr’s SCC viaAtomic::InlineText/BlockText->InlineElem/BlockElem->CmdTail, so a directAppArgfield here would close a brand-new cycle back intoAtomic(AppArg::Atom.atom: Atomic) entirely through non-root types — the exact “sub-cycle running entirely through non-root types” shape the#[recurse]engine rejects (seePatCons’s doc comment for the same hazard). Routing through this eraser keepsCmdTaila DAG leaf, same as every other cross-reference here. - BarVariant
Def - A
| Ctor [of ty]continuation of a variant list. - Bind
Name - A binding-position NAME: a plain variable, or
( ‹op› )— a parenthesized (possibly user-defined) operator name (OpNameTok), e.g.let (+++>) = ... Upstream’svarnonterminal foldsVARandLPAREN binop RPARENinto one production; this is that nonterminal, reused byTopLet::name,ast::Expr::LetIn’sname,ast::RecBinding::name, andSigItem::Val’sname— the four binding positions upstream admits it in..name/.spanmirrorVarTok’s own public fields exactly, so anelaborate.rs/typecheck.rscallsite readingfoo.name.name/foo.name.spanworks against either type. See alsoast::Atomic::OpRef, the matching atomic-expression form. - Expr
Erased - An
ast::Exprbehind a stream-erasing parse (see above). - File
- A whole
.saty/.satyhfile: headers, top-level bindings,in, the document expression (main/nxtoplevel/nxtopsubseqin parser.mly). - Math
Erased - An
ast::MathElemCstbehind a stream-erasing parse (see above). Unlike the other three erasers this one isn’t bridging a self-loop of its target’s own SCC —MathElemCstturns out to have no direct self-loop at all (see its doc comment) — but every nested reference to “one math element” still goes through here, for the same monomorphize-once reason. - OfType
- The
of tysuffix of a variant definition. - PatBot
Erased - An
ast::PatBotbehind a stream-erasing parse (see above). Kept separate fromPatErasedbecause a constructor pattern’s argument is apatbot, not a fullpatas(Some x as ybindsyto the whole value, not tox). - PatErased
- An
ast::Patternbehind a stream-erasing parse (see above). - Record
Kind kxtop:(| l1 : ty1; … |), a record-kind bound — “the constrained type variable must be a record containing at least these labels” (upstreamMRecordKind; lowers to this port’sKind::Recordrow obligation, presence-only — seetypecheck.rs).- Record
Kind Field - One
l : ty;field of aRecordKind(txrecord,parser.mly:962-965). The field type is parsed but currently dropped during lowering (only the label is kept, matchingKind::Record’s label-only representation) — a documented limitation, not a grammar gap. - SigAnnot
: sig ... end(nxsigopt/nxsigelem, drastically simplified — seeSigItem).- SigConstraint
- One
constrnt:constraint 'a :: (| l1 : ty1; l2 : ty2; … |)(parser.mly:526-530), a per-item suffix binding that item’s type variable to a row-kind obligation — not a standaloneSigItem(a reader expecting the latter should see this doc: upstream attachesconstrntstoSigValue/SigDirect/SigTypedirectly, so the suffix form here is the faithful one and avoids an ambiguous “which item does this constrain?”). - Struct
Decl - One declaration inside a
module ... = struct ... endbody (nxstruct).nxstruct’s alternatives are a strict subset ofnxtoplevel’s (every form it has,TopBindingalso has, onceModule/Openare added), so this simply re-parses aTopBinding— but not by namingTopBindingas a field type directly:TopBindinglives outside the#[recurse]module, soTopBinding -> Module -> Vec<StructDecl> -> TopBindingwould be a self-recursive cycle through a plain#[derive(Parse)], which (without the#[recurse]engine to back it) is anE0275hazard (an unbounded recursive trait-bound obligation). Hand-writingParse/Unparsehere — the same trick asExprErasedet al. — sidesteps that: the impl has no recursive where-bound for the compiler to try to satisfy, it just callsTopBinding::parsethrough the stream-erasing adapter at runtime. - TopLet
- A top-level non-recursive binding:
let name param* = expr.paramsisVec<ast::PatBot>(not merelyVec<VarTok>) —nxnonrecdec’sargpartispatbot*upstream too, matchingast::RecBinding’s field of the same name. Elaborated by the samerec_clause_valuehelperRecBindinguses (elaborate.rs), with no multi-clauseextra. - TopStage
- A binding’s own stage qualifier:
~(stage 0) orpersistent ~(persistent stage), the prefix SATySFi 0.1 writes betweenvaland the bound name (parser_v1.mly:417-421,UTBindValue(Stage0 | Persistent0, _); the absent prefix isStage1, the document stage). - TyErased
- An
ast::TypeExprbehind a stream-erasing parse (see above). - Type
Decl - A
typedeclaration, optionally with mutual (and) recursion between several type declarations (parser.mly’snxvariantdecand-chain, e.g.satysfi-base’sstream.satyg:type 'a state = … and 'a u = ('a state) Promise.t). The head clause iskw..body; every furtherand-clause is anAndTypeClause. All clauses in one chain are mutually visible — they lower to consecutiveUserTypeDecl/UserSynonymDecls, exactly the shape the 0.1 lowering (v1/lower.rs) already produces fortype … and …, which the typechecker resolves with the same forward-reference tolerance. - Variant
Def - One
Ctor [of ty]variant definition.
Enums§
- Header
@require:/@import:/@stage:header element.- SigItem
- One
nxsigelem. Type parameters/type synonyms ontypeitems are not supported — such input is rejected with a parse error. Each item may carry a trailingconstrnts(parser.mly:526-530) — seeSigConstraint. - TopBinding
- One top-level declaration (
nxtoplevel/nxstruct’s per-declaration alternatives).LetInline/LetBlockonly exist here — see the module doc comment. - Type
Decl Body - The right-hand side of a
typedeclaration: either a variant’s constructor list, or (transparently) a type-synonym body. Trying the variant shape first is unambiguous: a type name is always a bareVARin this grammar (txbot), so no type expression can ever start with theBarTok/CtorToka variant list requires — any input that isn’t a variant list falls through toSynonymcleanly, exactly like upstream’snxvariantdectellingvariants(alwaysCONSTRUCTOR-headed) apart fromtxfuncby lookahead.
Functions§
- parse_
file - Lex and parse a whole
.satysource file.