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