1 /* Declarations having to do with GNU Emacs syntax tables.
2
3 Copyright (C) 1985, 1993-1994, 1997-1998, 2001-2023 Free Software
4 Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or (at
11 your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
20
21 #ifndef EMACS_SYNTAX_H
22 #define EMACS_SYNTAX_H
23
24 #include "buffer.h"
25 #include "lisp.h"
26
27 INLINE_HEADER_BEGIN
28
29 extern void update_syntax_table (ptrdiff_t, EMACS_INT, bool, Lisp_Object);
30 extern void update_syntax_table_forward (ptrdiff_t, bool, Lisp_Object);
31
32 /* The standard syntax table is stored where it will automatically
33 be used in all new buffers. */
34 #define Vstandard_syntax_table BVAR (&buffer_defaults, syntax_table)
35
36 /* A syntax table is a chartable whose elements are cons cells
37 (CODE+FLAGS . MATCHING-CHAR). MATCHING-CHAR can be nil if the char
38 is not a kind of parenthesis.
39
40 The low 8 bits of CODE+FLAGS is a code, as follows: */
41
42 enum syntaxcode
43 {
44 Swhitespace, /* for a whitespace character */
45 Spunct, /* for random punctuation characters */
46 Sword, /* for a word constituent */
47 Ssymbol, /* symbol constituent but not word constituent */
48 Sopen, /* for a beginning delimiter */
49 Sclose, /* for an ending delimiter */
50 Squote, /* for a prefix character like Lisp ' */
51 Sstring, /* for a string-grouping character like Lisp " */
52 Smath, /* for delimiters like $ in Tex. */
53 Sescape, /* for a character that begins a C-style escape */
54 Scharquote, /* for a character that quotes the following character */
55 Scomment, /* for a comment-starting character */
56 Sendcomment, /* for a comment-ending character */
57 Sinherit, /* use the standard syntax table for this character */
58 Scomment_fence, /* Starts/ends comment which is delimited on the
59 other side by any char with the same syntaxcode. */
60 Sstring_fence, /* Starts/ends string which is delimited on the
61 other side by any char with the same syntaxcode. */
62 Smax /* Upper bound on codes that are meaningful. */
63 };
64
65
66 struct gl_state_s
67 {
68 Lisp_Object object; /* The object we are scanning. */
69 ptrdiff_t start; /* Where to stop. */
70 ptrdiff_t stop; /* Where to stop. */
71 bool use_global; /* Whether to use global_code
72 or c_s_t. */
73 Lisp_Object global_code; /* Syntax code of current char. */
74 Lisp_Object current_syntax_table; /* Syntax table for current pos. */
75 Lisp_Object old_prop; /* Syntax-table prop at prev pos. */
76 ptrdiff_t b_property; /* First index where c_s_t is valid. */
77 ptrdiff_t e_property; /* First index where c_s_t is
78 not valid. */
79 bool e_property_truncated; /* true if e_property if was truncated
80 by parse_sexp_propertize_done. */
81 INTERVAL forward_i; /* Where to start lookup on forward. */
82 INTERVAL backward_i; /* or backward movement. The
83 data in c_s_t is valid
84 between these intervals,
85 and possibly at the
86 intervals too, depending
87 on: */
88 };
89
90 extern struct gl_state_s gl_state;
91
92 /* Fetch the information from the entry for character C
93 in the current buffer's syntax table,
94 or (if VIA_PROPERTY) from globally kept data (gl_state).
95 Does inheritance. */
96
97 INLINE Lisp_Object
98 syntax_property_entry (int c, bool via_property)
99 {
100 if (via_property)
101 return (gl_state.use_global
102 ? gl_state.global_code
103 : CHAR_TABLE_REF (gl_state.current_syntax_table, c));
104 return CHAR_TABLE_REF (BVAR (current_buffer, syntax_table), c);
105 }
106 INLINE Lisp_Object
107 SYNTAX_ENTRY (int c)
108 {
109 return syntax_property_entry (c, false);
110 }
111
112 /* Extract the information from the entry for character C
113 in the current syntax table. */
114
115 INLINE int
116 syntax_property_with_flags (int c, bool via_property)
117 {
118 Lisp_Object ent = syntax_property_entry (c, via_property);
119 return CONSP (ent) ? XFIXNUM (XCAR (ent)) : Swhitespace;
120 }
121 INLINE int
122 SYNTAX_WITH_FLAGS (int c)
123 {
124 return syntax_property_with_flags (c, false);
125 }
126
127 INLINE enum syntaxcode
128 syntax_property (int c, bool via_property)
129 {
130 return syntax_property_with_flags (c, via_property) & 0xff;
131 }
132 INLINE enum syntaxcode
133 SYNTAX (int c)
134 {
135 return syntax_property (c, false);
136 }
137
138
139 /* Whether the syntax of the character C has the prefix flag set. */
140 extern bool syntax_prefix_flag_p (int c);
141
142 /* This array, indexed by a character less than 256, contains the
143 syntax code which that character signifies (as an unsigned char).
144 For example, syntax_spec_code['w'] == Sword. */
145
146 extern unsigned char const syntax_spec_code[0400];
147
148 /* Convert the regexp's BYTEOFFSET into a character position,
149 for the object recorded in gl_state with RE_SETUP_SYNTAX_TABLE_FOR_OBJECT.
150
151 The value is meant for use in code that does nothing when
152 parse_sexp_lookup_properties is false, so return 0 in that case,
153 for speed. */
154
155 INLINE ptrdiff_t
156 RE_SYNTAX_TABLE_BYTE_TO_CHAR (ptrdiff_t byteoffset)
157 {
158 return (! parse_sexp_lookup_properties
159 ? 0
160 : STRINGP (gl_state.object)
161 ? string_byte_to_char (gl_state.object, byteoffset)
162 : BUFFERP (gl_state.object)
163 ? ((buf_bytepos_to_charpos
164 (XBUFFER (gl_state.object),
165 (byteoffset + BUF_BEGV_BYTE (XBUFFER (gl_state.object))))))
166 : NILP (gl_state.object)
167 ? BYTE_TO_CHAR (byteoffset + BEGV_BYTE)
168 : byteoffset);
169 }
170
171 /* Make syntax table state (gl_state) good for CHARPOS, assuming it is
172 currently good for a position before CHARPOS. */
173
174 INLINE void
175 UPDATE_SYNTAX_TABLE_FORWARD (ptrdiff_t charpos)
176 { /* Performs just-in-time syntax-propertization. */
177 if (parse_sexp_lookup_properties && charpos >= gl_state.e_property)
178 update_syntax_table_forward (charpos, false, gl_state.object);
179 }
180
181 /* Make syntax table state (gl_state) good for CHARPOS, assuming it is
182 currently good for a position after CHARPOS. */
183
184 INLINE void
185 UPDATE_SYNTAX_TABLE_BACKWARD (ptrdiff_t charpos)
186 {
187 if (parse_sexp_lookup_properties && charpos < gl_state.b_property)
188 update_syntax_table (charpos, -1, false, gl_state.object);
189 }
190
191 /* Make syntax table good for CHARPOS. */
192
193 INLINE void
194 UPDATE_SYNTAX_TABLE (ptrdiff_t charpos)
195 {
196 UPDATE_SYNTAX_TABLE_BACKWARD (charpos);
197 UPDATE_SYNTAX_TABLE_FORWARD (charpos);
198 }
199
200 /* Set up the buffer-global syntax table. */
201
202 INLINE void
203 SETUP_BUFFER_SYNTAX_TABLE (void)
204 {
205 gl_state.use_global = false;
206 gl_state.e_property_truncated = false;
207 gl_state.current_syntax_table = BVAR (current_buffer, syntax_table);
208 }
209
210 extern ptrdiff_t scan_words (ptrdiff_t, EMACS_INT);
211 extern void RE_SETUP_SYNTAX_TABLE_FOR_OBJECT (Lisp_Object, ptrdiff_t);
212
213 INLINE_HEADER_END
214
215 #endif /* EMACS_SYNTAX_H */