1use std::path::PathBuf;
2
3use super::TexlangState;
4use crate::token::trace;
5use crate::token::Token;
6use crate::*;
7
8pub trait TokenStream {
33 type S;
35
36 fn next(&mut self) -> Result<Option<Token>, Box<error::Error>>;
43
44 fn peek(&mut self) -> Result<Option<&Token>, Box<error::Error>>;
65
66 fn consume(&mut self) -> Result<(), Box<error::Error>> {
71 self.next().map(|_| ())
72 }
73
74 fn vm(&self) -> &vm::VM<Self::S>;
76
77 #[inline]
79 fn commands_map(&self) -> &command::Map<Self::S> {
80 &self.vm().commands_map
81 }
82
83 #[inline]
85 fn state(&self) -> &Self::S {
86 &self.vm().state
87 }
88
89 fn trace(&self, token: Token) -> trace::SourceCodeTrace {
90 self.vm().trace(token)
91 }
92
93 fn trace_end_of_input(&self) -> trace::SourceCodeTrace {
94 self.vm().internal.tracer.trace_end_of_input()
95 }
96}
97
98#[repr(transparent)]
103pub struct ExpandedStream<S>(UnexpandedStream<S>);
104
105impl<S> std::convert::AsMut<ExpandedStream<S>> for ExpandedStream<S> {
106 fn as_mut(&mut self) -> &mut ExpandedStream<S> {
107 self
108 }
109}
110
111impl<S: TexlangState> ExpandedStream<S> {
112 pub fn unexpanded(&mut self) -> &mut UnexpandedStream<S> {
114 &mut self.0
115 }
116
117 pub fn expand_once(&mut self) -> Result<bool, Box<error::Error>> {
122 stream::expand_once(&mut self.unexpanded().0)
123 }
124}
125
126impl<S: TexlangState> TokenStream for ExpandedStream<S> {
127 type S = S;
128
129 #[inline]
130 fn next(&mut self) -> Result<Option<Token>, Box<error::Error>> {
131 stream::next_expanded(&mut self.unexpanded().0)
132 }
133
134 #[inline]
135 fn peek(&mut self) -> Result<Option<&Token>, Box<error::Error>> {
136 stream::peek_expanded(&mut self.unexpanded().0)
137 }
138
139 #[inline]
140 fn vm(&self) -> &vm::VM<Self::S> {
141 &self.0 .0
142 }
143}
144
145#[repr(transparent)]
153pub struct UnexpandedStream<S>(vm::VM<S>);
154
155impl<S: TexlangState> TokenStream for UnexpandedStream<S> {
156 type S = S;
157
158 #[inline]
159 fn next(&mut self) -> Result<Option<Token>, Box<error::Error>> {
160 stream::next_unexpanded(&mut self.0)
161 }
162
163 #[inline]
164 fn peek(&mut self) -> Result<Option<&Token>, Box<error::Error>> {
165 stream::peek_unexpanded(&mut self.0)
166 }
167
168 #[inline]
169 fn vm(&self) -> &vm::VM<S> {
170 &self.0
171 }
172}
173
174#[repr(transparent)]
196pub struct ExpansionInput<S>(ExpandedStream<S>);
199
200impl<S> std::convert::AsMut<ExpandedStream<S>> for ExpansionInput<S> {
201 fn as_mut(&mut self) -> &mut ExpandedStream<S> {
202 &mut self.0
203 }
204}
205
206impl<S: TexlangState> TokenStream for ExpansionInput<S> {
207 type S = S;
208
209 fn next(&mut self) -> Result<Option<Token>, Box<error::Error>> {
210 self.0.next()
211 }
212
213 fn peek(&mut self) -> Result<Option<&Token>, Box<error::Error>> {
214 self.0.peek()
215 }
216
217 fn vm(&self) -> &vm::VM<Self::S> {
218 self.0.vm()
219 }
220}
221
222impl<S> ExpansionInput<S> {
223 #[inline]
225 pub fn new(vm: &mut vm::VM<S>) -> &mut ExpansionInput<S> {
226 unsafe { &mut *(vm as *mut vm::VM<S> as *mut ExpansionInput<S>) }
227 }
228}
229
230impl<S: TexlangState> ExpansionInput<S> {
231 #[inline]
233 pub fn push_source(
234 &mut self,
235 token: Token,
236 file_name: PathBuf,
237 source_code: String,
238 ) -> Result<(), Box<error::Error>> {
239 self.0
240 .0
241 .0
242 .internal
243 .push_source(Some(token), file_name, source_code)
244 }
245
246 pub fn push_string_tokens(&mut self, token: Token, s: &str) {
247 let trace_key = token.trace_key();
248 for c in s.chars().rev() {
249 let token = match c {
250 ' ' => token::Token::new_space(' ', trace_key),
251 _ => token::Token::new_letter(c, trace_key),
252 };
253 self.expansions_mut().push(token);
254 }
255 }
256}
257
258impl<S> ExpansionInput<S> {
259 #[inline]
260 pub fn unexpanded(&mut self) -> &mut UnexpandedStream<S> {
261 &mut self.0 .0
262 }
263
264 #[inline]
265 pub fn expanded(&mut self) -> &mut ExpandedStream<S> {
266 &mut self.0
267 }
268
269 #[inline]
273 pub fn push_expansion(&mut self, expansion: &[Token]) {
274 self.0 .0 .0.internal.push_expansion(expansion)
275 }
276
277 #[inline]
284 pub fn expansions(&self) -> &Vec<Token> {
285 self.0 .0 .0.internal.expansions()
286 }
287
288 #[inline]
295 pub fn expansions_mut(&mut self) -> &mut Vec<Token> {
296 self.0 .0 .0.internal.expansions_mut()
297 }
298
299 pub fn checkout_token_buffer(&mut self) -> Vec<Token> {
315 self.0
316 .0
317 .0
318 .internal
319 .token_buffers
320 .pop()
321 .unwrap_or_default()
322 .0
323 }
324
325 pub fn return_token_buffer(&mut self, mut token_buffer: Vec<Token>) {
327 token_buffer.clear();
328 self.0
329 .0
330 .0
331 .internal
332 .token_buffers
333 .push(super::TokenBuffer(token_buffer))
334 }
335}
336
337#[repr(transparent)]
350pub struct ExecutionInput<S>(ExpandedStream<S>);
351
352impl<S> std::convert::AsMut<ExpandedStream<S>> for ExecutionInput<S> {
353 fn as_mut(&mut self) -> &mut ExpandedStream<S> {
354 &mut self.0
355 }
356}
357
358impl<S: TexlangState> TokenStream for ExecutionInput<S> {
359 type S = S;
360
361 fn next(&mut self) -> Result<Option<Token>, Box<error::Error>> {
362 self.0.next()
363 }
364
365 fn peek(&mut self) -> Result<Option<&Token>, Box<error::Error>> {
366 self.0.peek()
367 }
368
369 fn vm(&self) -> &vm::VM<Self::S> {
370 self.0.vm()
371 }
372}
373
374impl<S> ExecutionInput<S> {
375 #[inline]
377 pub fn new(state: &mut vm::VM<S>) -> &mut ExecutionInput<S> {
378 unsafe { &mut *(state as *mut vm::VM<S> as *mut ExecutionInput<S>) }
379 }
380
381 #[inline]
382 pub fn unexpanded(&mut self) -> &mut UnexpandedStream<S> {
383 &mut self.0 .0
384 }
385
386 #[inline]
387 pub fn commands_map_mut(&mut self) -> &mut command::Map<S> {
388 &mut self.0 .0 .0.commands_map
389 }
390
391 #[inline]
393 pub fn state_mut(&mut self) -> &mut S {
394 &mut self.0 .0 .0.state
395 }
396
397 pub fn state_mut_and_cs_name_interner(&mut self) -> (&mut S, &token::CsNameInterner) {
399 (
400 &mut self.0 .0 .0.state,
401 &self.0 .0 .0.internal.cs_name_interner,
402 )
403 }
404
405 pub fn begin_group(&mut self) {
407 self.0 .0 .0.begin_group()
408 }
409
410 pub fn end_group(&mut self, token: Token) -> Result<(), Box<error::Error>> {
411 self.0 .0 .0.end_group(token)
412 }
413
414 pub(crate) fn groups(&mut self) -> &mut [variable::SaveStackElement<S>] {
415 &mut self.0 .0 .0.internal.groups
416 }
417
418 pub(crate) fn current_group_mut(&mut self) -> Option<(&mut variable::SaveStackElement<S>, &S)> {
419 match self.0 .0 .0.internal.groups.last_mut() {
420 None => None,
421 Some(g) => Some((g, &self.0 .0 .0.state)),
422 }
423 }
424}
425
426#[inline]
435unsafe fn launder<'a>(token: &Token) -> &'a Token {
436 &*(token as *const Token)
437}
438
439mod stream {
440 use super::*;
441 use crate::token::lexer;
442 use crate::token::CatCode;
443 use crate::token::{lexer::CatCodeFn, Value::ControlSequence};
444
445 impl<T: TexlangState> CatCodeFn for T {
446 #[inline]
447 fn cat_code(&self, c: char) -> crate::token::CatCode {
448 self.cat_code(c)
449 }
450 }
451
452 #[inline]
453 pub fn next_unexpanded<S: TexlangState>(
454 vm: &mut vm::VM<S>,
455 ) -> Result<Option<Token>, Box<error::Error>> {
456 if let Some(token) = vm.internal.current_source.expansions.pop() {
457 return Ok(Some(token));
458 }
459 match vm
460 .internal
461 .current_source
462 .root
463 .next(&vm.state, &mut vm.internal.cs_name_interner)
464 {
465 Ok(None) => {}
466 Ok(Some(token)) => {
467 return Ok(Some(token));
468 }
469 Err(err) => return Err(LexerError::new(vm, err).into()),
470 }
471 next_unexpanded_recurse(vm)
472 }
473
474 fn next_unexpanded_recurse<S: TexlangState>(
475 vm: &mut vm::VM<S>,
476 ) -> Result<Option<Token>, Box<error::Error>> {
477 if vm.internal.pop_source() {
478 next_unexpanded(vm)
479 } else {
480 Ok(None)
481 }
482 }
483
484 #[inline]
485 pub fn peek_unexpanded<S: TexlangState>(
486 vm: &mut vm::VM<S>,
487 ) -> Result<Option<&Token>, Box<error::Error>> {
488 if let Some(token) = vm.internal.current_source.expansions.last() {
489 return Ok(Some(unsafe { launder(token) }));
490 }
491 match vm
492 .internal
493 .current_source
494 .root
495 .next(&vm.state, &mut vm.internal.cs_name_interner)
496 {
497 Ok(None) => {}
498 Ok(Some(token)) => {
499 vm.internal.current_source.expansions.push(token);
500 return Ok(vm.internal.current_source.expansions.last());
501 }
502 Err(err) => return Err(LexerError::new(vm, err).into()),
503 }
504 peek_unexpanded_recurse(vm)
505 }
506
507 fn peek_unexpanded_recurse<S: TexlangState>(
508 vm: &mut vm::VM<S>,
509 ) -> Result<Option<&Token>, Box<error::Error>> {
510 if vm.internal.pop_source() {
511 peek_unexpanded(vm)
512 } else {
513 Ok(None)
514 }
515 }
516
517 pub fn next_expanded<S: TexlangState>(
518 vm: &mut vm::VM<S>,
519 ) -> Result<Option<Token>, Box<error::Error>> {
520 let (token, command) = match next_unexpanded(vm)? {
521 None => return Ok(None),
522 Some(token) => match token.value() {
523 ControlSequence(name) => (token, vm.commands_map.get_command(&name)),
524 _ => return Ok(Some(token)),
525 },
526 };
527 match command {
528 Some(command::Command::Expansion(command, tag)) => {
529 let command = *command;
530 let tag = *tag;
531 match S::expansion_override_hook(token, ExpansionInput::new(vm), tag) {
532 Ok(None) => (),
533 Ok(Some(override_expansion)) => {
534 return Ok(Some(override_expansion));
535 }
536 Err(err) => return Err(convert_command_error(vm, token, err)),
537 };
538 let output = match command(token, ExpansionInput::new(vm)) {
539 Ok(output) => output,
540 Err(err) => return Err(convert_command_error(vm, token, err)),
541 };
542 vm.internal.push_expansion(&output);
543 next_expanded(vm)
544 }
545 Some(command::Command::Macro(command)) => {
546 let command = command.clone();
547 if let Err(err) = command.call(token, ExpansionInput::new(vm)) {
548 return Err(convert_command_error(vm, token, err));
549 }
550 next_expanded(vm)
551 }
552 _ => Ok(Some(token)),
553 }
554 }
555
556 pub fn peek_expanded<S: TexlangState>(
557 vm: &mut vm::VM<S>,
558 ) -> Result<Option<&Token>, Box<error::Error>> {
559 let (token, command) = match peek_unexpanded(vm)? {
560 None => return Ok(None),
561 Some(token) => match token.value() {
562 ControlSequence(name) => (
563 unsafe { launder(token) },
564 vm.commands_map.get_command(&name),
565 ),
566 _ => return Ok(Some(unsafe { launder(token) })),
567 },
568 };
569 match command {
570 Some(command::Command::Expansion(command, tag)) => {
571 let command = *command;
572 let token = *token;
573 let tag = *tag;
574 consume_peek(vm);
575 match S::expansion_override_hook(token, ExpansionInput::new(vm), tag) {
576 Ok(None) => (),
577 Ok(Some(override_expansion)) => {
578 vm.internal.expansions_mut().push(override_expansion);
579 return Ok(vm.internal.expansions().last());
580 }
581 Err(err) => return Err(convert_command_error(vm, token, err)),
582 };
583 let output = match command(token, ExpansionInput::new(vm)) {
584 Ok(output) => output,
585 Err(err) => return Err(convert_command_error(vm, token, err)),
586 };
587 vm.internal.push_expansion(&output);
588 peek_expanded(vm)
589 }
590 Some(command::Command::Macro(command)) => {
591 let command = command.clone();
592 let token = *token;
593 consume_peek(vm);
594 if let Err(err) = command.call(token, ExpansionInput::new(vm)) {
595 return Err(convert_command_error(vm, token, err));
596 }
597 peek_expanded(vm)
598 }
599 _ => Ok(Some(unsafe { launder(token) })),
600 }
601 }
602
603 pub fn expand_once<S: TexlangState>(vm: &mut vm::VM<S>) -> Result<bool, Box<error::Error>> {
604 let (token, command) = match peek_unexpanded(vm)? {
605 None => return Ok(false),
606 Some(token) => match token.value() {
607 ControlSequence(name) => (
608 unsafe { launder(token) },
609 vm.commands_map.get_command(&name),
610 ),
611 _ => return Ok(false),
612 },
613 };
614 match command {
615 Some(command::Command::Expansion(command, tag)) => {
616 let command = *command;
617 let token = *token;
618 let tag = *tag;
619 consume_peek(vm);
620 match S::expansion_override_hook(token, ExpansionInput::new(vm), tag) {
621 Ok(None) => (),
622 Ok(Some(override_expansion)) => {
623 vm.internal.expansions_mut().push(override_expansion);
624 return Ok(true);
625 }
626 Err(err) => return Err(convert_command_error(vm, token, err)),
627 };
628 let output = match command(token, ExpansionInput::new(vm)) {
629 Ok(output) => output,
630 Err(err) => return Err(convert_command_error(vm, token, err)),
631 };
632 vm.internal.push_expansion(&output);
633 Ok(true)
634 }
635 Some(command::Command::Macro(command)) => {
636 let command = command.clone();
637 let token = *token;
638 consume_peek(vm);
639 if let Err(err) = command.call(token, ExpansionInput::new(vm)) {
640 return Err(convert_command_error(vm, token, err));
641 }
642 Ok(true)
643 }
644 _ => Ok(false),
645 }
646 }
647
648 #[inline]
649 pub fn consume_peek<S>(vm: &mut vm::VM<S>) {
650 vm.internal.current_source.expansions.pop();
653 }
654
655 use crate::error::Error;
656
657 fn convert_command_error<S: TexlangState>(
658 vm: &mut vm::VM<S>,
659 token: Token,
660 err: Box<error::Error>,
661 ) -> Box<Error> {
662 Error::new_propagated(vm, error::PropagationContext::Expansion, token, err)
663 }
664
665 #[derive(Debug)]
666 enum LexerError {
667 InvalidCharacter(char, trace::SourceCodeTrace),
668 EmptyControlSequence(trace::SourceCodeTrace),
669 }
670
671 impl LexerError {
672 fn new<S>(vm: &vm::VM<S>, err: lexer::Error) -> LexerError {
673 match err {
674 lexer::Error::InvalidCharacter(c, key) => {
675 LexerError::InvalidCharacter(c, vm.trace(Token::new_other(c, key)))
676 }
677 lexer::Error::EmptyControlSequence(key) => {
678 LexerError::EmptyControlSequence(vm.trace(Token::new_other(' ', key)))
679 }
680 }
681 }
682 }
683
684 impl error::TexError for LexerError {
685 fn kind(&self) -> error::Kind {
686 match self {
687 LexerError::InvalidCharacter(_, key) => error::Kind::Token(key),
688 LexerError::EmptyControlSequence(key) => error::Kind::EndOfInput(key),
689 }
690 }
691
692 fn title(&self) -> String {
693 match self {
694 LexerError::InvalidCharacter(c, _) => {
695 format!["input contains a character {} (Unicode code point {}) with category code {}", *c, *c as u32, CatCode::Invalid]
696 }
697 LexerError::EmptyControlSequence(_) => {
698 format![
699 "unexpected end of file after a token with category code {}",
700 CatCode::Escape
701 ]
702 }
703 }
704 }
705
706 fn source_annotation(&self) -> String {
707 match self {
708 LexerError::InvalidCharacter(_, _) => "invalid character",
709 LexerError::EmptyControlSequence(_) => "file ended after this token",
710 }
711 .into()
712 }
713
714 fn notes(&self) -> Vec<error::display::Note> {
715 match self {
716 LexerError::InvalidCharacter(_, _) => vec![
717 format!["characters with category code {} cannot appear in the input", CatCode::Invalid].into()
718 ],
719 LexerError::EmptyControlSequence(_) => vec![
720 "escape tokens start a control sequence and must be followed by at least one character".into(),
721 ],
722 }
723 }
724 }
725}