1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2020 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "gl/xalloc.h"
21 #include "tex-parsing.h"
22 #include "libpspp/ll.h"
36 /* Return the category of C.
37 These are the default TeX categories as defined in Chapter 7 of
40 category (const char c)
42 if (c >= 'A' && c <= 'Z')
45 if (c >= 'a' && c <= 'z')
53 return CAT_BEGIN_GROUP;
63 return CAT_SUPERSCRIPT;
86 /* Parse the TeX fragment STR into TeX tokens and push them
89 tex_parse (const char *str, struct ll_list *list)
91 enum state state = STATE_INITIAL;
92 struct tex_token *token = NULL;
94 while ((c = *str++) != '\0')
96 enum tex_cat cat = category (c);
98 if (state == STATE_COMMENT)
100 ds_put_byte (&token->str, c);
103 token->cat = CAT_COMMENT;
104 ll_push_tail (list, &token->ll);
105 state = STATE_INITIAL;
108 else if (state == STATE_INITIAL)
110 token = XZALLOC (struct tex_token);
111 ds_init_empty (&token->str);
112 if (cat == CAT_COMMENT)
114 ds_put_byte (&token->str, c);
115 state = STATE_COMMENT;
117 else if (cat == CAT_ESCAPE)
119 ds_put_byte (&token->str, c);
124 ds_put_byte (&token->str, c);
125 token->cat = category (c);
126 ll_push_tail (list, &token->ll);
129 else if (state == STATE_CS)
131 ds_put_byte (&token->str, c);
132 if (cat != CAT_LETTER)
134 if (ds_length (&token->str) > 2)
136 ds_truncate (&token->str, ds_length (&token->str) - 1);
139 token->cat = CAT_CONTROL_SEQ;
140 ll_push_tail (list, &token->ll);
141 state = STATE_INITIAL;
145 if (state == STATE_CS)
147 /* The end of the string was encountered whilst processing
148 a control sequence. */
150 /* A \ at the end of the string must be erroneous. */
151 assert (ds_length (&token->str) > 1);
152 token->cat = CAT_CONTROL_SEQ;
153 ll_push_tail (list, &token->ll);
154 state = STATE_INITIAL;
157 assert (state == STATE_INITIAL);