1mod catcode;
4mod mathcode;
5use crate::command;
6use crate::parse;
7use crate::prelude as txl;
8use crate::traits::*;
9pub use catcode::CatCode;
10pub use mathcode::MathCode;
11
12impl Parsable for common::FontId {
13 fn parse_impl<S: TexlangState>(input: &mut crate::vm::ExpandedStream<S>) -> txl::Result<Self> {
14 match parse_font_or(input)? {
16 None => {
17 let token_or = input.peek()?;
18 input.error(
19 parse::Error::new(
20 "a font reference",
21 token_or,
22 r"a font reference can either be the current font (e.g. \font), a font variable (e.g. \textfont 1) or the result of loading a font (e.g. \a after \font \a path/to/font)",
23 )
24 )?;
25 Ok(common::FontId::NULL)
26 }
27 Some(font) => Ok(font),
28 }
29 }
30}
31
32fn parse_font_or<S: TexlangState>(
33 input: &mut crate::vm::ExpandedStream<S>,
34) -> txl::Result<Option<common::FontId>> {
35 let Some(token) = input.next()? else {
36 return Ok(None);
37 };
38 let crate::token::Value::CommandRef(command_ref) = token.value() else {
39 input.back(token);
40 return Ok(None);
41 };
42 match input.commands_map().get_command(&command_ref) {
43 Some(command::Command::Font(f)) => {
44 let f = *f;
45 Ok(Some(f))
46 }
47 Some(command::Command::Variable(var)) => {
48 let var = var.clone();
49 match var.resolve_type::<common::FontId>(token, input)? {
50 None => {
51 input.back(token);
52 Ok(None)
53 }
54 Some(typed_variable) => Ok(Some(*typed_variable.get(input.state()))),
55 }
56 }
57 Some(command::Command::Execution(_, Some(tag))) => {
58 if input.state().is_current_font_command(*tag) {
59 Ok(Some(input.vm().current_font()))
60 } else {
61 input.back(token);
62 Ok(None)
63 }
64 }
65 _ => {
66 input.back(token);
67 Ok(None)
68 }
69 }
70}