1 /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
2 Copyright (C) 1985, 1987 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
28 Lisp_Object Qsyntax_table_p
;
30 int words_include_escapes
;
32 DEFUN ("syntax-table-p", Fsyntax_table_p
, Ssyntax_table_p
, 1, 1, 0,
33 "Return t if ARG is a syntax table.\n\
34 Any vector of 256 elements will do.")
38 if (XTYPE (obj
) == Lisp_Vector
&& XVECTOR (obj
)->size
== 0400)
44 check_syntax_table (obj
)
47 register Lisp_Object tem
;
48 while (tem
= Fsyntax_table_p (obj
),
50 obj
= wrong_type_argument (Qsyntax_table_p
, obj
, 0);
55 DEFUN ("syntax-table", Fsyntax_table
, Ssyntax_table
, 0, 0, 0,
56 "Return the current syntax table.\n\
57 This is the one specified by the current buffer.")
60 return current_buffer
->syntax_table
;
63 DEFUN ("standard-syntax-table", Fstandard_syntax_table
,
64 Sstandard_syntax_table
, 0, 0, 0,
65 "Return the standard syntax table.\n\
66 This is the one used for new buffers.")
69 return Vstandard_syntax_table
;
72 DEFUN ("copy-syntax-table", Fcopy_syntax_table
, Scopy_syntax_table
, 0, 1, 0,
73 "Construct a new syntax table and return it.\n\
74 It is a copy of the TABLE, which defaults to the standard syntax table.")
78 Lisp_Object size
, val
;
79 XFASTINT (size
) = 0400;
81 val
= Fmake_vector (size
, val
);
83 table
= check_syntax_table (table
);
84 else if (NILP (Vstandard_syntax_table
))
85 /* Can only be null during initialization */
87 else table
= Vstandard_syntax_table
;
89 bcopy (XVECTOR (table
)->contents
,
90 XVECTOR (val
)->contents
, 0400 * sizeof (Lisp_Object
));
94 DEFUN ("set-syntax-table", Fset_syntax_table
, Sset_syntax_table
, 1, 1, 0,
95 "Select a new syntax table for the current buffer.\n\
96 One argument, a syntax table.")
100 table
= check_syntax_table (table
);
101 current_buffer
->syntax_table
= table
;
102 /* Indicate that this buffer now has a specified syntax table. */
103 current_buffer
->local_var_flags
|= buffer_local_flags
.syntax_table
;
107 /* Convert a letter which signifies a syntax code
108 into the code it signifies.
109 This is used by modify-syntax-entry, and other things. */
111 unsigned char syntax_spec_code
[0400] =
112 { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
113 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
114 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
115 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
116 (char) Swhitespace
, 0377, (char) Sstring
, 0377,
117 (char) Smath
, 0377, 0377, (char) Squote
,
118 (char) Sopen
, (char) Sclose
, 0377, 0377,
119 0377, (char) Swhitespace
, (char) Spunct
, (char) Scharquote
,
120 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
121 0377, 0377, 0377, 0377,
122 (char) Scomment
, 0377, (char) Sendcomment
, 0377,
123 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A, ... */
124 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
125 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword
,
126 0377, 0377, 0377, 0377, (char) Sescape
, 0377, 0377, (char) Ssymbol
,
127 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */
128 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
129 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword
,
130 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377
133 /* Indexed by syntax code, give the letter that describes it. */
135 char syntax_code_spec
[13] =
137 ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>'
140 DEFUN ("char-syntax", Fchar_syntax
, Schar_syntax
, 1, 1, 0,
141 "Return the syntax code of CHAR, described by a character.\n\
142 For example, if CHAR is a word constituent, the character `?w' is returned.\n\
143 The characters that correspond to various syntax codes\n\
144 are listed in the documentation of `modify-syntax-entry'.")
148 CHECK_NUMBER (ch
, 0);
149 return make_number (syntax_code_spec
[(int) SYNTAX (0xFF & XINT (ch
))]);
152 /* This comment supplies the doc string for modify-syntax-entry,
153 for make-docfile to see. We cannot put this in the real DEFUN
154 due to limits in the Unix cpp.
156 DEFUN ("modify-syntax-entry", foo, bar, 0, 0, 0,
157 "Set syntax for character CHAR according to string S.\n\
158 The syntax is changed only for table TABLE, which defaults to\n\
159 the current buffer's syntax table.\n\
160 The first character of S should be one of the following:\n\
161 Space whitespace syntax. w word constituent.\n\
162 _ symbol constituent. . punctuation.\n\
163 ( open-parenthesis. ) close-parenthesis.\n\
164 \" string quote. \\ character-quote.\n\
165 $ paired delimiter. ' expression quote or prefix operator.\n\
166 < comment starter. > comment ender.\n\
167 Only single-character comment start and end sequences are represented thus.\n\
168 Two-character sequences are represented as described below.\n\
169 The second character of S is the matching parenthesis,\n\
170 used only if the first character is `(' or `)'.\n\
171 Any additional characters are flags.\n\
172 Defined flags are the characters 1, 2, 3, 4, and p.\n\
173 1 means C is the start of a two-char comment start sequence.\n\
174 2 means C is the second character of such a sequence.\n\
175 3 means C is the start of a two-char comment end sequence.\n\
176 4 means C is the second character of such a sequence.\n\
177 p means C is a prefix character for `backward-prefix-chars';
178 such characters are treated as whitespace when they occur
179 between expressions.")
183 DEFUN ("modify-syntax-entry", Fmodify_syntax_entry
, Smodify_syntax_entry
, 2, 3,
184 /* I really don't know why this is interactive
185 help-form should at least be made useful whilst reading the second arg
187 "cSet syntax for character: \nsSet syntax for %s to: ",
188 0 /* See immediately above */)
189 (c
, newentry
, syntax_table
)
190 Lisp_Object c
, newentry
, syntax_table
;
192 register unsigned char *p
, match
;
193 register enum syntaxcode code
;
197 CHECK_STRING (newentry
, 1);
198 if (NILP (syntax_table
))
199 syntax_table
= current_buffer
->syntax_table
;
201 syntax_table
= check_syntax_table (syntax_table
);
203 p
= XSTRING (newentry
)->data
;
204 code
= (enum syntaxcode
) syntax_spec_code
[*p
++];
205 if (((int) code
& 0377) == 0377)
206 error ("invalid syntax description letter: %c", c
);
210 if (match
== ' ') match
= 0;
212 XFASTINT (val
) = (match
<< 8) + (int) code
;
217 XFASTINT (val
) |= 1 << 16;
221 XFASTINT (val
) |= 1 << 17;
225 XFASTINT (val
) |= 1 << 18;
229 XFASTINT (val
) |= 1 << 19;
233 XFASTINT (val
) |= 1 << 20;
237 XVECTOR (syntax_table
)->contents
[0xFF & XINT (c
)] = val
;
242 /* Dump syntax table to buffer in human-readable format */
244 describe_syntax (value
)
247 register enum syntaxcode code
;
248 char desc
, match
, start1
, start2
, end1
, end2
, prefix
;
251 Findent_to (make_number (16), make_number (1));
253 if (XTYPE (value
) != Lisp_Int
)
255 insert_string ("invalid");
259 code
= (enum syntaxcode
) (XINT (value
) & 0377);
260 match
= (XINT (value
) >> 8) & 0377;
261 start1
= (XINT (value
) >> 16) & 1;
262 start2
= (XINT (value
) >> 17) & 1;
263 end1
= (XINT (value
) >> 18) & 1;
264 end2
= (XINT (value
) >> 19) & 1;
265 prefix
= (XINT (value
) >> 20) & 1;
267 if ((int) code
< 0 || (int) code
>= (int) Smax
)
269 insert_string ("invalid");
272 desc
= syntax_code_spec
[(int) code
];
274 str
[0] = desc
, str
[1] = 0;
277 str
[0] = match
? match
: ' ';
294 insert_string ("\twhich means: ");
296 #ifdef SWITCH_ENUM_BUG
303 insert_string ("whitespace"); break;
305 insert_string ("punctuation"); break;
307 insert_string ("word"); break;
309 insert_string ("symbol"); break;
311 insert_string ("open"); break;
313 insert_string ("close"); break;
315 insert_string ("quote"); break;
317 insert_string ("string"); break;
319 insert_string ("math"); break;
321 insert_string ("escape"); break;
323 insert_string ("charquote"); break;
325 insert_string ("comment"); break;
327 insert_string ("endcomment"); break;
329 insert_string ("invalid");
335 insert_string (", matches ");
337 str
[0] = match
, str
[1] = 0;
342 insert_string (",\n\t is the first character of a comment-start sequence");
344 insert_string (",\n\t is the second character of a comment-start sequence");
347 insert_string (",\n\t is the first character of a comment-end sequence");
349 insert_string (",\n\t is the second character of a comment-end sequence");
351 insert_string (",\n\t is a prefix character for `backward-prefix-chars'");
353 insert_string ("\n");
357 describe_syntax_1 (vector
)
360 struct buffer
*old
= current_buffer
;
361 set_buffer_internal (XBUFFER (Vstandard_output
));
362 describe_vector (vector
, Qnil
, describe_syntax
, 0, Qnil
, Qnil
);
363 set_buffer_internal (old
);
367 DEFUN ("describe-syntax", Fdescribe_syntax
, Sdescribe_syntax
, 0, 0, "",
368 "Describe the syntax specifications in the syntax table.\n\
369 The descriptions are inserted in a buffer, which is then displayed.")
372 internal_with_output_to_temp_buffer
373 ("*Help*", describe_syntax_1
, current_buffer
->syntax_table
);
378 /* Return the position across COUNT words from FROM.
379 If that many words cannot be found before the end of the buffer, return 0.
380 COUNT negative means scan backward and stop at word beginning. */
382 scan_words (from
, count
)
383 register int from
, count
;
385 register int beg
= BEGV
;
386 register int end
= ZV
;
401 code
= SYNTAX (FETCH_CHAR (from
));
402 if (words_include_escapes
403 && (code
== Sescape
|| code
== Scharquote
))
411 if (from
== end
) break;
412 code
= SYNTAX (FETCH_CHAR (from
));
413 if (!(words_include_escapes
414 && (code
== Sescape
|| code
== Scharquote
)))
430 code
= SYNTAX (FETCH_CHAR (from
- 1));
431 if (words_include_escapes
432 && (code
== Sescape
|| code
== Scharquote
))
440 if (from
== beg
) break;
441 code
= SYNTAX (FETCH_CHAR (from
- 1));
442 if (!(words_include_escapes
443 && (code
== Sescape
|| code
== Scharquote
)))
456 DEFUN ("forward-word", Fforward_word
, Sforward_word
, 1, 1, "p",
457 "Move point forward ARG words (backward if ARG is negative).\n\
458 Normally returns t.\n\
459 If an edge of the buffer is reached, point is left there\n\
460 and nil is returned.")
465 CHECK_NUMBER (count
, 0);
467 if (!(val
= scan_words (point
, XINT (count
))))
469 SET_PT (XINT (count
) > 0 ? ZV
: BEGV
);
476 int parse_sexp_ignore_comments
;
479 scan_lists (from
, count
, depth
, sexpflag
)
481 int count
, depth
, sexpflag
;
489 register enum syntaxcode code
;
490 int min_depth
= depth
; /* Err out if depth gets less than this. */
492 if (depth
> 0) min_depth
= 0;
502 c
= FETCH_CHAR (from
);
505 if (from
< stop
&& SYNTAX_COMSTART_FIRST (c
)
506 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from
))
507 && parse_sexp_ignore_comments
)
508 code
= Scomment
, from
++;
509 if (SYNTAX_PREFIX (c
))
512 #ifdef SWITCH_ENUM_BUG
520 if (from
== stop
) goto lose
;
522 /* treat following character as a word constituent */
525 if (depth
|| !sexpflag
) break;
526 /* This word counts as a sexp; return at end of it. */
529 #ifdef SWITCH_ENUM_BUG
530 switch ((int) SYNTAX(FETCH_CHAR (from
)))
532 switch (SYNTAX(FETCH_CHAR (from
)))
538 if (from
== stop
) goto lose
;
552 if (!parse_sexp_ignore_comments
) break;
555 if (from
== stop
) goto done
;
556 if (SYNTAX (c
= FETCH_CHAR (from
)) == Sendcomment
)
559 if (from
< stop
&& SYNTAX_COMEND_FIRST (c
)
560 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from
)))
568 if (from
!= stop
&& c
== FETCH_CHAR (from
))
578 if (!++depth
) goto done
;
583 if (!--depth
) goto done
;
584 if (depth
< min_depth
)
585 error ("Containing expression ends prematurely");
589 stringterm
= FETCH_CHAR (from
- 1);
592 if (from
>= stop
) goto lose
;
593 if (FETCH_CHAR (from
) == stringterm
) break;
594 #ifdef SWITCH_ENUM_BUG
595 switch ((int) SYNTAX(FETCH_CHAR (from
)))
597 switch (SYNTAX(FETCH_CHAR (from
)))
607 if (!depth
&& sexpflag
) goto done
;
612 /* Reached end of buffer. Error if within object, return nil if between */
613 if (depth
) goto lose
;
618 /* End of object reached */
629 if (quoted
= char_quoted (from
))
631 c
= FETCH_CHAR (from
);
633 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
634 && SYNTAX_COMEND_FIRST (FETCH_CHAR (from
- 1))
635 && !char_quoted (from
- 1)
636 && parse_sexp_ignore_comments
)
637 code
= Sendcomment
, from
--;
638 if (SYNTAX_PREFIX (c
))
641 #ifdef SWITCH_ENUM_BUG
642 switch ((int) (quoted
? Sword
: code
))
644 switch (quoted
? Sword
: code
)
649 if (depth
|| !sexpflag
) break;
650 /* This word counts as a sexp; count object finished after passing it. */
653 quoted
= char_quoted (from
- 1);
656 if (! (quoted
|| SYNTAX(FETCH_CHAR (from
- 1)) == Sword
657 || SYNTAX(FETCH_CHAR (from
- 1)) == Ssymbol
658 || SYNTAX(FETCH_CHAR (from
- 1)) == Squote
))
667 if (from
!= stop
&& c
== FETCH_CHAR (from
- 1))
677 if (!++depth
) goto done2
;
682 if (!--depth
) goto done2
;
683 if (depth
< min_depth
)
684 error ("Containing expression ends prematurely");
688 if (!parse_sexp_ignore_comments
)
690 /* Look back, counting the parity of string-quotes,
691 and recording the comment-starters seen.
692 When we reach a safe place, assume that's not in a string;
693 then step the main scan to the earliest comment-starter seen
694 an even number of string quotes away from the safe place.
696 OFROM[I] is position of the earliest comment-starter seen
697 which is I+2X quotes from the comment-end.
698 PARITY is current parity of quotes from the comment end. */
703 ofrom
[0] = ofrom
[1] = from
;
705 /* At beginning of range to scan, we're outside of strings;
706 that determines quote parity to the comment-end. */
709 /* Move back and examine a character. */
712 c
= FETCH_CHAR (from
);
715 /* If this char is the second of a 2-char comment sequence,
716 back up and give the pair the appropriate syntax. */
717 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
718 && SYNTAX_COMEND_FIRST (FETCH_CHAR (from
- 1)))
719 code
= Sendcomment
, from
--;
720 else if (from
> stop
&& SYNTAX_COMSTART_SECOND (c
)
721 && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from
- 1)))
722 code
= Scomment
, from
--;
724 /* Ignore escaped characters. */
725 if (char_quoted (from
))
728 /* Track parity of quotes between here and comment-end. */
732 /* Record comment-starters according to that
733 quote-parity to the comment-end. */
734 if (code
== Scomment
)
735 ofrom
[parity
] = from
;
737 /* If we come to another comment-end,
738 assume it's not inside a string.
739 That determines the quote parity to the comment-end. */
740 if (code
== Sendcomment
)
743 from
= ofrom
[parity
];
748 stringterm
= FETCH_CHAR (from
);
751 if (from
== stop
) goto lose
;
752 if (!char_quoted (from
- 1)
753 && stringterm
== FETCH_CHAR (from
- 1))
758 if (!depth
&& sexpflag
) goto done2
;
763 /* Reached start of buffer. Error if within object, return nil if between */
764 if (depth
) goto lose
;
775 XFASTINT (val
) = from
;
779 error ("Unbalanced parentheses");
786 register enum syntaxcode code
;
787 register int beg
= BEGV
;
788 register int quoted
= 0;
791 && ((code
= SYNTAX (FETCH_CHAR (pos
- 1))) == Scharquote
793 pos
--, quoted
= !quoted
;
797 DEFUN ("scan-lists", Fscan_lists
, Sscan_lists
, 3, 3, 0,
798 "Scan from character number FROM by COUNT lists.\n\
799 Returns the character number of the position thus found.\n\
801 If DEPTH is nonzero, paren depth begins counting from that value,\n\
802 only places where the depth in parentheses becomes zero\n\
803 are candidates for stopping; COUNT such places are counted.\n\
804 Thus, a positive value for DEPTH means go out levels.\n\
806 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
808 If the beginning or end of (the accessible part of) the buffer is reached\n\
809 and the depth is wrong, an error is signaled.\n\
810 If the depth is right but the count is not used up, nil is returned.")
812 Lisp_Object from
, count
, depth
;
814 CHECK_NUMBER (from
, 0);
815 CHECK_NUMBER (count
, 1);
816 CHECK_NUMBER (depth
, 2);
818 return scan_lists (XINT (from
), XINT (count
), XINT (depth
), 0);
821 DEFUN ("scan-sexps", Fscan_sexps
, Sscan_sexps
, 2, 2, 0,
822 "Scan from character number FROM by COUNT balanced expressions.\n\
823 If COUNT is negative, scan backwards.\n\
824 Returns the character number of the position thus found.\n\
826 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
828 If the beginning or end of (the accessible part of) the buffer is reached\n\
829 in the middle of a parenthetical grouping, an error is signaled.\n\
830 If the beginning or end is reached between groupings\n\
831 but before count is used up, nil is returned.")
833 Lisp_Object from
, count
;
835 CHECK_NUMBER (from
, 0);
836 CHECK_NUMBER (count
, 1);
838 return scan_lists (XINT (from
), XINT (count
), 0, 1);
841 DEFUN ("backward-prefix-chars", Fbackward_prefix_chars
, Sbackward_prefix_chars
,
843 "Move point backward over any number of chars with prefix syntax.\n\
844 This includes chars with \"quote\" or \"prefix\" syntax (' or p).")
850 while (pos
> beg
&& !char_quoted (pos
- 1)
851 && (SYNTAX (FETCH_CHAR (pos
- 1)) == Squote
852 || SYNTAX_PREFIX (FETCH_CHAR (pos
- 1))))
860 struct lisp_parse_state
862 int depth
; /* Depth at end of parsing */
863 int instring
; /* -1 if not within string, else desired terminator. */
864 int incomment
; /* Nonzero if within a comment at end of parsing */
865 int quoted
; /* Nonzero if just after an escape char at end of parsing */
866 int thislevelstart
; /* Char number of most recent start-of-expression at current level */
867 int prevlevelstart
; /* Char number of start of containing expression */
868 int location
; /* Char number at which parsing stopped. */
869 int mindepth
; /* Minimum depth seen while scanning. */
872 /* Parse forward from FROM to END,
873 assuming that FROM is the start of a function,
874 and return a description of the state of the parse at END. */
876 struct lisp_parse_state val_scan_sexps_forward
;
878 struct lisp_parse_state
*
879 scan_sexps_forward (from
, end
, targetdepth
, stopbefore
, oldstate
)
881 int end
, targetdepth
, stopbefore
;
882 Lisp_Object oldstate
;
884 struct lisp_parse_state state
;
886 register enum syntaxcode code
;
887 struct level
{ int last
, prev
; };
888 struct level levelstart
[100];
889 register struct level
*curlevel
= levelstart
;
890 struct level
*endlevel
= levelstart
+ 100;
892 register int depth
; /* Paren depth of current scanning location.
893 level - levelstart equals this except
894 when the depth becomes negative. */
895 int mindepth
; /* Lowest DEPTH value seen. */
896 int start_quoted
= 0; /* Nonzero means starting after a char quote */
910 tem
= Fcar (oldstate
);
916 oldstate
= Fcdr (oldstate
);
917 oldstate
= Fcdr (oldstate
);
918 oldstate
= Fcdr (oldstate
);
919 tem
= Fcar (oldstate
);
920 state
.instring
= !NILP (tem
) ? XINT (tem
) : -1;
922 oldstate
= Fcdr (oldstate
);
923 tem
= Fcar (oldstate
);
924 state
.incomment
= !NILP (tem
);
926 oldstate
= Fcdr (oldstate
);
927 tem
= Fcar (oldstate
);
928 start_quoted
= !NILP (tem
);
936 /* Enter the loop at a place appropriate for initial state. */
938 if (state
.incomment
) goto startincomment
;
939 if (state
.instring
>= 0)
941 if (start_quoted
) goto startquotedinstring
;
944 if (start_quoted
) goto startquoted
;
948 code
= SYNTAX(FETCH_CHAR (from
));
950 if (from
< end
&& SYNTAX_COMSTART_FIRST (FETCH_CHAR (from
- 1))
951 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from
)))
952 code
= Scomment
, from
++;
953 if (SYNTAX_PREFIX (FETCH_CHAR (from
- 1)))
955 #ifdef SWITCH_ENUM_BUG
963 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
964 curlevel
->last
= from
- 1;
966 if (from
== end
) goto endquoted
;
969 /* treat following character as a word constituent */
972 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
973 curlevel
->last
= from
- 1;
977 #ifdef SWITCH_ENUM_BUG
978 switch ((int) SYNTAX(FETCH_CHAR (from
)))
980 switch (SYNTAX(FETCH_CHAR (from
)))
986 if (from
== end
) goto endquoted
;
998 curlevel
->prev
= curlevel
->last
;
1002 state
.incomment
= 1;
1006 if (from
== end
) goto done
;
1007 if (SYNTAX (prev
= FETCH_CHAR (from
)) == Sendcomment
)
1010 if (from
< end
&& SYNTAX_COMEND_FIRST (prev
)
1011 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from
)))
1014 state
.incomment
= 0;
1018 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
1020 /* curlevel++->last ran into compiler bug on Apollo */
1021 curlevel
->last
= from
- 1;
1022 if (++curlevel
== endlevel
)
1023 error ("Nesting too deep for parser");
1024 curlevel
->prev
= -1;
1025 curlevel
->last
= -1;
1026 if (!--targetdepth
) goto done
;
1031 if (depth
< mindepth
)
1033 if (curlevel
!= levelstart
)
1035 curlevel
->prev
= curlevel
->last
;
1036 if (!++targetdepth
) goto done
;
1040 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
1041 curlevel
->last
= from
- 1;
1042 state
.instring
= FETCH_CHAR (from
- 1);
1046 if (from
>= end
) goto done
;
1047 if (FETCH_CHAR (from
) == state
.instring
) break;
1048 #ifdef SWITCH_ENUM_BUG
1049 switch ((int) SYNTAX(FETCH_CHAR (from
)))
1051 switch (SYNTAX(FETCH_CHAR (from
)))
1057 startquotedinstring
:
1058 if (from
>= end
) goto endquoted
;
1062 state
.instring
= -1;
1063 curlevel
->prev
= curlevel
->last
;
1073 stop
: /* Here if stopping before start of sexp. */
1074 from
--; /* We have just fetched the char that starts it; */
1075 goto done
; /* but return the position before it. */
1080 state
.depth
= depth
;
1081 state
.mindepth
= mindepth
;
1082 state
.thislevelstart
= curlevel
->prev
;
1083 state
.prevlevelstart
1084 = (curlevel
== levelstart
) ? -1 : (curlevel
- 1)->last
;
1085 state
.location
= from
;
1088 val_scan_sexps_forward
= state
;
1089 return &val_scan_sexps_forward
;
1092 /* This comment supplies the doc string for parse-partial-sexp,
1093 for make-docfile to see. We cannot put this in the real DEFUN
1094 due to limits in the Unix cpp.
1096 DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 0, 0, 0,
1097 "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\
1098 Parsing stops at TO or when certain criteria are met;\n\
1099 point is set to where parsing stops.\n\
1100 If fifth arg STATE is omitted or nil,\n\
1101 parsing assumes that FROM is the beginning of a function.\n\
1102 Value is a list of seven elements describing final state of parsing:\n\
1103 1. depth in parens.\n\
1104 2. character address of start of innermost containing list; nil if none.\n\
1105 3. character address of start of last complete sexp terminated.\n\
1106 4. non-nil if inside a string.\n\
1107 (it is the character that will terminate the string.)\n\
1108 5. t if inside a comment.\n\
1109 6. t if following a quote character.\n\
1110 7. the minimum paren-depth encountered during this scan.\n\
1111 If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
1112 in parentheses becomes equal to TARGETDEPTH.\n\
1113 Fourth arg STOPBEFORE non-nil means stop when come to\n\
1114 any character that starts a sexp.\n\
1115 Fifth arg STATE is a seven-list like what this function returns.\n\
1116 It is used to initialize the state of the parse.")
1120 DEFUN ("parse-partial-sexp", Fparse_partial_sexp
, Sparse_partial_sexp
, 2, 5, 0,
1121 0 /* See immediately above */)
1122 (from
, to
, targetdepth
, stopbefore
, oldstate
)
1123 Lisp_Object from
, to
, targetdepth
, stopbefore
, oldstate
;
1125 struct lisp_parse_state state
;
1128 if (!NILP (targetdepth
))
1130 CHECK_NUMBER (targetdepth
, 3);
1131 target
= XINT (targetdepth
);
1134 target
= -100000; /* We won't reach this depth */
1136 validate_region (&from
, &to
);
1137 state
= *scan_sexps_forward (XINT (from
), XINT (to
),
1138 target
, !NILP (stopbefore
), oldstate
);
1140 SET_PT (state
.location
);
1142 return Fcons (make_number (state
.depth
),
1143 Fcons (state
.prevlevelstart
< 0 ? Qnil
: make_number (state
.prevlevelstart
),
1144 Fcons (state
.thislevelstart
< 0 ? Qnil
: make_number (state
.thislevelstart
),
1145 Fcons (state
.instring
>= 0 ? make_number (state
.instring
) : Qnil
,
1146 Fcons (state
.incomment
? Qt
: Qnil
,
1147 Fcons (state
.quoted
? Qt
: Qnil
,
1148 Fcons (make_number (state
.mindepth
), Qnil
)))))));
1154 register struct Lisp_Vector
*v
;
1156 /* Set this now, so first buffer creation can refer to it. */
1157 /* Make it nil before calling copy-syntax-table
1158 so that copy-syntax-table will know not to try to copy from garbage */
1159 Vstandard_syntax_table
= Qnil
;
1160 Vstandard_syntax_table
= Fcopy_syntax_table (Qnil
);
1162 v
= XVECTOR (Vstandard_syntax_table
);
1164 for (i
= 'a'; i
<= 'z'; i
++)
1165 XFASTINT (v
->contents
[i
]) = (int) Sword
;
1166 for (i
= 'A'; i
<= 'Z'; i
++)
1167 XFASTINT (v
->contents
[i
]) = (int) Sword
;
1168 for (i
= '0'; i
<= '9'; i
++)
1169 XFASTINT (v
->contents
[i
]) = (int) Sword
;
1170 XFASTINT (v
->contents
['$']) = (int) Sword
;
1171 XFASTINT (v
->contents
['%']) = (int) Sword
;
1173 XFASTINT (v
->contents
['(']) = (int) Sopen
+ (')' << 8);
1174 XFASTINT (v
->contents
[')']) = (int) Sclose
+ ('(' << 8);
1175 XFASTINT (v
->contents
['[']) = (int) Sopen
+ (']' << 8);
1176 XFASTINT (v
->contents
[']']) = (int) Sclose
+ ('[' << 8);
1177 XFASTINT (v
->contents
['{']) = (int) Sopen
+ ('}' << 8);
1178 XFASTINT (v
->contents
['}']) = (int) Sclose
+ ('{' << 8);
1179 XFASTINT (v
->contents
['"']) = (int) Sstring
;
1180 XFASTINT (v
->contents
['\\']) = (int) Sescape
;
1182 for (i
= 0; i
< 10; i
++)
1183 XFASTINT (v
->contents
["_-+*/&|<>="[i
]]) = (int) Ssymbol
;
1185 for (i
= 0; i
< 12; i
++)
1186 XFASTINT (v
->contents
[".,;:?!#@~^'`"[i
]]) = (int) Spunct
;
1191 Qsyntax_table_p
= intern ("syntax-table-p");
1192 staticpro (&Qsyntax_table_p
);
1194 DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments
,
1195 "Non-nil means `forward-sexp', etc., should treat comments as whitespace.");
1197 words_include_escapes
= 0;
1198 DEFVAR_BOOL ("words-include-escapes", &words_include_escapes
,
1199 "Non-nil means `forward-word', etc., should treat escape chars part of words.");
1201 defsubr (&Ssyntax_table_p
);
1202 defsubr (&Ssyntax_table
);
1203 defsubr (&Sstandard_syntax_table
);
1204 defsubr (&Scopy_syntax_table
);
1205 defsubr (&Sset_syntax_table
);
1206 defsubr (&Schar_syntax
);
1207 defsubr (&Smodify_syntax_entry
);
1208 defsubr (&Sdescribe_syntax
);
1210 defsubr (&Sforward_word
);
1212 defsubr (&Sscan_lists
);
1213 defsubr (&Sscan_sexps
);
1214 defsubr (&Sbackward_prefix_chars
);
1215 defsubr (&Sparse_partial_sexp
);