1use crate::span::Span;
12pub use crate::token::*;
15use syan::error::ParseError;
16use syan::parse::unparse::Emitter;
17use syan::parse::{Parse, ParseStream, Unparse};
18use syan::span::Spanned;
19
20macro_rules! qualified_name_tokens {
25 ($($(#[$doc:meta])* $name:ident => $variant:ident, $desc:literal;)*) => {
26 $(
27 $(#[$doc])*
28 #[derive(Clone, Debug, PartialEq)]
29 pub struct $name {
30 pub mods: Vec<String>,
31 pub name: String,
32 pub span: Span,
33 }
34
35 impl Parse<Atom> for $name {
36 type Error = ParseError<Span>;
37
38 fn parse_stream<S: ParseStream<Atom = Atom>>(
39 stream: &mut S,
40 ) -> Result<Self, Self::Error> {
41 match stream.next() {
42 Some(Atom { slot: Token::$variant(mods, name), span }) => {
43 Ok($name { mods, name, span })
44 }
45 Some(atom) => {
46 let span = atom.span;
47 stream.push(atom);
48 Err(ParseError::expected(span, $desc))
49 }
50 None => Err(ParseError::eof(Span::default())),
51 }
52 }
53 }
54
55 impl Unparse<Atom> for $name {
56 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
57 sink.write_one(Atom {
58 slot: Token::$variant(self.mods.clone(), self.name.clone()),
59 span: self.span,
60 })
61 }
62 }
63
64 impl Spanned for $name {
65 type Span = Span;
66 fn span(&self) -> Span {
67 self.span
68 }
69 }
70 )*
71 };
72}
73
74qualified_name_tokens! {
75 VarInHorzTok => VarInHorz, "a variable reference in inline text";
77 VarInVertTok => VarInVert, "a variable reference in block text";
79 VarInMathTok => VarInMath, "a variable reference in math";
81 VarWithModTok => VarWithMod, "a qualified variable name";
83 LongUpperTok => LongUpper, "a qualified module path";
88 HorzCmdWithModTok => HorzCmdWithMod, "a qualified inline command";
90 VertCmdWithModTok => VertCmdWithMod, "a qualified block command";
92 MathCmdWithModTok => MathCmdWithMod, "a qualified math command";
94}
95
96#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
100pub enum AnyHorzCmdTok {
101 Plain(HorzCmdTok),
102 Mod(HorzCmdWithModTok),
103}
104
105#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
108pub enum AnyVertCmdTok {
109 Plain(VertCmdTok),
110 Mod(VertCmdWithModTok),
111}
112
113#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
116pub enum AnyMathCmdTok {
117 Plain(MathCmdTok),
118 Mod(MathCmdWithModTok),
119}
120
121#[derive(Clone, Debug, PartialEq)]
123pub struct LengthTok {
124 pub value: f64,
125 pub unit: String,
126 pub span: Span,
127}
128
129impl Parse<Atom> for LengthTok {
130 type Error = ParseError<Span>;
131
132 fn parse_stream<S: ParseStream<Atom = Atom>>(
133 stream: &mut S,
134 ) -> Result<Self, Self::Error> {
135 match stream.next() {
136 Some(Atom {
137 slot: Token::LengthConst(value, unit),
138 span,
139 }) => Ok(LengthTok { value, unit, span }),
140 Some(atom) => {
141 let span = atom.span;
142 stream.push(atom);
143 Err(ParseError::expected(span, "a length constant"))
144 }
145 None => Err(ParseError::eof(Span::default())),
146 }
147 }
148}
149
150impl Unparse<Atom> for LengthTok {
151 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
152 sink.write_one(Atom {
153 slot: Token::LengthConst(self.value, self.unit.clone()),
154 span: self.span,
155 })
156 }
157}
158
159impl Spanned for LengthTok {
160 type Span = Span;
161 fn span(&self) -> Span {
162 self.span
163 }
164}
165
166#[derive(Clone, Debug, PartialEq)]
168pub struct LiteralTok {
169 pub body: String,
170 pub omit_pre: bool,
171 pub omit_post: bool,
172 pub span: Span,
173}
174
175impl Parse<Atom> for LiteralTok {
176 type Error = ParseError<Span>;
177
178 fn parse_stream<S: ParseStream<Atom = Atom>>(
179 stream: &mut S,
180 ) -> Result<Self, Self::Error> {
181 match stream.next() {
182 Some(Atom {
183 slot:
184 Token::Literal {
185 body,
186 omit_pre,
187 omit_post,
188 },
189 span,
190 }) => Ok(LiteralTok {
191 body,
192 omit_pre,
193 omit_post,
194 span,
195 }),
196 Some(atom) => {
197 let span = atom.span;
198 stream.push(atom);
199 Err(ParseError::expected(span, "a string literal"))
200 }
201 None => Err(ParseError::eof(Span::default())),
202 }
203 }
204}
205
206impl Unparse<Atom> for LiteralTok {
207 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
208 sink.write_one(Atom {
209 slot: Token::Literal {
210 body: self.body.clone(),
211 omit_pre: self.omit_pre,
212 omit_post: self.omit_post,
213 },
214 span: self.span,
215 })
216 }
217}
218
219impl Spanned for LiteralTok {
220 type Span = Span;
221 fn span(&self) -> Span {
222 self.span
223 }
224}
225
226#[derive(Clone, Debug, PartialEq)]
234pub struct ExactTimesTok {
235 pub span: Span,
236}
237
238impl Parse<Atom> for ExactTimesTok {
239 type Error = ParseError<Span>;
240
241 fn parse_stream<S: ParseStream<Atom = Atom>>(
242 stream: &mut S,
243 ) -> Result<Self, Self::Error> {
244 match stream.next() {
245 Some(Atom {
246 slot: Token::ExactTimes,
247 span,
248 }) => Ok(ExactTimesTok { span }),
249 Some(atom) => {
250 let span = atom.span;
251 stream.push(atom);
252 Err(ParseError::expected(span, "'*'"))
253 }
254 None => Err(ParseError::eof(Span::default())),
255 }
256 }
257}
258
259impl Unparse<Atom> for ExactTimesTok {
260 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
261 sink.write_one(Atom {
262 slot: Token::ExactTimes,
263 span: self.span,
264 })
265 }
266}
267
268impl Spanned for ExactTimesTok {
269 type Span = Span;
270 fn span(&self) -> Span {
271 self.span
272 }
273}
274
275#[derive(Clone, Debug, PartialEq)]
283pub struct BinOpTok {
284 pub tok: Token,
285 pub span: Span,
286}
287
288impl Parse<Atom> for BinOpTok {
289 type Error = ParseError<Span>;
290
291 fn parse_stream<S: ParseStream<Atom = Atom>>(
292 stream: &mut S,
293 ) -> Result<Self, Self::Error> {
294 match stream.next() {
295 Some(Atom { slot, span })
296 if matches!(
297 slot,
298 Token::BinopPlus(_)
299 | Token::BinopMinus(_)
300 | Token::BinopTimes(_)
301 | Token::BinopDivides(_)
302 | Token::BinopEq(_)
303 | Token::BinopLt(_)
304 | Token::BinopGt(_)
305 | Token::BinopAmp(_)
306 | Token::BinopBar(_)
307 | Token::BinopHat(_)
308 | Token::ExactMinus
309 | Token::ExactTimes
310 | Token::Mod
311 | Token::Cons
312 ) =>
313 {
314 Ok(BinOpTok { tok: slot, span })
315 }
316 Some(atom) => {
317 let span = atom.span;
318 stream.push(atom);
319 Err(ParseError::expected(span, "a binary operator"))
320 }
321 None => Err(ParseError::eof(Span::default())),
322 }
323 }
324}
325
326impl Unparse<Atom> for BinOpTok {
327 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
328 sink.write_one(Atom {
329 slot: self.tok.clone(),
330 span: self.span,
331 })
332 }
333}
334
335impl Spanned for BinOpTok {
336 type Span = Span;
337 fn span(&self) -> Span {
338 self.span
339 }
340}
341
342impl BinOpTok {
343 pub fn op_text(&self) -> String {
345 match &self.tok {
346 Token::BinopPlus(s)
347 | Token::BinopMinus(s)
348 | Token::BinopTimes(s)
349 | Token::BinopDivides(s)
350 | Token::BinopEq(s)
351 | Token::BinopLt(s)
352 | Token::BinopGt(s)
353 | Token::BinopAmp(s)
354 | Token::BinopBar(s)
355 | Token::BinopHat(s) => s.clone(),
356 Token::ExactMinus => "-".to_string(),
357 Token::ExactTimes => "*".to_string(),
358 Token::Mod => "mod".to_string(),
359 Token::Cons => "::".to_string(),
360 _ => unreachable!("BinOpTok only ever holds one of the matched variants"),
361 }
362 }
363}
364
365#[derive(Clone, Debug, PartialEq)]
384pub struct NamingOpTok {
385 pub tok: Token,
386 pub span: Span,
387}
388
389impl Parse<Atom> for NamingOpTok {
390 type Error = ParseError<Span>;
391
392 fn parse_stream<S: ParseStream<Atom = Atom>>(
393 stream: &mut S,
394 ) -> Result<Self, Self::Error> {
395 match stream.next() {
396 Some(Atom { slot, span })
397 if matches!(
398 slot,
399 Token::BinopPlus(_)
400 | Token::BinopMinus(_)
401 | Token::BinopTimes(_)
402 | Token::BinopDivides(_)
403 | Token::BinopEq(_)
404 | Token::BinopLt(_)
405 | Token::BinopGt(_)
406 | Token::BinopAmp(_)
407 | Token::BinopBar(_)
408 | Token::BinopHat(_)
409 | Token::ExactMinus
410 | Token::ExactTimes
411 | Token::Mod
412 | Token::Cons
413 | Token::UnopExclam(_)
414 | Token::Before
415 ) =>
416 {
417 Ok(NamingOpTok { tok: slot, span })
418 }
419 Some(atom) => {
420 let span = atom.span;
421 stream.push(atom);
422 Err(ParseError::expected(
423 span,
424 "a binary operator, '!', or 'before'",
425 ))
426 }
427 None => Err(ParseError::eof(Span::default())),
428 }
429 }
430}
431
432impl Unparse<Atom> for NamingOpTok {
433 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
434 sink.write_one(Atom {
435 slot: self.tok.clone(),
436 span: self.span,
437 })
438 }
439}
440
441impl Spanned for NamingOpTok {
442 type Span = Span;
443 fn span(&self) -> Span {
444 self.span
445 }
446}
447
448impl NamingOpTok {
449 pub fn op_text(&self) -> String {
453 match &self.tok {
454 Token::BinopPlus(s)
455 | Token::BinopMinus(s)
456 | Token::BinopTimes(s)
457 | Token::BinopDivides(s)
458 | Token::BinopEq(s)
459 | Token::BinopLt(s)
460 | Token::BinopGt(s)
461 | Token::BinopAmp(s)
462 | Token::BinopBar(s)
463 | Token::BinopHat(s)
464 | Token::UnopExclam(s) => s.clone(),
465 Token::ExactMinus => "-".to_string(),
466 Token::ExactTimes => "*".to_string(),
467 Token::Mod => "mod".to_string(),
468 Token::Cons => "::".to_string(),
469 Token::Before => "before".to_string(),
470 _ => unreachable!("NamingOpTok only ever holds one of the matched variants"),
471 }
472 }
473}
474
475#[derive(Clone, Debug, PartialEq)]
491pub struct OpNameTok {
492 pub name: String,
493 pub span: Span,
494 pub lparen: LParenTok,
495 pub op: NamingOpTok,
496 pub rparen: RParenTok,
497}
498
499impl Parse<Atom> for OpNameTok {
500 type Error = ParseError<Span>;
501
502 fn parse_stream<S: ParseStream<Atom = Atom>>(
503 stream: &mut S,
504 ) -> Result<Self, Self::Error> {
505 let lparen = LParenTok::parse_stream(&mut *stream)?;
506 let op = NamingOpTok::parse_stream(&mut *stream)?;
507 let rparen = RParenTok::parse_stream(&mut *stream)?;
508 let name = op.op_text();
509 let span = lparen.span().unite(rparen.span());
510 Ok(OpNameTok {
511 name,
512 span,
513 lparen,
514 op,
515 rparen,
516 })
517 }
518}
519
520impl Unparse<Atom> for OpNameTok {
521 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
522 self.lparen.unparse(sink)?;
523 self.op.unparse(sink)?;
524 self.rparen.unparse(sink)
525 }
526}
527
528impl Spanned for OpNameTok {
529 type Span = Span;
530 fn span(&self) -> Span {
531 self.span
532 }
533}
534
535#[derive(Clone, Debug, PartialEq)]
542pub struct HeaderStageTok {
543 pub tok: Token,
544 pub span: Span,
545}
546
547impl Parse<Atom> for HeaderStageTok {
548 type Error = ParseError<Span>;
549
550 fn parse_stream<S: ParseStream<Atom = Atom>>(
551 stream: &mut S,
552 ) -> Result<Self, Self::Error> {
553 match stream.next() {
554 Some(Atom { slot, span })
555 if matches!(
556 slot,
557 Token::HeaderStage0 | Token::HeaderStage1 | Token::HeaderPersistent0
558 ) =>
559 {
560 Ok(HeaderStageTok { tok: slot, span })
561 }
562 Some(atom) => {
563 let span = atom.span;
564 stream.push(atom);
565 Err(ParseError::expected(span, "'@stage:'"))
566 }
567 None => Err(ParseError::eof(Span::default())),
568 }
569 }
570}
571
572impl Unparse<Atom> for HeaderStageTok {
573 fn unparse<S: Emitter<Atom>>(&self, sink: &mut S) -> Result<(), S::Error> {
574 sink.write_one(Atom {
575 slot: self.tok.clone(),
576 span: self.span,
577 })
578 }
579}
580
581impl Spanned for HeaderStageTok {
582 type Span = Span;
583 fn span(&self) -> Span {
584 self.span
585 }
586}
587
588pub type ParenGroup<T> = syan::nested::group::Group<T, LParenTok, RParenTok>;
598pub type RecordGroup<T> = syan::nested::group::Group<T, BRecordTok, ERecordTok>;
600pub type ListGroup<T> = syan::nested::group::Group<T, BListTok, EListTok>;
602pub type InlineGroup<T> = syan::nested::group::Group<T, BHorzGrpTok, EHorzGrpTok>;
604pub type BlockGroup<T> = syan::nested::group::Group<T, BVertGrpTok, EVertGrpTok>;
606pub type MathGroup<T> = syan::nested::group::Group<T, BMathGrpTok, EMathGrpTok>;
608pub type OpenModuleGroup<T> = syan::nested::group::Group<T, OpenModuleTok, RParenTok>;
613
614#[derive(Parse, Unparse, Debug, Clone, PartialEq)]
634pub struct UnitParen {
635 pub open: LParenTok,
636 pub close: RParenTok,
637}
638
639impl Spanned for UnitParen {
640 type Span = Span;
641 fn span(&self) -> Span {
642 self.open.span().unite(self.close.span())
643 }
644}
645
646macro_rules! leaf_eq {
653 (
654 span_only: $($unit:ident),* $(,)?;
655 with_fields: $($payload:ident { $($field:ident),* }),* $(,)?
656 ) => {
657 $(
658 impl PartialEq for $unit {
659 fn eq(&self, other: &Self) -> bool {
660 self.0 == other.0
661 }
662 }
663 )*
664 $(
665 impl PartialEq for $payload {
666 fn eq(&self, other: &Self) -> bool {
667 $(self.$field == other.$field &&)* self.span == other.span
668 }
669 }
670 )*
671 };
672}
673
674leaf_eq! {
675 span_only:
676 KwLet, KwLetRec, KwLetHorz, KwLetVert, KwLetMath, KwAnd, KwIn, KwFun,
677 KwIf, KwThen, KwElse, KwTrue, KwFalse, ArrowTok, DefEqTok, ListPunctTok,
678 CommaTok, LParenTok, RParenTok, BRecordTok, ERecordTok, BListTok, EListTok,
679 BHorzGrpTok, EHorzGrpTok, BVertGrpTok, EVertGrpTok, SpaceTok, BreakTok,
680 EndActiveTok, EoiTok, KwMatch, KwWith, KwWhen, KwAs, KwType, KwOf, BarTok,
681 WildcardTok, ConsTok, ColonTok, ExactMinusTok, KwLetMutable, KwWhile, KwDo,
682 KwBefore, OverwriteEqTok, AccessTok, KwModule, KwStruct, KwSig, KwEnd,
683 KwOpen, KwVal, KwDirect, OptionalTok, OmissionTok, SuperscriptTok,
684 SubscriptTok, SepTok, BMathGrpTok, EMathGrpTok, HorzCmdTypeTok,
685 VertCmdTypeTok, MathCmdTypeTok, OptionalTypeTok, OptionalArrowTok,
686 ConstraintTok, CommandTok, KwRec, KwInline, KwBlock, KwMutable,
687 CoerceTok, KwSignature, KwInclude, KwUse, KwPackage, KwMath,
688 KwPersistent, ExactAmpTok, ExactTildeTok;
689 with_fields:
690 VarTok { name }, CtorTok { name }, IntTok { value }, FloatTok { value },
691 HorzCmdTok { name }, VertCmdTok { name }, CharTok { text }, ItemTok { depth },
692 CodeTextTok { text },
693 HeaderRequireTok { content }, HeaderImportTok { content }, TypeVarTok { name },
694 UnopExclamTok { text }, MathCharTok { text }, MathCmdTok { name },
695 PrimesTok { count }, OpenModuleTok { name }, RowVarTok { name }
696}