Author: Gianluca Guida <glguida@tlbflush.org>
Date: Mon Mar 6 22:44:25 UTC 2017
Parent: 9f4695494f545832955ea255fe101a6636bd9efa
Log message:
lac: remove bison, use lemon parser.
1: diff --git a/Makefile.am b/Makefile.am
2: index 1ff611a..bde7397 100644
3: --- a/Makefile.am
4: +++ b/Makefile.am
5: @@ -1,2 +1,3 @@
6: SUBDIRS= src examples
7:
8: +EXTRA_DIST= tools/lemon.c
9: diff --git a/Makefile.in b/Makefile.in
10: index e241962..585cd4e 100644
11: --- a/Makefile.in
12: +++ b/Makefile.in
13: @@ -89,11 +89,12 @@ build_triplet = @build@
14: host_triplet = @host@
15: subdir = .
16: ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
17: -am__aclocal_m4_deps = $(top_srcdir)/m4/lib-ld.m4 \
18: - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
19: - $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/libtool.m4 \
20: - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
21: - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
22: +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_prog_flex.m4 \
23: + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
24: + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \
25: + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
26: + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
27: + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
28: $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/std-gnu11.m4 \
29: $(top_srcdir)/configure.ac
30: am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
31: @@ -165,7 +166,8 @@ CSCOPE = cscope
32: DIST_SUBDIRS = $(SUBDIRS)
33: am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \
34: COPYING ChangeLog INSTALL NEWS README TODO config.guess \
35: - config.rpath config.sub install-sh ltmain.sh missing ylwrap
36: + config.rpath config.sub depcomp install-sh ltmain.sh missing \
37: + ylwrap
38: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
39: distdir = $(PACKAGE)-$(VERSION)
40: top_distdir = $(distdir)
41: @@ -219,8 +221,6 @@ AUTOMAKE = @AUTOMAKE@
42: AWK = @AWK@
43: BDW_GC_CFLAGS = @BDW_GC_CFLAGS@
44: BDW_GC_LIBS = @BDW_GC_LIBS@
45: -BISON = @BISON@
46: -BISON_VERSION = @BISON_VERSION@
47: CC = @CC@
48: CCDEPMODE = @CCDEPMODE@
49: CFLAGS = @CFLAGS@
50: @@ -343,6 +343,7 @@ top_build_prefix = @top_build_prefix@
51: top_builddir = @top_builddir@
52: top_srcdir = @top_srcdir@
53: SUBDIRS = src examples
54: +EXTRA_DIST = tools/lemon.c
55: all: config.h
56: $(MAKE) $(AM_MAKEFLAGS) all-recursive
57:
58: diff --git a/aclocal.m4 b/aclocal.m4
59: index d8c5be4..1c39afb 100644
60: --- a/aclocal.m4
61: +++ b/aclocal.m4
62: @@ -20,529 +20,6 @@ You have another version of autoconf. It may work, but is not guaranteed to.
63: If you have problems, you may need to regenerate the build system entirely.
64: To do so, use the procedure documented by the package, typically 'autoreconf'.])])
65:
66: -# ===========================================================================
67: -# http://www.gnu.org/software/autoconf-archive/ax_compare_version.html
68: -# ===========================================================================
69: -#
70: -# SYNOPSIS
71: -#
72: -# AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
73: -#
74: -# DESCRIPTION
75: -#
76: -# This macro compares two version strings. Due to the various number of
77: -# minor-version numbers that can exist, and the fact that string
78: -# comparisons are not compatible with numeric comparisons, this is not
79: -# necessarily trivial to do in a autoconf script. This macro makes doing
80: -# these comparisons easy.
81: -#
82: -# The six basic comparisons are available, as well as checking equality
83: -# limited to a certain number of minor-version levels.
84: -#
85: -# The operator OP determines what type of comparison to do, and can be one
86: -# of:
87: -#
88: -# eq - equal (test A == B)
89: -# ne - not equal (test A != B)
90: -# le - less than or equal (test A <= B)
91: -# ge - greater than or equal (test A >= B)
92: -# lt - less than (test A < B)
93: -# gt - greater than (test A > B)
94: -#
95: -# Additionally, the eq and ne operator can have a number after it to limit
96: -# the test to that number of minor versions.
97: -#
98: -# eq0 - equal up to the length of the shorter version
99: -# ne0 - not equal up to the length of the shorter version
100: -# eqN - equal up to N sub-version levels
101: -# neN - not equal up to N sub-version levels
102: -#
103: -# When the condition is true, shell commands ACTION-IF-TRUE are run,
104: -# otherwise shell commands ACTION-IF-FALSE are run. The environment
105: -# variable 'ax_compare_version' is always set to either 'true' or 'false'
106: -# as well.
107: -#
108: -# Examples:
109: -#
110: -# AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])
111: -# AX_COMPARE_VERSION([3.15],[lt],[3.15.8])
112: -#
113: -# would both be true.
114: -#
115: -# AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])
116: -# AX_COMPARE_VERSION([3.15],[gt],[3.15.8])
117: -#
118: -# would both be false.
119: -#
120: -# AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])
121: -#
122: -# would be true because it is only comparing two minor versions.
123: -#
124: -# AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])
125: -#
126: -# would be true because it is only comparing the lesser number of minor
127: -# versions of the two values.
128: -#
129: -# Note: The characters that separate the version numbers do not matter. An
130: -# empty string is the same as version 0. OP is evaluated by autoconf, not
131: -# configure, so must be a string, not a variable.
132: -#
133: -# The author would like to acknowledge Guido Draheim whose advice about
134: -# the m4_case and m4_ifvaln functions make this macro only include the
135: -# portions necessary to perform the specific comparison specified by the
136: -# OP argument in the final configure script.
137: -#
138: -# LICENSE
139: -#
140: -# Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>
141: -#
142: -# Copying and distribution of this file, with or without modification, are
143: -# permitted in any medium without royalty provided the copyright notice
144: -# and this notice are preserved. This file is offered as-is, without any
145: -# warranty.
146: -
147: -#serial 11
148: -
149: -dnl #########################################################################
150: -AC_DEFUN([AX_COMPARE_VERSION], [
151: - AC_REQUIRE([AC_PROG_AWK])
152: -
153: - # Used to indicate true or false condition
154: - ax_compare_version=false
155: -
156: - # Convert the two version strings to be compared into a format that
157: - # allows a simple string comparison. The end result is that a version
158: - # string of the form 1.12.5-r617 will be converted to the form
159: - # 0001001200050617. In other words, each number is zero padded to four
160: - # digits, and non digits are removed.
161: - AS_VAR_PUSHDEF([A],[ax_compare_version_A])
162: - A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
163: - -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
164: - -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
165: - -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
166: - -e 's/[[^0-9]]//g'`
167: -
168: - AS_VAR_PUSHDEF([B],[ax_compare_version_B])
169: - B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
170: - -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
171: - -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
172: - -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
173: - -e 's/[[^0-9]]//g'`
174: -
175: - dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
176: - dnl # then the first line is used to determine if the condition is true.
177: - dnl # The sed right after the echo is to remove any indented white space.
178: - m4_case(m4_tolower($2),
179: - [lt],[
180: - ax_compare_version=`echo "x$A
181: -x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
182: - ],
183: - [gt],[
184: - ax_compare_version=`echo "x$A
185: -x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
186: - ],
187: - [le],[
188: - ax_compare_version=`echo "x$A
189: -x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
190: - ],
191: - [ge],[
192: - ax_compare_version=`echo "x$A
193: -x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
194: - ],[
195: - dnl Split the operator from the subversion count if present.
196: - m4_bmatch(m4_substr($2,2),
197: - [0],[
198: - # A count of zero means use the length of the shorter version.
199: - # Determine the number of characters in A and B.
200: - ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'`
201: - ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'`
202: -
203: - # Set A to no more than B's length and B to no more than A's length.
204: - A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
205: - B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
206: - ],
207: - [[0-9]+],[
208: - # A count greater than zero means use only that many subversions
209: - A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
210: - B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
211: - ],
212: - [.+],[
213: - AC_WARNING(
214: - [illegal OP numeric parameter: $2])
215: - ],[])
216: -
217: - # Pad zeros at end of numbers to make same length.
218: - ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
219: - B="$B`echo $A | sed 's/./0/g'`"
220: - A="$ax_compare_version_tmp_A"
221: -
222: - # Check for equality or inequality as necessary.
223: - m4_case(m4_tolower(m4_substr($2,0,2)),
224: - [eq],[
225: - test "x$A" = "x$B" && ax_compare_version=true
226: - ],
227: - [ne],[
228: - test "x$A" != "x$B" && ax_compare_version=true
229: - ],[
230: - AC_WARNING([illegal OP parameter: $2])
231: - ])
232: - ])
233: -
234: - AS_VAR_POPDEF([A])dnl
235: - AS_VAR_POPDEF([B])dnl
236: -
237: - dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
238: - if test "$ax_compare_version" = "true" ; then
239: - m4_ifvaln([$4],[$4],[:])dnl
240: - m4_ifvaln([$5],[else $5])dnl
241: - fi
242: -]) dnl AX_COMPARE_VERSION
243: -
244: -# ===========================================================================
245: -# http://www.gnu.org/software/autoconf-archive/ax_prog_bison_version.html
246: -# ===========================================================================
247: -#
248: -# SYNOPSIS
249: -#
250: -# AX_PROG_BISON_VERSION([VERSION],[ACTION-IF-TRUE],[ACTION-IF-FALSE])
251: -#
252: -# DESCRIPTION
253: -#
254: -# Makes sure that bison version is greater or equal to the version
255: -# indicated. If true the shell commands in ACTION-IF-TRUE are executed. If
256: -# not the shell commands in commands in ACTION-IF-TRUE are executed. If
257: -# not the shell commands in ACTION-IF-FALSE are run. Note if $BISON is not
258: -# set (for example by running AC_CHECK_PROG or AC_PATH_PROG) the macro
259: -# will fail.
260: -#
261: -# Example:
262: -#
263: -# AC_PATH_PROG([BISON],[bison])
264: -# AX_PROG_BISON_VERSION([3.0.2],[ ... ],[ ... ])
265: -#
266: -# This will check to make sure that the bison you have is at least version
267: -# 3.0.2 or greater.
268: -#
269: -# NOTE: This macro uses the $BISON variable to perform the check.
270: -#
271: -# LICENSE
272: -#
273: -# Copyright (c) 2015 Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
274: -#
275: -# Copying and distribution of this file, with or without modification, are
276: -# permitted in any medium without royalty provided the copyright notice
277: -# and this notice are preserved. This file is offered as-is, without any
278: -# warranty.
279: -
280: -#serial 2
281: -
282: -AC_DEFUN([AX_PROG_BISON_VERSION],[
283: - AC_REQUIRE([AC_PROG_SED])
284: - AC_REQUIRE([AC_PROG_GREP])
285: -
286: - AS_IF([test -n "$BISON"],[
287: - ax_bison_version="$1"
288: -
289: - AC_MSG_CHECKING([for bison version])
290: - changequote(<<,>>)
291: - bison_version=`$BISON --version 2>&1 \
292: - | $SED -n -e '/bison (GNU Bison)/b inspect
293: -b
294: -: inspect
295: -s/.* (\{0,1\}\([0-9]*\.[0-9]*\.[0-9]*\))\{0,1\}.*/\1/;p'`
296: - changequote([,])
297: - AC_MSG_RESULT($bison_version)
298: -
299: - AC_SUBST([BISON_VERSION],[$bison_version])
300: -
301: - AX_COMPARE_VERSION([$bison_version],[ge],[$ax_bison_version],[
302: - :
303: - $2
304: - ],[
305: - :
306: - $3
307: - ])
308: - ],[
309: - AC_MSG_WARN([could not find bison])
310: - $3
311: - ])
312: -])
313: -
314: -# ===========================================================================
315: -# http://www.gnu.org/software/autoconf-archive/ax_prog_flex.html
316: -# ===========================================================================
317: -#
318: -# SYNOPSIS
319: -#
320: -# AX_PROG_FLEX(ACTION-IF-TRUE,ACTION-IF-FALSE)
321: -#
322: -# DESCRIPTION
323: -#
324: -# Check whether flex is the scanner generator. Run ACTION-IF-TRUE if
325: -# successful, ACTION-IF-FALSE otherwise
326: -#
327: -# LICENSE
328: -#
329: -# Copyright (c) 2009 Francesco Salvestrini <salvestrini@users.sourceforge.net>
330: -# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
331: -#
332: -# This program is free software; you can redistribute it and/or modify it
333: -# under the terms of the GNU General Public License as published by the
334: -# Free Software Foundation; either version 2 of the License, or (at your
335: -# option) any later version.
336: -#
337: -# This program is distributed in the hope that it will be useful, but
338: -# WITHOUT ANY WARRANTY; without even the implied warranty of
339: -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
340: -# Public License for more details.
341: -#
342: -# You should have received a copy of the GNU General Public License along
343: -# with this program. If not, see <http://www.gnu.org/licenses/>.
344: -#
345: -# As a special exception, the respective Autoconf Macro's copyright owner
346: -# gives unlimited permission to copy, distribute and modify the configure
347: -# scripts that are the output of Autoconf when processing the Macro. You
348: -# need not follow the terms of the GNU General Public License when using
349: -# or distributing such scripts, even though portions of the text of the
350: -# Macro appear in them. The GNU General Public License (GPL) does govern
351: -# all other use of the material that constitutes the Autoconf Macro.
352: -#
353: -# This special exception to the GPL applies to versions of the Autoconf
354: -# Macro released by the Autoconf Archive. When you make and distribute a
355: -# modified version of the Autoconf Macro, you may extend this special
356: -# exception to the GPL to apply to your modified version as well.
357: -
358: -#serial 12
359: -
360: -AC_DEFUN([AX_PROG_FLEX], [
361: - AC_REQUIRE([AM_PROG_LEX])
362: - AC_REQUIRE([AC_PROG_EGREP])
363: -
364: - AC_CACHE_CHECK([if flex is the lexer generator],[ax_cv_prog_flex],[
365: - AS_IF([$LEX --version 2>/dev/null | $EGREP -qw '^g?flex'],
366: - [ax_cv_prog_flex=yes], [ax_cv_prog_flex=no])
367: - ])
368: - AS_IF([test "$ax_cv_prog_flex" = "yes"],
369: - m4_ifnblank([$1], [[$1]]),
370: - m4_ifnblank([$2], [[$2]])
371: - )
372: -])
373: -
374: -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
375: -# serial 1 (pkg-config-0.24)
376: -#
377: -# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
378: -#
379: -# This program is free software; you can redistribute it and/or modify
380: -# it under the terms of the GNU General Public License as published by
381: -# the Free Software Foundation; either version 2 of the License, or
382: -# (at your option) any later version.
383: -#
384: -# This program is distributed in the hope that it will be useful, but
385: -# WITHOUT ANY WARRANTY; without even the implied warranty of
386: -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
387: -# General Public License for more details.
388: -#
389: -# You should have received a copy of the GNU General Public License
390: -# along with this program; if not, write to the Free Software
391: -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
392: -#
393: -# As a special exception to the GNU General Public License, if you
394: -# distribute this file as part of a program that contains a
395: -# configuration script generated by Autoconf, you may include it under
396: -# the same distribution terms that you use for the rest of that program.
397: -
398: -# PKG_PROG_PKG_CONFIG([MIN-VERSION])
399: -# ----------------------------------
400: -AC_DEFUN([PKG_PROG_PKG_CONFIG],
401: -[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
402: -m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
403: -m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
404: -AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
405: -AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
406: -AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
407: -
408: -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
409: - AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
410: -fi
411: -if test -n "$PKG_CONFIG"; then
412: - _pkg_min_version=m4_default([$1], [0.9.0])
413: - AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
414: - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
415: - AC_MSG_RESULT([yes])
416: - else
417: - AC_MSG_RESULT([no])
418: - PKG_CONFIG=""
419: - fi
420: -fi[]dnl
421: -])# PKG_PROG_PKG_CONFIG
422: -
423: -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
424: -#
425: -# Check to see whether a particular set of modules exists. Similar
426: -# to PKG_CHECK_MODULES(), but does not set variables or print errors.
427: -#
428: -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
429: -# only at the first occurence in configure.ac, so if the first place
430: -# it's called might be skipped (such as if it is within an "if", you
431: -# have to call PKG_CHECK_EXISTS manually
432: -# --------------------------------------------------------------
433: -AC_DEFUN([PKG_CHECK_EXISTS],
434: -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
435: -if test -n "$PKG_CONFIG" && \
436: - AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
437: - m4_default([$2], [:])
438: -m4_ifvaln([$3], [else
439: - $3])dnl
440: -fi])
441: -
442: -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
443: -# ---------------------------------------------
444: -m4_define([_PKG_CONFIG],
445: -[if test -n "$$1"; then
446: - pkg_cv_[]$1="$$1"
447: - elif test -n "$PKG_CONFIG"; then
448: - PKG_CHECK_EXISTS([$3],
449: - [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
450: - test "x$?" != "x0" && pkg_failed=yes ],
451: - [pkg_failed=yes])
452: - else
453: - pkg_failed=untried
454: -fi[]dnl
455: -])# _PKG_CONFIG
456: -
457: -# _PKG_SHORT_ERRORS_SUPPORTED
458: -# -----------------------------
459: -AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
460: -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
461: -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
462: - _pkg_short_errors_supported=yes
463: -else
464: - _pkg_short_errors_supported=no
465: -fi[]dnl
466: -])# _PKG_SHORT_ERRORS_SUPPORTED
467: -
468: -
469: -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
470: -# [ACTION-IF-NOT-FOUND])
471: -#
472: -#
473: -# Note that if there is a possibility the first call to
474: -# PKG_CHECK_MODULES might not happen, you should be sure to include an
475: -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
476: -#
477: -#
478: -# --------------------------------------------------------------
479: -AC_DEFUN([PKG_CHECK_MODULES],
480: -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
481: -AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
482: -AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
483: -
484: -pkg_failed=no
485: -AC_MSG_CHECKING([for $1])
486: -
487: -_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
488: -_PKG_CONFIG([$1][_LIBS], [libs], [$2])
489: -
490: -m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
491: -and $1[]_LIBS to avoid the need to call pkg-config.
492: -See the pkg-config man page for more details.])
493: -
494: -if test $pkg_failed = yes; then
495: - AC_MSG_RESULT([no])
496: - _PKG_SHORT_ERRORS_SUPPORTED
497: - if test $_pkg_short_errors_supported = yes; then
498: - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
499: - else
500: - $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
501: - fi
502: - # Put the nasty error message in config.log where it belongs
503: - echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
504: -
505: - m4_default([$4], [AC_MSG_ERROR(
506: -[Package requirements ($2) were not met:
507: -
508: -$$1_PKG_ERRORS
509: -
510: -Consider adjusting the PKG_CONFIG_PATH environment variable if you
511: -installed software in a non-standard prefix.
512: -
513: -_PKG_TEXT])[]dnl
514: - ])
515: -elif test $pkg_failed = untried; then
516: - AC_MSG_RESULT([no])
517: - m4_default([$4], [AC_MSG_FAILURE(
518: -[The pkg-config script could not be found or is too old. Make sure it
519: -is in your PATH or set the PKG_CONFIG environment variable to the full
520: -path to pkg-config.
521: -
522: -_PKG_TEXT
523: -
524: -To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
525: - ])
526: -else
527: - $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
528: - $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
529: - AC_MSG_RESULT([yes])
530: - $3
531: -fi[]dnl
532: -])# PKG_CHECK_MODULES
533: -
534: -
535: -# PKG_INSTALLDIR(DIRECTORY)
536: -# -------------------------
537: -# Substitutes the variable pkgconfigdir as the location where a module
538: -# should install pkg-config .pc files. By default the directory is
539: -# $libdir/pkgconfig, but the default can be changed by passing
540: -# DIRECTORY. The user can override through the --with-pkgconfigdir
541: -# parameter.
542: -AC_DEFUN([PKG_INSTALLDIR],
543: -[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
544: -m4_pushdef([pkg_description],
545: - [pkg-config installation directory @<:@]pkg_default[@:>@])
546: -AC_ARG_WITH([pkgconfigdir],
547: - [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
548: - [with_pkgconfigdir=]pkg_default)
549: -AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
550: -m4_popdef([pkg_default])
551: -m4_popdef([pkg_description])
552: -]) dnl PKG_INSTALLDIR
553: -
554: -
555: -# PKG_NOARCH_INSTALLDIR(DIRECTORY)
556: -# -------------------------
557: -# Substitutes the variable noarch_pkgconfigdir as the location where a
558: -# module should install arch-independent pkg-config .pc files. By
559: -# default the directory is $datadir/pkgconfig, but the default can be
560: -# changed by passing DIRECTORY. The user can override through the
561: -# --with-noarch-pkgconfigdir parameter.
562: -AC_DEFUN([PKG_NOARCH_INSTALLDIR],
563: -[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
564: -m4_pushdef([pkg_description],
565: - [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
566: -AC_ARG_WITH([noarch-pkgconfigdir],
567: - [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
568: - [with_noarch_pkgconfigdir=]pkg_default)
569: -AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
570: -m4_popdef([pkg_default])
571: -m4_popdef([pkg_description])
572: -]) dnl PKG_NOARCH_INSTALLDIR
573: -
574: -
575: -# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
576: -# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
577: -# -------------------------------------------
578: -# Retrieves the value of the pkg-config variable for the given module.
579: -AC_DEFUN([PKG_CHECK_VAR],
580: -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
581: -AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
582: -
583: -_PKG_CONFIG([$1], [variable="][$3]["], [$2])
584: -AS_VAR_COPY([$1], [pkg_cv_][$1])
585: -
586: -AS_VAR_IF([$1], [""], [$5], [$4])dnl
587: -])# PKG_CHECK_VAR
588: -
589: # Copyright (C) 2002-2014 Free Software Foundation, Inc.
590: #
591: # This file is free software; the Free Software Foundation
592: @@ -1627,6 +1104,7 @@ AC_SUBST([am__tar])
593: AC_SUBST([am__untar])
594: ]) # _AM_PROG_TAR
595:
596: +m4_include([m4/ax_prog_flex.m4])
597: m4_include([m4/lib-ld.m4])
598: m4_include([m4/lib-link.m4])
599: m4_include([m4/lib-prefix.m4])
600: @@ -1636,5 +1114,6 @@ m4_include([m4/ltoptions.m4])
601: m4_include([m4/ltsugar.m4])
602: m4_include([m4/ltversion.m4])
603: m4_include([m4/lt~obsolete.m4])
604: +m4_include([m4/pkg.m4])
605: m4_include([m4/readline.m4])
606: m4_include([m4/std-gnu11.m4])
607: diff --git a/configure b/configure
608: index 514000d..76e36e2 100755
609: --- a/configure
610: +++ b/configure
611: @@ -653,6 +653,7 @@ ac_ct_DUMPBIN
612: DUMPBIN
613: LD
614: FGREP
615: +SED
616: LIBTOOL
617: LIBOBJS
618: ALLOCA
619: @@ -679,13 +680,10 @@ PKG_CONFIG
620: YFLAGS
621: YACC
622: EGREP
623: +GREP
624: LEXLIB
625: LEX_OUTPUT_ROOT
626: LEX
627: -BISON_VERSION
628: -GREP
629: -SED
630: -BISON
631: am__fastdepCC_FALSE
632: am__fastdepCC_TRUE
633: CCDEPMODE
634: @@ -4422,252 +4420,6 @@ fi
635:
636:
637:
638: -# Extract the first word of "bison", so it can be a program name with args.
639: -set dummy bison; ac_word=$2
640: -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
641: -$as_echo_n "checking for $ac_word... " >&6; }
642: -if ${ac_cv_path_BISON+:} false; then :
643: - $as_echo_n "(cached) " >&6
644: -else
645: - case $BISON in
646: - [\\/]* | ?:[\\/]*)
647: - ac_cv_path_BISON="$BISON" # Let the user override the test with a path.
648: - ;;
649: - *)
650: - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
651: -for as_dir in $PATH
652: -do
653: - IFS=$as_save_IFS
654: - test -z "$as_dir" && as_dir=.
655: - for ac_exec_ext in '' $ac_executable_extensions; do
656: - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
657: - ac_cv_path_BISON="$as_dir/$ac_word$ac_exec_ext"
658: - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
659: - break 2
660: - fi
661: -done
662: - done
663: -IFS=$as_save_IFS
664: -
665: - ;;
666: -esac
667: -fi
668: -BISON=$ac_cv_path_BISON
669: -if test -n "$BISON"; then
670: - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BISON" >&5
671: -$as_echo "$BISON" >&6; }
672: -else
673: - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
674: -$as_echo "no" >&6; }
675: -fi
676: -
677: -
678: -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
679: -$as_echo_n "checking for a sed that does not truncate output... " >&6; }
680: -if ${ac_cv_path_SED+:} false; then :
681: - $as_echo_n "(cached) " >&6
682: -else
683: - ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
684: - for ac_i in 1 2 3 4 5 6 7; do
685: - ac_script="$ac_script$as_nl$ac_script"
686: - done
687: - echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
688: - { ac_script=; unset ac_script;}
689: - if test -z "$SED"; then
690: - ac_path_SED_found=false
691: - # Loop through the user's path and test for each of PROGNAME-LIST
692: - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
693: -for as_dir in $PATH
694: -do
695: - IFS=$as_save_IFS
696: - test -z "$as_dir" && as_dir=.
697: - for ac_prog in sed gsed; do
698: - for ac_exec_ext in '' $ac_executable_extensions; do
699: - ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
700: - as_fn_executable_p "$ac_path_SED" || continue
701: -# Check for GNU ac_path_SED and select it if it is found.
702: - # Check for GNU $ac_path_SED
703: -case `"$ac_path_SED" --version 2>&1` in
704: -*GNU*)
705: - ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
706: -*)
707: - ac_count=0
708: - $as_echo_n 0123456789 >"conftest.in"
709: - while :
710: - do
711: - cat "conftest.in" "conftest.in" >"conftest.tmp"
712: - mv "conftest.tmp" "conftest.in"
713: - cp "conftest.in" "conftest.nl"
714: - $as_echo '' >> "conftest.nl"
715: - "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
716: - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
717: - as_fn_arith $ac_count + 1 && ac_count=$as_val
718: - if test $ac_count -gt ${ac_path_SED_max-0}; then
719: - # Best one so far, save it but keep looking for a better one
720: - ac_cv_path_SED="$ac_path_SED"
721: - ac_path_SED_max=$ac_count
722: - fi
723: - # 10*(2^10) chars as input seems more than enough
724: - test $ac_count -gt 10 && break
725: - done
726: - rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
727: -esac
728: -
729: - $ac_path_SED_found && break 3
730: - done
731: - done
732: - done
733: -IFS=$as_save_IFS
734: - if test -z "$ac_cv_path_SED"; then
735: - as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
736: - fi
737: -else
738: - ac_cv_path_SED=$SED
739: -fi
740: -
741: -fi
742: -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
743: -$as_echo "$ac_cv_path_SED" >&6; }
744: - SED="$ac_cv_path_SED"
745: - rm -f conftest.sed
746: -
747: -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
748: -$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
749: -if ${ac_cv_path_GREP+:} false; then :
750: - $as_echo_n "(cached) " >&6
751: -else
752: - if test -z "$GREP"; then
753: - ac_path_GREP_found=false
754: - # Loop through the user's path and test for each of PROGNAME-LIST
755: - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
756: -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
757: -do
758: - IFS=$as_save_IFS
759: - test -z "$as_dir" && as_dir=.
760: - for ac_prog in grep ggrep; do
761: - for ac_exec_ext in '' $ac_executable_extensions; do
762: - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
763: - as_fn_executable_p "$ac_path_GREP" || continue
764: -# Check for GNU ac_path_GREP and select it if it is found.
765: - # Check for GNU $ac_path_GREP
766: -case `"$ac_path_GREP" --version 2>&1` in
767: -*GNU*)
768: - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
769: -*)
770: - ac_count=0
771: - $as_echo_n 0123456789 >"conftest.in"
772: - while :
773: - do
774: - cat "conftest.in" "conftest.in" >"conftest.tmp"
775: - mv "conftest.tmp" "conftest.in"
776: - cp "conftest.in" "conftest.nl"
777: - $as_echo 'GREP' >> "conftest.nl"
778: - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
779: - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
780: - as_fn_arith $ac_count + 1 && ac_count=$as_val
781: - if test $ac_count -gt ${ac_path_GREP_max-0}; then
782: - # Best one so far, save it but keep looking for a better one
783: - ac_cv_path_GREP="$ac_path_GREP"
784: - ac_path_GREP_max=$ac_count
785: - fi
786: - # 10*(2^10) chars as input seems more than enough
787: - test $ac_count -gt 10 && break
788: - done
789: - rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
790: -esac
791: -
792: - $ac_path_GREP_found && break 3
793: - done
794: - done
795: - done
796: -IFS=$as_save_IFS
797: - if test -z "$ac_cv_path_GREP"; then
798: - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
799: - fi
800: -else
801: - ac_cv_path_GREP=$GREP
802: -fi
803: -
804: -fi
805: -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
806: -$as_echo "$ac_cv_path_GREP" >&6; }
807: - GREP="$ac_cv_path_GREP"
808: -
809: -
810: -
811: -
812: -
813: -
814: - if test -n "$BISON"; then :
815: -
816: - ax_bison_version="3.0"
817: -
818: - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bison version" >&5
819: -$as_echo_n "checking for bison version... " >&6; }
820: -
821: - bison_version=`$BISON --version 2>&1 \
822: - | $SED -n -e '/bison (GNU Bison)/b inspect
823: -b
824: -: inspect
825: -s/.* (\{0,1\}\([0-9]*\.[0-9]*\.[0-9]*\))\{0,1\}.*/\1/;p'`
826: -
827: - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $bison_version" >&5
828: -$as_echo "$bison_version" >&6; }
829: -
830: - BISON_VERSION=$bison_version
831: -
832: -
833: -
834: -
835: -
836: - # Used to indicate true or false condition
837: - ax_compare_version=false
838: -
839: - # Convert the two version strings to be compared into a format that
840: - # allows a simple string comparison. The end result is that a version
841: - # string of the form 1.12.5-r617 will be converted to the form
842: - # 0001001200050617. In other words, each number is zero padded to four
843: - # digits, and non digits are removed.
844: -
845: - ax_compare_version_A=`echo "$bison_version" | sed -e 's/\([0-9]*\)/Z\1Z/g' \
846: - -e 's/Z\([0-9]\)Z/Z0\1Z/g' \
847: - -e 's/Z\([0-9][0-9]\)Z/Z0\1Z/g' \
848: - -e 's/Z\([0-9][0-9][0-9]\)Z/Z0\1Z/g' \
849: - -e 's/[^0-9]//g'`
850: -
851: -
852: - ax_compare_version_B=`echo "$ax_bison_version" | sed -e 's/\([0-9]*\)/Z\1Z/g' \
853: - -e 's/Z\([0-9]\)Z/Z0\1Z/g' \
854: - -e 's/Z\([0-9][0-9]\)Z/Z0\1Z/g' \
855: - -e 's/Z\([0-9][0-9][0-9]\)Z/Z0\1Z/g' \
856: - -e 's/[^0-9]//g'`
857: -
858: -
859: - ax_compare_version=`echo "x$ax_compare_version_A
860: -x$ax_compare_version_B" | sed 's/^ *//' | sort -r | sed "s/x${ax_compare_version_A}/true/;s/x${ax_compare_version_B}/false/;1q"`
861: -
862: -
863: -
864: - if test "$ax_compare_version" = "true" ; then
865: -
866: - :
867: -
868: -
869: - else
870: - :
871: - as_fn_error $? "Requires bison 3.0 or later" "$LINENO" 5
872: -
873: - fi
874: -
875: -
876: -else
877: -
878: - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find bison" >&5
879: -$as_echo "$as_me: WARNING: could not find bison" >&2;}
880: - as_fn_error $? "Requires bison 3.0 or later" "$LINENO" 5
881: -
882: -fi
883: -
884:
885: for ac_prog in flex lex
886: do
887: @@ -4831,6 +4583,69 @@ fi
888: if test "$LEX" = :; then
889: LEX=${am_missing_run}flex
890: fi
891: +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
892: +$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
893: +if ${ac_cv_path_GREP+:} false; then :
894: + $as_echo_n "(cached) " >&6
895: +else
896: + if test -z "$GREP"; then
897: + ac_path_GREP_found=false
898: + # Loop through the user's path and test for each of PROGNAME-LIST
899: + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
900: +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
901: +do
902: + IFS=$as_save_IFS
903: + test -z "$as_dir" && as_dir=.
904: + for ac_prog in grep ggrep; do
905: + for ac_exec_ext in '' $ac_executable_extensions; do
906: + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
907: + as_fn_executable_p "$ac_path_GREP" || continue
908: +# Check for GNU ac_path_GREP and select it if it is found.
909: + # Check for GNU $ac_path_GREP
910: +case `"$ac_path_GREP" --version 2>&1` in
911: +*GNU*)
912: + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
913: +*)
914: + ac_count=0
915: + $as_echo_n 0123456789 >"conftest.in"
916: + while :
917: + do
918: + cat "conftest.in" "conftest.in" >"conftest.tmp"
919: + mv "conftest.tmp" "conftest.in"
920: + cp "conftest.in" "conftest.nl"
921: + $as_echo 'GREP' >> "conftest.nl"
922: + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
923: + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
924: + as_fn_arith $ac_count + 1 && ac_count=$as_val
925: + if test $ac_count -gt ${ac_path_GREP_max-0}; then
926: + # Best one so far, save it but keep looking for a better one
927: + ac_cv_path_GREP="$ac_path_GREP"
928: + ac_path_GREP_max=$ac_count
929: + fi
930: + # 10*(2^10) chars as input seems more than enough
931: + test $ac_count -gt 10 && break
932: + done
933: + rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
934: +esac
935: +
936: + $ac_path_GREP_found && break 3
937: + done
938: + done
939: + done
940: +IFS=$as_save_IFS
941: + if test -z "$ac_cv_path_GREP"; then
942: + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
943: + fi
944: +else
945: + ac_cv_path_GREP=$GREP
946: +fi
947: +
948: +fi
949: +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
950: +$as_echo "$ac_cv_path_GREP" >&6; }
951: + GREP="$ac_cv_path_GREP"
952: +
953: +
954: { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
955: $as_echo_n "checking for egrep... " >&6; }
956: if ${ac_cv_path_EGREP+:} false; then :
957: diff --git a/configure.ac b/configure.ac
958: index a4bfcee..fc75845 100644
959: --- a/configure.ac
960: +++ b/configure.ac
961: @@ -10,8 +10,6 @@ AC_CONFIG_MACRO_DIRS([m4])
962: # Checks for programs.
963: AC_PROG_CC
964:
965: -AC_PATH_PROG([BISON],[bison])
966: -AX_PROG_BISON_VERSION([3.0], [], AC_MSG_ERROR([Requires bison 3.0 or later]))
967: AX_PROG_FLEX([], AC_MSG_ERROR([Requires flex]))
968: AC_PROG_YACC
969: AM_PROG_LEX
970: diff --git a/examples/Makefile.in b/examples/Makefile.in
971: index 4f76f1f..ab30b5f 100644
972: --- a/examples/Makefile.in
973: +++ b/examples/Makefile.in
974: @@ -90,11 +90,12 @@ build_triplet = @build@
975: host_triplet = @host@
976: subdir = examples
977: ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
978: -am__aclocal_m4_deps = $(top_srcdir)/m4/lib-ld.m4 \
979: - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
980: - $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/libtool.m4 \
981: - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
982: - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
983: +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_prog_flex.m4 \
984: + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
985: + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \
986: + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
987: + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
988: + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
989: $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/std-gnu11.m4 \
990: $(top_srcdir)/configure.ac
991: am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
992: @@ -138,8 +139,6 @@ AUTOMAKE = @AUTOMAKE@
993: AWK = @AWK@
994: BDW_GC_CFLAGS = @BDW_GC_CFLAGS@
995: BDW_GC_LIBS = @BDW_GC_LIBS@
996: -BISON = @BISON@
997: -BISON_VERSION = @BISON_VERSION@
998: CC = @CC@
999: CCDEPMODE = @CCDEPMODE@
1000: CFLAGS = @CFLAGS@
1001: diff --git a/src/Makefile.in b/src/Makefile.in
1002: index a2c2849..1542fa0 100644
1003: --- a/src/Makefile.in
1004: +++ b/src/Makefile.in
1005: @@ -89,11 +89,12 @@ build_triplet = @build@
1006: host_triplet = @host@
1007: subdir = src
1008: ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
1009: -am__aclocal_m4_deps = $(top_srcdir)/m4/lib-ld.m4 \
1010: - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
1011: - $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/libtool.m4 \
1012: - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
1013: - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
1014: +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_prog_flex.m4 \
1015: + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
1016: + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \
1017: + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
1018: + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
1019: + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
1020: $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/std-gnu11.m4 \
1021: $(top_srcdir)/configure.ac
1022: am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
1023: @@ -196,8 +197,6 @@ AUTOMAKE = @AUTOMAKE@
1024: AWK = @AWK@
1025: BDW_GC_CFLAGS = @BDW_GC_CFLAGS@
1026: BDW_GC_LIBS = @BDW_GC_LIBS@
1027: -BISON = @BISON@
1028: -BISON_VERSION = @BISON_VERSION@
1029: CC = @CC@
1030: CCDEPMODE = @CCDEPMODE@
1031: CFLAGS = @CFLAGS@
1032: diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
1033: index b13dfe4..0ca135b 100644
1034: --- a/src/lib/Makefile.am
1035: +++ b/src/lib/Makefile.am
1036: @@ -1,8 +1,7 @@
1037: lib_LTLIBRARIES= liblac.la
1038:
1039: liblac_la_SOURCES= lac.c env.c ext_types.c map.c private.h lex.l \
1040: - sexpr_parse.y ty_int.c ty_string.c
1041: -BUILT_SOURCES= sexpr_parse.h
1042: + sexpr.c ty_int.c ty_string.c
1043: liblac_la_LIBADD= $(BDW_GC_LIBS) $(LTLIBREADLINE) $(LTLIBSIGSEGV)
1044: include_HEADERS=lac.h
1045:
1046: diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
1047: index c90b6eb..660b1ab 100644
1048: --- a/src/lib/Makefile.in
1049: +++ b/src/lib/Makefile.in
1050: @@ -92,11 +92,12 @@ build_triplet = @build@
1051: host_triplet = @host@
1052: subdir = src/lib
1053: ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
1054: -am__aclocal_m4_deps = $(top_srcdir)/m4/lib-ld.m4 \
1055: - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
1056: - $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/libtool.m4 \
1057: - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
1058: - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
1059: +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_prog_flex.m4 \
1060: + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
1061: + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \
1062: + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
1063: + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
1064: + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
1065: $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/std-gnu11.m4 \
1066: $(top_srcdir)/configure.ac
1067: am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
1068: @@ -141,7 +142,7 @@ am__DEPENDENCIES_1 =
1069: liblac_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
1070: $(am__DEPENDENCIES_1)
1071: am_liblac_la_OBJECTS = lac.lo env.lo ext_types.lo map.lo lex.lo \
1072: - sexpr_parse.lo ty_int.lo ty_string.lo
1073: + sexpr.lo ty_int.lo ty_string.lo
1074: liblac_la_OBJECTS = $(am_liblac_la_OBJECTS)
1075: AM_V_lt = $(am__v_lt_@AM_V@)
1076: am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
1077: @@ -189,15 +190,6 @@ am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
1078: am__v_LEX_0 = @echo " LEX " $@;
1079: am__v_LEX_1 =
1080: YLWRAP = $(top_srcdir)/ylwrap
1081: -am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
1082: - -e s/c++$$/h++/ -e s/c$$/h/
1083: -YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
1084: -LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
1085: - $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
1086: -AM_V_YACC = $(am__v_YACC_@AM_V@)
1087: -am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
1088: -am__v_YACC_0 = @echo " YACC " $@;
1089: -am__v_YACC_1 =
1090: SOURCES = $(liblac_la_SOURCES)
1091: DIST_SOURCES = $(liblac_la_SOURCES)
1092: am__can_run_installinfo = \
1093: @@ -227,7 +219,7 @@ am__define_uniq_tagged_files = \
1094: ETAGS = etags
1095: CTAGS = ctags
1096: am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
1097: - $(top_srcdir)/ylwrap lex.c sexpr_parse.c sexpr_parse.h
1098: + $(top_srcdir)/ylwrap lex.c
1099: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
1100: ACLOCAL = @ACLOCAL@
1101: ALLOCA = @ALLOCA@
1102: @@ -240,8 +232,6 @@ AUTOMAKE = @AUTOMAKE@
1103: AWK = @AWK@
1104: BDW_GC_CFLAGS = @BDW_GC_CFLAGS@
1105: BDW_GC_LIBS = @BDW_GC_LIBS@
1106: -BISON = @BISON@
1107: -BISON_VERSION = @BISON_VERSION@
1108: CC = @CC@
1109: CCDEPMODE = @CCDEPMODE@
1110: CFLAGS = @CFLAGS@
1111: @@ -365,20 +355,18 @@ top_builddir = @top_builddir@
1112: top_srcdir = @top_srcdir@
1113: lib_LTLIBRARIES = liblac.la
1114: liblac_la_SOURCES = lac.c env.c ext_types.c map.c private.h lex.l \
1115: - sexpr_parse.y ty_int.c ty_string.c
1116: + sexpr.c ty_int.c ty_string.c
1117:
1118: -BUILT_SOURCES = sexpr_parse.h
1119: liblac_la_LIBADD = $(BDW_GC_LIBS) $(LTLIBREADLINE) $(LTLIBSIGSEGV)
1120: include_HEADERS = lac.h
1121: lacdir = ${datadir}/@PACKAGE@
1122: dist_lac_DATA = sys.lac
1123: AM_CPPFLAGS = -DLAC_SYSDIR='"$(lacdir)"'
1124: AM_YFLAGS = -d
1125: -all: $(BUILT_SOURCES)
1126: - $(MAKE) $(AM_MAKEFLAGS) all-am
1127: +all: all-am
1128:
1129: .SUFFIXES:
1130: -.SUFFIXES: .c .l .lo .o .obj .y
1131: +.SUFFIXES: .c .l .lo .o .obj
1132: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
1133: @for dep in $?; do \
1134: case '$(am__configure_deps)' in \
1135: @@ -443,9 +431,6 @@ clean-libLTLIBRARIES:
1136: echo rm -f $${locs}; \
1137: rm -f $${locs}; \
1138: }
1139: -sexpr_parse.h: sexpr_parse.c
1140: - @if test ! -f $@; then rm -f sexpr_parse.c; else :; fi
1141: - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) sexpr_parse.c; else :; fi
1142:
1143: liblac.la: $(liblac_la_OBJECTS) $(liblac_la_DEPENDENCIES) $(EXTRA_liblac_la_DEPENDENCIES)
1144: $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(liblac_la_OBJECTS) $(liblac_la_LIBADD) $(LIBS)
1145: @@ -461,7 +446,7 @@ distclean-compile:
1146: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lac.Plo@am__quote@
1147: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lex.Plo@am__quote@
1148: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@
1149: -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sexpr_parse.Plo@am__quote@
1150: +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sexpr.Plo@am__quote@
1151: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ty_int.Plo@am__quote@
1152: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ty_string.Plo@am__quote@
1153:
1154: @@ -489,9 +474,6 @@ distclean-compile:
1155: .l.c:
1156: $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
1157:
1158: -.y.c:
1159: - $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
1160: -
1161: mostlyclean-libtool:
1162: -rm -f *.lo
1163:
1164: @@ -623,15 +605,13 @@ distdir: $(DISTFILES)
1165: fi; \
1166: done
1167: check-am: all-am
1168: -check: $(BUILT_SOURCES)
1169: - $(MAKE) $(AM_MAKEFLAGS) check-am
1170: +check: check-am
1171: all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
1172: installdirs:
1173: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(lacdir)" "$(DESTDIR)$(includedir)"; do \
1174: test -z "$$dir" || $(MKDIR_P) "$$dir"; \
1175: done
1176: -install: $(BUILT_SOURCES)
1177: - $(MAKE) $(AM_MAKEFLAGS) install-am
1178: +install: install-am
1179: install-exec: install-exec-am
1180: install-data: install-data-am
1181: uninstall: uninstall-am
1182: @@ -662,9 +642,6 @@ maintainer-clean-generic:
1183: @echo "This command is intended for maintainers to use"
1184: @echo "it deletes files that may require special tools to rebuild."
1185: -rm -f lex.c
1186: - -rm -f sexpr_parse.c
1187: - -rm -f sexpr_parse.h
1188: - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
1189: clean: clean-am
1190:
1191: clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
1192: @@ -737,7 +714,7 @@ ps-am:
1193: uninstall-am: uninstall-dist_lacDATA uninstall-includeHEADERS \
1194: uninstall-libLTLIBRARIES
1195:
1196: -.MAKE: all check install install-am install-strip
1197: +.MAKE: install-am install-strip
1198:
1199: .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
1200: clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \
1201: diff --git a/src/lib/lac.c b/src/lib/lac.c
1202: index 020e064..ab9fddc 100644
1203: --- a/src/lib/lac.c
1204: +++ b/src/lib/lac.c
1205: @@ -650,11 +650,9 @@ LAC_API static lreg_t proc_gensym(lreg_t args, lenv_t *argenv, lenv_t *env)
1206:
1207: LAC_API static lreg_t proc_load(lreg_t args, lenv_t *argenv, lenv_t *env)
1208: {
1209: - int r;
1210: FILE *f;
1211: char *file;
1212: - void *scan;
1213: - lreg_t res, arg1;
1214: + lreg_t arg1;
1215: _EXPECT_ARGS(args, 1);
1216:
1217: arg1 = ARGEVAL(car(args), argenv);
1218: @@ -666,18 +664,13 @@ LAC_API static lreg_t proc_load(lreg_t args, lenv_t *argenv, lenv_t *env)
1219: if ( f == NULL )
1220: _ERROR_AND_RET("Could not open file");
1221:
1222: - sexpr_read_start(f, &scan);
1223: lac_on_error({
1224: - sexpr_read_stop(scan);
1225: _throw(); /* rethrow */
1226: });
1227: - do {
1228: - r = sexpr_read(&res, scan);
1229: - eval(res, env);
1230: - } while(r);
1231: +
1232: + sexpr_parse_file(f, (lreg_t (*)(lreg_t, void *))eval, (void *)env);
1233:
1234: lac_off_error();
1235: - sexpr_read_stop(scan);
1236: return sym_true;
1237: }
1238:
1239: @@ -754,10 +747,7 @@ modules_init(lenv_t *env)
1240: static void
1241: library_init(lenv_t *env)
1242: {
1243: - int r;
1244: FILE *f;
1245: - lreg_t res;
1246: - void *scan;
1247:
1248: f = fopen("sys.lac", "r");
1249: if ( f == NULL )
1250: @@ -765,13 +755,7 @@ library_init(lenv_t *env)
1251: if ( f == NULL )
1252: raise_exception("SYSTEM LIBRARY NOT FOUND", NIL);
1253:
1254: - sexpr_read_start(f, &scan);
1255: - do {
1256: - r = sexpr_read(&res, scan);
1257: - eval(res, env);
1258: - } while(r);
1259: - sexpr_read_stop(scan);
1260: -
1261: + sexpr_parse_file(f, (lreg_t (*)(lreg_t, void *))eval, (void *)env);
1262: fclose(f);
1263: }
1264:
1265: diff --git a/src/lib/lac.h b/src/lib/lac.h
1266: index 4413dd3..012c293 100644
1267: --- a/src/lib/lac.h
1268: +++ b/src/lib/lac.h
1269: @@ -24,6 +24,8 @@
1270: #include <stdint.h>
1271: #include <inttypes.h>
1272:
1273: +#include <gc/gc.h>
1274: +
1275: #ifdef __GNUC__
1276: #define _noreturn __attribute__((noreturn))
1277: #else
1278: @@ -82,7 +84,7 @@ struct treg_hdr {
1279: typedef struct {
1280: char *name;
1281: void (*print)(FILE *fd, lreg_t lr);
1282: - lreg_t (*equal)(lreg_t arg1, lreg_t arg2);
1283: + int (*equal)(lreg_t arg1, lreg_t arg2);
1284: } lac_exttype_t;
1285:
1286: static inline lreg_t lreg_raw(void *ptr, unsigned type)
1287: @@ -130,7 +132,19 @@ void raise_exception(char *, lreg_t) _noreturn;
1288: lenv_t *lac_envalloc(void);
1289: lenv_t * lac_init(void);
1290: extern void *GC_malloc(size_t);
1291: -#define lac_alloc GC_malloc
1292: +
1293: +static inline void *lac_alloc(size_t size)
1294: +{
1295: + return GC_MALLOC(size);
1296: +}
1297: +
1298: +static inline void *lac_alloc_fini(size_t size,
1299: + void (*fn)(void*,void*), void *opq)
1300: +{
1301: + void *obj = GC_MALLOC(size);
1302: + GC_REGISTER_FINALIZER_IGNORE_SELF(obj, fn, opq, 0, 0);
1303: + return obj;
1304: +}
1305:
1306: struct cons
1307: {
1308: @@ -274,9 +288,8 @@ extern __thread lreg_t _lac_xcpt_reg;
1309: * Representations
1310: */
1311:
1312: -void sexpr_read_start(FILE *f, void **yyscan);
1313: -int sexpr_read(lreg_t *res, void *yyscan);
1314: -void sexpr_read_stop(void *yyscan);
1315: -void sexpr_print(FILE *f, lreg_t lr);
1316: +lreg_t sexpr_parse_string(char *s, lreg_t (*fn)(lreg_t,void*), void *opq);
1317: +lreg_t sexpr_parse_file(FILE *f, lreg_t (*fn)(lreg_t,void*), void *opq);
1318: +void sexpr_fprint(FILE *f, lreg_t lr);
1319:
1320: #endif /* LACONIC_H */
1321: diff --git a/src/lib/lex.c b/src/lib/lex.c
1322: deleted file mode 100644
1323: index 699b9eb..0000000
1324: --- a/src/lib/lex.c
1325: +++ /dev/null
1326: @@ -1,2151 +0,0 @@
1327: -
1328: -#line 3 "lex.c"
1329: -
1330: -#define YY_INT_ALIGNED short int
1331: -
1332: -/* A lexical scanner generated by flex */
1333: -
1334: -#define FLEX_SCANNER
1335: -#define YY_FLEX_MAJOR_VERSION 2
1336: -#define YY_FLEX_MINOR_VERSION 6
1337: -#define YY_FLEX_SUBMINOR_VERSION 0
1338: -#if YY_FLEX_SUBMINOR_VERSION > 0
1339: -#define FLEX_BETA
1340: -#endif
1341: -
1342: -/* First, we deal with platform-specific or compiler-specific issues. */
1343: -
1344: -/* begin standard C headers. */
1345: -#include <stdio.h>
1346: -#include <string.h>
1347: -#include <errno.h>
1348: -#include <stdlib.h>
1349: -
1350: -/* end standard C headers. */
1351: -
1352: -/* flex integer type definitions */
1353: -
1354: -#ifndef FLEXINT_H
1355: -#define FLEXINT_H
1356: -
1357: -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
1358: -
1359: -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
1360: -
1361: -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
1362: - * if you want the limit (max/min) macros for int types.
1363: - */
1364: -#ifndef __STDC_LIMIT_MACROS
1365: -#define __STDC_LIMIT_MACROS 1
1366: -#endif
1367: -
1368: -#include <inttypes.h>
1369: -typedef int8_t flex_int8_t;
1370: -typedef uint8_t flex_uint8_t;
1371: -typedef int16_t flex_int16_t;
1372: -typedef uint16_t flex_uint16_t;
1373: -typedef int32_t flex_int32_t;
1374: -typedef uint32_t flex_uint32_t;
1375: -#else
1376: -typedef signed char flex_int8_t;
1377: -typedef short int flex_int16_t;
1378: -typedef int flex_int32_t;
1379: -typedef unsigned char flex_uint8_t;
1380: -typedef unsigned short int flex_uint16_t;
1381: -typedef unsigned int flex_uint32_t;
1382: -
1383: -/* Limits of integral types. */
1384: -#ifndef INT8_MIN
1385: -#define INT8_MIN (-128)
1386: -#endif
1387: -#ifndef INT16_MIN
1388: -#define INT16_MIN (-32767-1)
1389: -#endif
1390: -#ifndef INT32_MIN
1391: -#define INT32_MIN (-2147483647-1)
1392: -#endif
1393: -#ifndef INT8_MAX
1394: -#define INT8_MAX (127)
1395: -#endif
1396: -#ifndef INT16_MAX
1397: -#define INT16_MAX (32767)
1398: -#endif
1399: -#ifndef INT32_MAX
1400: -#define INT32_MAX (2147483647)
1401: -#endif
1402: -#ifndef UINT8_MAX
1403: -#define UINT8_MAX (255U)
1404: -#endif
1405: -#ifndef UINT16_MAX
1406: -#define UINT16_MAX (65535U)
1407: -#endif
1408: -#ifndef UINT32_MAX
1409: -#define UINT32_MAX (4294967295U)
1410: -#endif
1411: -
1412: -#endif /* ! C99 */
1413: -
1414: -#endif /* ! FLEXINT_H */
1415: -
1416: -#ifdef __cplusplus
1417: -
1418: -/* The "const" storage-class-modifier is valid. */
1419: -#define YY_USE_CONST
1420: -
1421: -#else /* ! __cplusplus */
1422: -
1423: -/* C99 requires __STDC__ to be defined as 1. */
1424: -#if defined (__STDC__)
1425: -
1426: -#define YY_USE_CONST
1427: -
1428: -#endif /* defined (__STDC__) */
1429: -#endif /* ! __cplusplus */
1430: -
1431: -#ifdef YY_USE_CONST
1432: -#define yyconst const
1433: -#else
1434: -#define yyconst
1435: -#endif
1436: -
1437: -/* Returned upon end-of-file. */
1438: -#define YY_NULL 0
1439: -
1440: -/* Promotes a possibly negative, possibly signed char to an unsigned
1441: - * integer for use as an array index. If the signed char is negative,
1442: - * we want to instead treat it as an 8-bit unsigned char, hence the
1443: - * double cast.
1444: - */
1445: -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
1446: -
1447: -/* An opaque pointer. */
1448: -#ifndef YY_TYPEDEF_YY_SCANNER_T
1449: -#define YY_TYPEDEF_YY_SCANNER_T
1450: -typedef void* yyscan_t;
1451: -#endif
1452: -
1453: -/* For convenience, these vars (plus the bison vars far below)
1454: - are macros in the reentrant scanner. */
1455: -#define yyin yyg->yyin_r
1456: -#define yyout yyg->yyout_r
1457: -#define yyextra yyg->yyextra_r
1458: -#define yyleng yyg->yyleng_r
1459: -#define yytext yyg->yytext_r
1460: -#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
1461: -#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
1462: -#define yy_flex_debug yyg->yy_flex_debug_r
1463: -
1464: -/* Enter a start condition. This macro really ought to take a parameter,
1465: - * but we do it the disgusting crufty way forced on us by the ()-less
1466: - * definition of BEGIN.
1467: - */
1468: -#define BEGIN yyg->yy_start = 1 + 2 *
1469: -
1470: -/* Translate the current start state into a value that can be later handed
1471: - * to BEGIN to return to the state. The YYSTATE alias is for lex
1472: - * compatibility.
1473: - */
1474: -#define YY_START ((yyg->yy_start - 1) / 2)
1475: -#define YYSTATE YY_START
1476: -
1477: -/* Action number for EOF rule of a given start state. */
1478: -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
1479: -
1480: -/* Special action meaning "start processing a new file". */
1481: -#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
1482: -
1483: -#define YY_END_OF_BUFFER_CHAR 0
1484: -
1485: -/* Size of default input buffer. */
1486: -#ifndef YY_BUF_SIZE
1487: -#ifdef __ia64__
1488: -/* On IA-64, the buffer size is 16k, not 8k.
1489: - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
1490: - * Ditto for the __ia64__ case accordingly.
1491: - */
1492: -#define YY_BUF_SIZE 32768
1493: -#else
1494: -#define YY_BUF_SIZE 16384
1495: -#endif /* __ia64__ */
1496: -#endif
1497: -
1498: -/* The state buf must be large enough to hold one state per character in the main buffer.
1499: - */
1500: -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
1501: -
1502: -#ifndef YY_TYPEDEF_YY_BUFFER_STATE
1503: -#define YY_TYPEDEF_YY_BUFFER_STATE
1504: -typedef struct yy_buffer_state *YY_BUFFER_STATE;
1505: -#endif
1506: -
1507: -#ifndef YY_TYPEDEF_YY_SIZE_T
1508: -#define YY_TYPEDEF_YY_SIZE_T
1509: -typedef size_t yy_size_t;
1510: -#endif
1511: -
1512: -#define EOB_ACT_CONTINUE_SCAN 0
1513: -#define EOB_ACT_END_OF_FILE 1
1514: -#define EOB_ACT_LAST_MATCH 2
1515: -
1516: - #define YY_LESS_LINENO(n)
1517: - #define YY_LINENO_REWIND_TO(ptr)
1518: -
1519: -/* Return all but the first "n" matched characters back to the input stream. */
1520: -#define yyless(n) \
1521: - do \
1522: - { \
1523: - /* Undo effects of setting up yytext. */ \
1524: - yy_size_t yyless_macro_arg = (n); \
1525: - YY_LESS_LINENO(yyless_macro_arg);\
1526: - *yy_cp = yyg->yy_hold_char; \
1527: - YY_RESTORE_YY_MORE_OFFSET \
1528: - yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
1529: - YY_DO_BEFORE_ACTION; /* set up yytext again */ \
1530: - } \
1531: - while ( 0 )
1532: -
1533: -#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
1534: -
1535: -#ifndef YY_STRUCT_YY_BUFFER_STATE
1536: -#define YY_STRUCT_YY_BUFFER_STATE
1537: -struct yy_buffer_state
1538: - {
1539: - FILE *yy_input_file;
1540: -
1541: - char *yy_ch_buf; /* input buffer */
1542: - char *yy_buf_pos; /* current position in input buffer */
1543: -
1544: - /* Size of input buffer in bytes, not including room for EOB
1545: - * characters.
1546: - */
1547: - yy_size_t yy_buf_size;
1548: -
1549: - /* Number of characters read into yy_ch_buf, not including EOB
1550: - * characters.
1551: - */
1552: - yy_size_t yy_n_chars;
1553: -
1554: - /* Whether we "own" the buffer - i.e., we know we created it,
1555: - * and can realloc() it to grow it, and should free() it to
1556: - * delete it.
1557: - */
1558: - int yy_is_our_buffer;
1559: -
1560: - /* Whether this is an "interactive" input source; if so, and
1561: - * if we're using stdio for input, then we want to use getc()
1562: - * instead of fread(), to make sure we stop fetching input after
1563: - * each newline.
1564: - */
1565: - int yy_is_interactive;
1566: -
1567: - /* Whether we're considered to be at the beginning of a line.
1568: - * If so, '^' rules will be active on the next match, otherwise
1569: - * not.
1570: - */
1571: - int yy_at_bol;
1572: -
1573: - int yy_bs_lineno; /**< The line count. */
1574: - int yy_bs_column; /**< The column count. */
1575: -
1576: - /* Whether to try to fill the input buffer when we reach the
1577: - * end of it.
1578: - */
1579: - int yy_fill_buffer;
1580: -
1581: - int yy_buffer_status;
1582: -
1583: -#define YY_BUFFER_NEW 0
1584: -#define YY_BUFFER_NORMAL 1
1585: - /* When an EOF's been seen but there's still some text to process
1586: - * then we mark the buffer as YY_EOF_PENDING, to indicate that we
1587: - * shouldn't try reading from the input source any more. We might
1588: - * still have a bunch of tokens to match, though, because of
1589: - * possible backing-up.
1590: - *
1591: - * When we actually see the EOF, we change the status to "new"
1592: - * (via yyrestart()), so that the user can continue scanning by
1593: - * just pointing yyin at a new input file.
1594: - */
1595: -#define YY_BUFFER_EOF_PENDING 2
1596: -
1597: - };
1598: -#endif /* !YY_STRUCT_YY_BUFFER_STATE */
1599: -
1600: -/* We provide macros for accessing buffer states in case in the
1601: - * future we want to put the buffer states in a more general
1602: - * "scanner state".
1603: - *
1604: - * Returns the top of the stack, or NULL.
1605: - */
1606: -#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
1607: - ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
1608: - : NULL)
1609: -
1610: -/* Same as previous macro, but useful when we know that the buffer stack is not
1611: - * NULL or when we need an lvalue. For internal use only.
1612: - */
1613: -#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
1614: -
1615: -void yyrestart (FILE *input_file ,yyscan_t yyscanner );
1616: -void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
1617: -YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
1618: -void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
1619: -void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
1620: -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
1621: -void yypop_buffer_state (yyscan_t yyscanner );
1622: -
1623: -static void yyensure_buffer_stack (yyscan_t yyscanner );
1624: -static void yy_load_buffer_state (yyscan_t yyscanner );
1625: -static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
1626: -
1627: -#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
1628: -
1629: -YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
1630: -YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
1631: -YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
1632: -
1633: -void *yyalloc (yy_size_t ,yyscan_t yyscanner );
1634: -void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
1635: -void yyfree (void * ,yyscan_t yyscanner );
1636: -
1637: -#define yy_new_buffer yy_create_buffer
1638: -
1639: -#define yy_set_interactive(is_interactive) \
1640: - { \
1641: - if ( ! YY_CURRENT_BUFFER ){ \
1642: - yyensure_buffer_stack (yyscanner); \
1643: - YY_CURRENT_BUFFER_LVALUE = \
1644: - yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
1645: - } \
1646: - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
1647: - }
1648: -
1649: -#define yy_set_bol(at_bol) \
1650: - { \
1651: - if ( ! YY_CURRENT_BUFFER ){\
1652: - yyensure_buffer_stack (yyscanner); \
1653: - YY_CURRENT_BUFFER_LVALUE = \
1654: - yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
1655: - } \
1656: - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
1657: - }
1658: -
1659: -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
1660: -
1661: -/* Begin user sect3 */
1662: -
1663: -#define yywrap(yyscanner) (/*CONSTCOND*/1)
1664: -#define YY_SKIP_YYWRAP
1665: -
1666: -typedef unsigned char YY_CHAR;
1667: -
1668: -typedef int yy_state_type;
1669: -
1670: -#define yytext_ptr yytext_r
1671: -
1672: -static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
1673: -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
1674: -static int yy_get_next_buffer (yyscan_t yyscanner );
1675: -#if defined(__GNUC__) && __GNUC__ >= 3
1676: -__attribute__((__noreturn__))
1677: -#endif
1678: -static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
1679: -
1680: -/* Done after the current pattern has been matched and before the
1681: - * corresponding action - sets up yytext.
1682: - */
1683: -#define YY_DO_BEFORE_ACTION \
1684: - yyg->yytext_ptr = yy_bp; \
1685: - yyleng = (size_t) (yy_cp - yy_bp); \
1686: - yyg->yy_hold_char = *yy_cp; \
1687: - *yy_cp = '\0'; \
1688: - yyg->yy_c_buf_p = yy_cp;
1689: -
1690: -#define YY_NUM_RULES 10
1691: -#define YY_END_OF_BUFFER 11
1692: -/* This struct is not used in this scanner,
1693: - but its presence is necessary. */
1694: -struct yy_trans_info
1695: - {
1696: - flex_int32_t yy_verify;
1697: - flex_int32_t yy_nxt;
1698: - };
1699: -static yyconst flex_int16_t yy_accept[34] =
1700: - { 0,
1701: - 0, 0, 11, 9, 2, 2, 7, 9, 7, 7,
1702: - 9, 3, 3, 1, 7, 7, 9, 7, 0, 6,
1703: - 7, 3, 8, 7, 3, 7, 1, 7, 7, 3,
1704: - 4, 5, 0
1705: - } ;
1706: -
1707: -static yyconst YY_CHAR yy_ec[256] =
1708: - { 0,
1709: - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1710: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1711: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1712: - 1, 2, 4, 5, 6, 4, 4, 4, 1, 1,
1713: - 1, 4, 7, 8, 7, 9, 4, 10, 11, 11,
1714: - 11, 11, 11, 11, 11, 11, 11, 4, 12, 4,
1715: - 4, 4, 4, 13, 14, 14, 14, 14, 14, 14,
1716: - 15, 15, 16, 15, 15, 17, 15, 18, 15, 15,
1717: - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
1718: - 1, 1, 1, 4, 4, 1, 14, 14, 14, 14,
1719: -
1720: - 14, 14, 15, 15, 19, 15, 15, 20, 15, 21,
1721: - 15, 15, 15, 15, 15, 15, 15, 15, 15, 22,
1722: - 15, 15, 1, 23, 1, 4, 1, 1, 1, 1,
1723: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1724: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1725: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1726: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1727: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1728: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1729: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1730: -
1731: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1732: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1733: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1734: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1735: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1736: - 1, 1, 1, 1, 1
1737: - } ;
1738: -
1739: -static yyconst YY_CHAR yy_meta[24] =
1740: - { 0,
1741: - 1, 1, 2, 3, 1, 1, 3, 3, 3, 3,
1742: - 3, 1, 1, 3, 3, 3, 3, 3, 3, 3,
1743: - 3, 3, 1
1744: - } ;
1745: -
1746: -static yyconst flex_uint16_t yy_base[38] =
1747: - { 0,
1748: - 0, 0, 57, 58, 58, 58, 0, 51, 33, 14,
1749: - 41, 16, 18, 0, 37, 33, 20, 0, 46, 58,
1750: - 22, 24, 58, 0, 29, 0, 0, 33, 29, 31,
1751: - 0, 0, 58, 44, 42, 34, 45
1752: - } ;
1753: -
1754: -static yyconst flex_int16_t yy_def[38] =
1755: - { 0,
1756: - 33, 1, 33, 33, 33, 33, 34, 35, 34, 34,
1757: - 33, 36, 36, 37, 34, 34, 33, 34, 35, 33,
1758: - 34, 34, 33, 34, 36, 21, 37, 34, 34, 33,
1759: - 21, 34, 0, 33, 33, 33, 33
1760: - } ;
1761: -
1762: -static yyconst flex_uint16_t yy_nxt[82] =
1763: - { 0,
1764: - 4, 5, 6, 7, 8, 9, 10, 11, 4, 12,
1765: - 13, 14, 4, 7, 7, 7, 7, 15, 7, 7,
1766: - 16, 7, 17, 22, 22, 25, 25, 25, 25, 30,
1767: - 30, 31, 31, 22, 22, 31, 24, 26, 25, 25,
1768: - 30, 30, 19, 19, 19, 27, 18, 27, 32, 32,
1769: - 20, 29, 28, 23, 21, 20, 33, 3, 33, 33,
1770: - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
1771: - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
1772: - 33
1773: - } ;
1774: -
1775: -static yyconst flex_int16_t yy_chk[82] =
1776: - { 0,
1777: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1778: - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1779: - 1, 1, 1, 10, 10, 12, 12, 13, 13, 17,
1780: - 17, 21, 21, 22, 22, 21, 36, 12, 25, 25,
1781: - 30, 30, 35, 35, 35, 37, 34, 37, 29, 28,
1782: - 19, 16, 15, 11, 9, 8, 3, 33, 33, 33,
1783: - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
1784: - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
1785: - 33
1786: - } ;
1787: -
1788: -/* The intent behind this definition is that it'll catch
1789: - * any uses of REJECT which flex missed.
1790: - */
1791: -#define REJECT reject_used_but_not_detected
1792: -#define yymore() yymore_used_but_not_detected
1793: -#define YY_MORE_ADJ 0
1794: -#define YY_RESTORE_YY_MORE_OFFSET
1795: -#line 1 "lex.l"
1796: -/*
1797: - lac -- a lisp interpreter
1798: - Copyright (C) 2010 Gianluca Guida
1799: -
1800: - This program is free software; you can redistribute it and/or modify
1801: - it under the terms of the GNU General Public License as published by
1802: - the Free Software Foundation; either version 2 of the License, or
1803: - (at your option) any later version.
1804: -
1805: - This program is distributed in the hope that it will be useful,
1806: - but WITHOUT ANY WARRANTY; without even the implied warranty of
1807: - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1808: - GNU General Public License for more details.
1809: -
1810: - You should have received a copy of the GNU General Public License along
1811: - with this program; if not, write to the Free Software Foundation, Inc.,
1812: - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1813: -*/
1814: -#line 21 "lex.l"
1815: -#define YYSTYPE lreg_t
1816: -#define YY_DECL int yylex(YYSTYPE *lvalp,void *yyscanner)
1817: -#define YY_NO_INPUT
1818: -#include <ctype.h>
1819: -#include <strings.h>
1820: -
1821: -#include "config.h"
1822: -#include "lac.h"
1823: -#include "sexpr_parse.h"
1824: -
1825: -
1826: -#ifdef HAVE_READLINE
1827: -#ifdef HAVE_READLINE_READLINE_H
1828: -#include <readline/readline.h>
1829: -#else
1830: -#include <readline.h>
1831: -#endif
1832: -#ifdef HAVE_READLINE_HISTORY_H
1833: -#include <readline/history.h>
1834: -#else
1835: -#include <history.h>
1836: -#endif
1837: -
1838: -static int readline_getc(void)
1839: -{
1840: - static int curchar = 0;
1841: - static char *buf = NULL;
1842: -
1843: - /* First run */
1844: - if ( buf == NULL ) {
1845: - buf = readline("LAC>");
1846: - if ( buf != NULL && *buf != '\0' )
1847: - add_history(buf);
1848: - curchar = 0;
1849: - }
1850: -
1851: - if ( buf == NULL )
1852: - return EOF;
1853: - if ( buf[curchar] == '\0' ) {
1854: - free(buf);
1855: - buf = NULL;
1856: - return '\n';
1857: - }
1858: -
1859: - return buf[curchar++];
1860: -}
1861: -
1862: -#else
1863: -#define readline_getc() getchar()
1864: -#endif
1865: -
1866: -#define YY_INPUT(buf,result,max_size) \
1867: - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
1868: - { \
1869: - int c = '*'; \
1870: - size_t n; \
1871: - for ( n = 0; n < max_size && \
1872: - (c = readline_getc())!=EOF && c!='\n'; ++n ) \
1873: - buf[n] = (char) c; \
1874: - if ( c == '\n' ) \
1875: - buf[n++] = (char) c; \
1876: - if ( c == EOF && ferror( yyin ) ) \
1877: - YY_FATAL_ERROR( "input in flex scanner failed" ); \
1878: - result = n; \
1879: - } \
1880: - else \
1881: - { \
1882: - errno=0; \
1883: - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
1884: - { \
1885: - if( errno != EINTR) \
1886: - { \
1887: - YY_FATAL_ERROR( "input in flex scanner failed" ); \
1888: - break; \
1889: - } \
1890: - errno=0; \
1891: - clearerr(yyin); \
1892: - } \
1893: - }\
1894: -
1895: -#line 570 "lex.c"
1896: -
1897: -#define INITIAL 0
1898: -
1899: -#ifndef YY_NO_UNISTD_H
1900: -/* Special case for "unistd.h", since it is non-ANSI. We include it way
1901: - * down here because we want the user's section 1 to have been scanned first.
1902: - * The user has a chance to override it with an option.
1903: - */
1904: -#include <unistd.h>
1905: -#endif
1906: -
1907: -#ifndef YY_EXTRA_TYPE
1908: -#define YY_EXTRA_TYPE void *
1909: -#endif
1910: -
1911: -/* Holds the entire state of the reentrant scanner. */
1912: -struct yyguts_t
1913: - {
1914: -
1915: - /* User-defined. Not touched by flex. */
1916: - YY_EXTRA_TYPE yyextra_r;
1917: -
1918: - /* The rest are the same as the globals declared in the non-reentrant scanner. */
1919: - FILE *yyin_r, *yyout_r;
1920: - size_t yy_buffer_stack_top; /**< index of top of stack. */
1921: - size_t yy_buffer_stack_max; /**< capacity of stack. */
1922: - YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
1923: - char yy_hold_char;
1924: - yy_size_t yy_n_chars;
1925: - yy_size_t yyleng_r;
1926: - char *yy_c_buf_p;
1927: - int yy_init;
1928: - int yy_start;
1929: - int yy_did_buffer_switch_on_eof;
1930: - int yy_start_stack_ptr;
1931: - int yy_start_stack_depth;
1932: - int *yy_start_stack;
1933: - yy_state_type yy_last_accepting_state;
1934: - char* yy_last_accepting_cpos;
1935: -
1936: - int yylineno_r;
1937: - int yy_flex_debug_r;
1938: -
1939: - char *yytext_r;
1940: - int yy_more_flag;
1941: - int yy_more_len;
1942: -
1943: - }; /* end struct yyguts_t */
1944: -
1945: -static int yy_init_globals (yyscan_t yyscanner );
1946: -
1947: -int yylex_init (yyscan_t* scanner);
1948: -
1949: -int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
1950: -
1951: -/* Accessor methods to globals.
1952: - These are made visible to non-reentrant scanners for convenience. */
1953: -
1954: -int yylex_destroy (yyscan_t yyscanner );
1955: -
1956: -int yyget_debug (yyscan_t yyscanner );
1957: -
1958: -void yyset_debug (int debug_flag ,yyscan_t yyscanner );
1959: -
1960: -YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
1961: -
1962: -void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
1963: -
1964: -FILE *yyget_in (yyscan_t yyscanner );
1965: -
1966: -void yyset_in (FILE * _in_str ,yyscan_t yyscanner );
1967: -
1968: -FILE *yyget_out (yyscan_t yyscanner );
1969: -
1970: -void yyset_out (FILE * _out_str ,yyscan_t yyscanner );
1971: -
1972: -yy_size_t yyget_leng (yyscan_t yyscanner );
1973: -
1974: -char *yyget_text (yyscan_t yyscanner );
1975: -
1976: -int yyget_lineno (yyscan_t yyscanner );
1977: -
1978: -void yyset_lineno (int _line_number ,yyscan_t yyscanner );
1979: -
1980: -int yyget_column (yyscan_t yyscanner );
1981: -
1982: -void yyset_column (int _column_no ,yyscan_t yyscanner );
1983: -
1984: -/* Macros after this point can all be overridden by user definitions in
1985: - * section 1.
1986: - */
1987: -
1988: -#ifndef YY_SKIP_YYWRAP
1989: -#ifdef __cplusplus
1990: -extern "C" int yywrap (yyscan_t yyscanner );
1991: -#else
1992: -extern int yywrap (yyscan_t yyscanner );
1993: -#endif
1994: -#endif
1995: -
1996: -#ifndef YY_NO_UNPUT
1997: -
1998: - static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
1999: -
2000: -#endif
2001: -
2002: -#ifndef yytext_ptr
2003: -static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
2004: -#endif
2005: -
2006: -#ifdef YY_NEED_STRLEN
2007: -static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
2008: -#endif
2009: -
2010: -#ifndef YY_NO_INPUT
2011: -
2012: -#ifdef __cplusplus
2013: -static int yyinput (yyscan_t yyscanner );
2014: -#else
2015: -static int input (yyscan_t yyscanner );
2016: -#endif
2017: -
2018: -#endif
2019: -
2020: -/* Amount of stuff to slurp up with each read. */
2021: -#ifndef YY_READ_BUF_SIZE
2022: -#ifdef __ia64__
2023: -/* On IA-64, the buffer size is 16k, not 8k */
2024: -#define YY_READ_BUF_SIZE 16384
2025: -#else
2026: -#define YY_READ_BUF_SIZE 8192
2027: -#endif /* __ia64__ */
2028: -#endif
2029: -
2030: -/* Copy whatever the last rule matched to the standard output. */
2031: -#ifndef ECHO
2032: -/* This used to be an fputs(), but since the string might contain NUL's,
2033: - * we now use fwrite().
2034: - */
2035: -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
2036: -#endif
2037: -
2038: -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
2039: - * is returned in "result".
2040: - */
2041: -#ifndef YY_INPUT
2042: -#define YY_INPUT(buf,result,max_size) \
2043: - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
2044: - { \
2045: - int c = '*'; \
2046: - size_t n; \
2047: - for ( n = 0; n < max_size && \
2048: - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
2049: - buf[n] = (char) c; \
2050: - if ( c == '\n' ) \
2051: - buf[n++] = (char) c; \
2052: - if ( c == EOF && ferror( yyin ) ) \
2053: - YY_FATAL_ERROR( "input in flex scanner failed" ); \
2054: - result = n; \
2055: - } \
2056: - else \
2057: - { \
2058: - errno=0; \
2059: - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
2060: - { \
2061: - if( errno != EINTR) \
2062: - { \
2063: - YY_FATAL_ERROR( "input in flex scanner failed" ); \
2064: - break; \
2065: - } \
2066: - errno=0; \
2067: - clearerr(yyin); \
2068: - } \
2069: - }\
2070: -\
2071: -
2072: -#endif
2073: -
2074: -/* No semi-colon after return; correct usage is to write "yyterminate();" -
2075: - * we don't want an extra ';' after the "return" because that will cause
2076: - * some compilers to complain about unreachable statements.
2077: - */
2078: -#ifndef yyterminate
2079: -#define yyterminate() return YY_NULL
2080: -#endif
2081: -
2082: -/* Number of entries by which start-condition stack grows. */
2083: -#ifndef YY_START_STACK_INCR
2084: -#define YY_START_STACK_INCR 25
2085: -#endif
2086: -
2087: -/* Report a fatal error. */
2088: -#ifndef YY_FATAL_ERROR
2089: -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
2090: -#endif
2091: -
2092: -/* end tables serialization structures and prototypes */
2093: -
2094: -/* Default declaration of generated scanner - a define so the user can
2095: - * easily add parameters.
2096: - */
2097: -#ifndef YY_DECL
2098: -#define YY_DECL_IS_OURS 1
2099: -
2100: -extern int yylex (yyscan_t yyscanner);
2101: -
2102: -#define YY_DECL int yylex (yyscan_t yyscanner)
2103: -#endif /* !YY_DECL */
2104: -
2105: -/* Code executed at the beginning of each rule, after yytext and yyleng
2106: - * have been set up.
2107: - */
2108: -#ifndef YY_USER_ACTION
2109: -#define YY_USER_ACTION
2110: -#endif
2111: -
2112: -/* Code executed at the end of each rule. */
2113: -#ifndef YY_BREAK
2114: -#define YY_BREAK /*LINTED*/break;
2115: -#endif
2116: -
2117: -#define YY_RULE_SETUP \
2118: - YY_USER_ACTION
2119: -
2120: -/** The main scanner function which does all the work.
2121: - */
2122: -YY_DECL
2123: -{
2124: - yy_state_type yy_current_state;
2125: - char *yy_cp, *yy_bp;
2126: - int yy_act;
2127: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2128: -
2129: - if ( !yyg->yy_init )
2130: - {
2131: - yyg->yy_init = 1;
2132: -
2133: -#ifdef YY_USER_INIT
2134: - YY_USER_INIT;
2135: -#endif
2136: -
2137: - if ( ! yyg->yy_start )
2138: - yyg->yy_start = 1; /* first start state */
2139: -
2140: - if ( ! yyin )
2141: - yyin = stdin;
2142: -
2143: - if ( ! yyout )
2144: - yyout = stdout;
2145: -
2146: - if ( ! YY_CURRENT_BUFFER ) {
2147: - yyensure_buffer_stack (yyscanner);
2148: - YY_CURRENT_BUFFER_LVALUE =
2149: - yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
2150: - }
2151: -
2152: - yy_load_buffer_state(yyscanner );
2153: - }
2154: -
2155: - {
2156: -#line 114 "lex.l"
2157: -
2158: -
2159: -#line 834 "lex.c"
2160: -
2161: - while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
2162: - {
2163: - yy_cp = yyg->yy_c_buf_p;
2164: -
2165: - /* Support of yytext. */
2166: - *yy_cp = yyg->yy_hold_char;
2167: -
2168: - /* yy_bp points to the position in yy_ch_buf of the start of
2169: - * the current run.
2170: - */
2171: - yy_bp = yy_cp;
2172: -
2173: - yy_current_state = yyg->yy_start;
2174: -yy_match:
2175: - do
2176: - {
2177: - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
2178: - if ( yy_accept[yy_current_state] )
2179: - {
2180: - yyg->yy_last_accepting_state = yy_current_state;
2181: - yyg->yy_last_accepting_cpos = yy_cp;
2182: - }
2183: - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
2184: - {
2185: - yy_current_state = (int) yy_def[yy_current_state];
2186: - if ( yy_current_state >= 34 )
2187: - yy_c = yy_meta[(unsigned int) yy_c];
2188: - }
2189: - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
2190: - ++yy_cp;
2191: - }
2192: - while ( yy_base[yy_current_state] != 58 );
2193: -
2194: -yy_find_action:
2195: - yy_act = yy_accept[yy_current_state];
2196: - if ( yy_act == 0 )
2197: - { /* have to back up */
2198: - yy_cp = yyg->yy_last_accepting_cpos;
2199: - yy_current_state = yyg->yy_last_accepting_state;
2200: - yy_act = yy_accept[yy_current_state];
2201: - }
2202: -
2203: - YY_DO_BEFORE_ACTION;
2204: -
2205: -do_action: /* This label is used only to access EOF actions. */
2206: -
2207: - switch ( yy_act )
2208: - { /* beginning of action switch */
2209: - case 0: /* must back up */
2210: - /* undo the effects of YY_DO_BEFORE_ACTION */
2211: - *yy_cp = yyg->yy_hold_char;
2212: - yy_cp = yyg->yy_last_accepting_cpos;
2213: - yy_current_state = yyg->yy_last_accepting_state;
2214: - goto yy_find_action;
2215: -
2216: -case 1:
2217: -YY_RULE_SETUP
2218: -#line 116 "lex.l"
2219: -
2220: - YY_BREAK
2221: -case 2:
2222: -/* rule 2 can match eol */
2223: -YY_RULE_SETUP
2224: -#line 117 "lex.l"
2225: -
2226: - YY_BREAK
2227: -case 3:
2228: -YY_RULE_SETUP
2229: -#line 119 "lex.l"
2230: -{
2231: - intptr_t n;
2232: -
2233: - errno = 0;
2234: - n = strtol(yytext, (char **)NULL, 10);
2235: - if ( errno == ERANGE )
2236: - raise_exception("Integer overflow in input", NIL);
2237: - *lvalp = lac_extty_box(LREG_INTEGER, (void *)n, 0);
2238: - return INTEGER;
2239: -}
2240: - YY_BREAK
2241: -case 4:
2242: -YY_RULE_SETUP
2243: -#line 130 "lex.l"
2244: -{
2245: - intptr_t n;
2246: -
2247: - errno = 0;
2248: - n = strtol(yytext+2, (char **)NULL, 16);
2249: - if ( errno == ERANGE )
2250: - raise_exception("Integer overflow in input", NIL);
2251: - *lvalp = lac_extty_box(LREG_INTEGER, (void *)n, 0);
2252: - return INTEGER;
2253: -}
2254: - YY_BREAK
2255: -case 5:
2256: -YY_RULE_SETUP
2257: -#line 141 "lex.l"
2258: -{
2259: - *lvalp = NIL;
2260: - return NIHIL;
2261: -}
2262: - YY_BREAK
2263: -case 6:
2264: -/* rule 6 can match eol */
2265: -YY_RULE_SETUP
2266: -#line 146 "lex.l"
2267: -{
2268: - size_t len = strlen(yytext);
2269: - char *s = lac_alloc(len - 1);
2270: - memcpy(s, yytext+1, len - 2);
2271: - *lvalp = lreg_raw(s, LREG_STRING);
2272: - return STRING;
2273: -}
2274: - YY_BREAK
2275: -case 7:
2276: -YY_RULE_SETUP
2277: -#line 154 "lex.l"
2278: -{
2279: - int i;
2280: - size_t len = strlen(yytext);
2281: - char *s = lac_alloc(len + 1);
2282: - for (i = 0; i < len; i++)
2283: - *(s+i) = toupper((int)*(yytext+i));
2284: - *lvalp = intern_symbol(s);
2285: - return SYMBOL;
2286: -};
2287: - YY_BREAK
2288: -case 8:
2289: -YY_RULE_SETUP
2290: -#line 164 "lex.l"
2291: -{ return COMMA_AT; }
2292: - YY_BREAK
2293: -case YY_STATE_EOF(INITIAL):
2294: -#line 166 "lex.l"
2295: -{ return ENDOFFILE; }
2296: - YY_BREAK
2297: -case 9:
2298: -YY_RULE_SETUP
2299: -#line 168 "lex.l"
2300: -{ return *yytext; }
2301: - YY_BREAK
2302: -case 10:
2303: -YY_RULE_SETUP
2304: -#line 171 "lex.l"
2305: -ECHO;
2306: - YY_BREAK
2307: -#line 982 "lex.c"
2308: -
2309: - case YY_END_OF_BUFFER:
2310: - {
2311: - /* Amount of text matched not including the EOB char. */
2312: - int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
2313: -
2314: - /* Undo the effects of YY_DO_BEFORE_ACTION. */
2315: - *yy_cp = yyg->yy_hold_char;
2316: - YY_RESTORE_YY_MORE_OFFSET
2317: -
2318: - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
2319: - {
2320: - /* We're scanning a new file or input source. It's
2321: - * possible that this happened because the user
2322: - * just pointed yyin at a new source and called
2323: - * yylex(). If so, then we have to assure
2324: - * consistency between YY_CURRENT_BUFFER and our
2325: - * globals. Here is the right place to do so, because
2326: - * this is the first action (other than possibly a
2327: - * back-up) that will match for the new input source.
2328: - */
2329: - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
2330: - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
2331: - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
2332: - }
2333: -
2334: - /* Note that here we test for yy_c_buf_p "<=" to the position
2335: - * of the first EOB in the buffer, since yy_c_buf_p will
2336: - * already have been incremented past the NUL character
2337: - * (since all states make transitions on EOB to the
2338: - * end-of-buffer state). Contrast this with the test
2339: - * in input().
2340: - */
2341: - if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
2342: - { /* This was really a NUL. */
2343: - yy_state_type yy_next_state;
2344: -
2345: - yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
2346: -
2347: - yy_current_state = yy_get_previous_state( yyscanner );
2348: -
2349: - /* Okay, we're now positioned to make the NUL
2350: - * transition. We couldn't have
2351: - * yy_get_previous_state() go ahead and do it
2352: - * for us because it doesn't know how to deal
2353: - * with the possibility of jamming (and we don't
2354: - * want to build jamming into it because then it
2355: - * will run more slowly).
2356: - */
2357: -
2358: - yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
2359: -
2360: - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
2361: -
2362: - if ( yy_next_state )
2363: - {
2364: - /* Consume the NUL. */
2365: - yy_cp = ++yyg->yy_c_buf_p;
2366: - yy_current_state = yy_next_state;
2367: - goto yy_match;
2368: - }
2369: -
2370: - else
2371: - {
2372: - yy_cp = yyg->yy_c_buf_p;
2373: - goto yy_find_action;
2374: - }
2375: - }
2376: -
2377: - else switch ( yy_get_next_buffer( yyscanner ) )
2378: - {
2379: - case EOB_ACT_END_OF_FILE:
2380: - {
2381: - yyg->yy_did_buffer_switch_on_eof = 0;
2382: -
2383: - if ( yywrap(yyscanner ) )
2384: - {
2385: - /* Note: because we've taken care in
2386: - * yy_get_next_buffer() to have set up
2387: - * yytext, we can now set up
2388: - * yy_c_buf_p so that if some total
2389: - * hoser (like flex itself) wants to
2390: - * call the scanner after we return the
2391: - * YY_NULL, it'll still work - another
2392: - * YY_NULL will get returned.
2393: - */
2394: - yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
2395: -
2396: - yy_act = YY_STATE_EOF(YY_START);
2397: - goto do_action;
2398: - }
2399: -
2400: - else
2401: - {
2402: - if ( ! yyg->yy_did_buffer_switch_on_eof )
2403: - YY_NEW_FILE;
2404: - }
2405: - break;
2406: - }
2407: -
2408: - case EOB_ACT_CONTINUE_SCAN:
2409: - yyg->yy_c_buf_p =
2410: - yyg->yytext_ptr + yy_amount_of_matched_text;
2411: -
2412: - yy_current_state = yy_get_previous_state( yyscanner );
2413: -
2414: - yy_cp = yyg->yy_c_buf_p;
2415: - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
2416: - goto yy_match;
2417: -
2418: - case EOB_ACT_LAST_MATCH:
2419: - yyg->yy_c_buf_p =
2420: - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
2421: -
2422: - yy_current_state = yy_get_previous_state( yyscanner );
2423: -
2424: - yy_cp = yyg->yy_c_buf_p;
2425: - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
2426: - goto yy_find_action;
2427: - }
2428: - break;
2429: - }
2430: -
2431: - default:
2432: - YY_FATAL_ERROR(
2433: - "fatal flex scanner internal error--no action found" );
2434: - } /* end of action switch */
2435: - } /* end of scanning one token */
2436: - } /* end of user's declarations */
2437: -} /* end of yylex */
2438: -
2439: -/* yy_get_next_buffer - try to read in a new buffer
2440: - *
2441: - * Returns a code representing an action:
2442: - * EOB_ACT_LAST_MATCH -
2443: - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
2444: - * EOB_ACT_END_OF_FILE - end of file
2445: - */
2446: -static int yy_get_next_buffer (yyscan_t yyscanner)
2447: -{
2448: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2449: - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
2450: - char *source = yyg->yytext_ptr;
2451: - yy_size_t number_to_move, i;
2452: - int ret_val;
2453: -
2454: - if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
2455: - YY_FATAL_ERROR(
2456: - "fatal flex scanner internal error--end of buffer missed" );
2457: -
2458: - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
2459: - { /* Don't try to fill the buffer, so this is an EOF. */
2460: - if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
2461: - {
2462: - /* We matched a single character, the EOB, so
2463: - * treat this as a final EOF.
2464: - */
2465: - return EOB_ACT_END_OF_FILE;
2466: - }
2467: -
2468: - else
2469: - {
2470: - /* We matched some text prior to the EOB, first
2471: - * process it.
2472: - */
2473: - return EOB_ACT_LAST_MATCH;
2474: - }
2475: - }
2476: -
2477: - /* Try to read more data. */
2478: -
2479: - /* First move last chars to start of buffer. */
2480: - number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
2481: -
2482: - for ( i = 0; i < number_to_move; ++i )
2483: - *(dest++) = *(source++);
2484: -
2485: - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
2486: - /* don't do the read, it's not guaranteed to return an EOF,
2487: - * just force an EOF
2488: - */
2489: - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
2490: -
2491: - else
2492: - {
2493: - int num_to_read =
2494: - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
2495: -
2496: - while ( num_to_read <= 0 )
2497: - { /* Not enough room in the buffer - grow it. */
2498: -
2499: - /* just a shorter name for the current buffer */
2500: - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
2501: -
2502: - int yy_c_buf_p_offset =
2503: - (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
2504: -
2505: - if ( b->yy_is_our_buffer )
2506: - {
2507: - yy_size_t new_size = b->yy_buf_size * 2;
2508: -
2509: - if ( new_size <= 0 )
2510: - b->yy_buf_size += b->yy_buf_size / 8;
2511: - else
2512: - b->yy_buf_size *= 2;
2513: -
2514: - b->yy_ch_buf = (char *)
2515: - /* Include room in for 2 EOB chars. */
2516: - yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
2517: - }
2518: - else
2519: - /* Can't grow it, we don't own it. */
2520: - b->yy_ch_buf = 0;
2521: -
2522: - if ( ! b->yy_ch_buf )
2523: - YY_FATAL_ERROR(
2524: - "fatal error - scanner input buffer overflow" );
2525: -
2526: - yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
2527: -
2528: - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
2529: - number_to_move - 1;
2530: -
2531: - }
2532: -
2533: - if ( num_to_read > YY_READ_BUF_SIZE )
2534: - num_to_read = YY_READ_BUF_SIZE;
2535: -
2536: - /* Read in more data. */
2537: - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
2538: - yyg->yy_n_chars, num_to_read );
2539: -
2540: - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
2541: - }
2542: -
2543: - if ( yyg->yy_n_chars == 0 )
2544: - {
2545: - if ( number_to_move == YY_MORE_ADJ )
2546: - {
2547: - ret_val = EOB_ACT_END_OF_FILE;
2548: - yyrestart(yyin ,yyscanner);
2549: - }
2550: -
2551: - else
2552: - {
2553: - ret_val = EOB_ACT_LAST_MATCH;
2554: - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
2555: - YY_BUFFER_EOF_PENDING;
2556: - }
2557: - }
2558: -
2559: - else
2560: - ret_val = EOB_ACT_CONTINUE_SCAN;
2561: -
2562: - if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
2563: - /* Extend the array by 50%, plus the number we really need. */
2564: - yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
2565: - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
2566: - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
2567: - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
2568: - }
2569: -
2570: - yyg->yy_n_chars += number_to_move;
2571: - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
2572: - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
2573: -
2574: - yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
2575: -
2576: - return ret_val;
2577: -}
2578: -
2579: -/* yy_get_previous_state - get the state just before the EOB char was reached */
2580: -
2581: - static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
2582: -{
2583: - yy_state_type yy_current_state;
2584: - char *yy_cp;
2585: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2586: -
2587: - yy_current_state = yyg->yy_start;
2588: -
2589: - for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
2590: - {
2591: - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
2592: - if ( yy_accept[yy_current_state] )
2593: - {
2594: - yyg->yy_last_accepting_state = yy_current_state;
2595: - yyg->yy_last_accepting_cpos = yy_cp;
2596: - }
2597: - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
2598: - {
2599: - yy_current_state = (int) yy_def[yy_current_state];
2600: - if ( yy_current_state >= 34 )
2601: - yy_c = yy_meta[(unsigned int) yy_c];
2602: - }
2603: - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
2604: - }
2605: -
2606: - return yy_current_state;
2607: -}
2608: -
2609: -/* yy_try_NUL_trans - try to make a transition on the NUL character
2610: - *
2611: - * synopsis
2612: - * next_state = yy_try_NUL_trans( current_state );
2613: - */
2614: - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
2615: -{
2616: - int yy_is_jam;
2617: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
2618: - char *yy_cp = yyg->yy_c_buf_p;
2619: -
2620: - YY_CHAR yy_c = 1;
2621: - if ( yy_accept[yy_current_state] )
2622: - {
2623: - yyg->yy_last_accepting_state = yy_current_state;
2624: - yyg->yy_last_accepting_cpos = yy_cp;
2625: - }
2626: - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
2627: - {
2628: - yy_current_state = (int) yy_def[yy_current_state];
2629: - if ( yy_current_state >= 34 )
2630: - yy_c = yy_meta[(unsigned int) yy_c];
2631: - }
2632: - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
2633: - yy_is_jam = (yy_current_state == 33);
2634: -
2635: - (void)yyg;
2636: - return yy_is_jam ? 0 : yy_current_state;
2637: -}
2638: -
2639: -#ifndef YY_NO_UNPUT
2640: -
2641: - static void yyunput (int c, char * yy_bp , yyscan_t yyscanner)
2642: -{
2643: - char *yy_cp;
2644: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2645: -
2646: - yy_cp = yyg->yy_c_buf_p;
2647: -
2648: - /* undo effects of setting up yytext */
2649: - *yy_cp = yyg->yy_hold_char;
2650: -
2651: - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
2652: - { /* need to shift things up to make room */
2653: - /* +2 for EOB chars. */
2654: - yy_size_t number_to_move = yyg->yy_n_chars + 2;
2655: - char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
2656: - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
2657: - char *source =
2658: - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
2659: -
2660: - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
2661: - *--dest = *--source;
2662: -
2663: - yy_cp += (int) (dest - source);
2664: - yy_bp += (int) (dest - source);
2665: - YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
2666: - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
2667: -
2668: - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
2669: - YY_FATAL_ERROR( "flex scanner push-back overflow" );
2670: - }
2671: -
2672: - *--yy_cp = (char) c;
2673: -
2674: - yyg->yytext_ptr = yy_bp;
2675: - yyg->yy_hold_char = *yy_cp;
2676: - yyg->yy_c_buf_p = yy_cp;
2677: -}
2678: -
2679: -#endif
2680: -
2681: -#ifndef YY_NO_INPUT
2682: -#ifdef __cplusplus
2683: - static int yyinput (yyscan_t yyscanner)
2684: -#else
2685: - static int input (yyscan_t yyscanner)
2686: -#endif
2687: -
2688: -{
2689: - int c;
2690: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2691: -
2692: - *yyg->yy_c_buf_p = yyg->yy_hold_char;
2693: -
2694: - if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
2695: - {
2696: - /* yy_c_buf_p now points to the character we want to return.
2697: - * If this occurs *before* the EOB characters, then it's a
2698: - * valid NUL; if not, then we've hit the end of the buffer.
2699: - */
2700: - if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
2701: - /* This was really a NUL. */
2702: - *yyg->yy_c_buf_p = '\0';
2703: -
2704: - else
2705: - { /* need more input */
2706: - yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
2707: - ++yyg->yy_c_buf_p;
2708: -
2709: - switch ( yy_get_next_buffer( yyscanner ) )
2710: - {
2711: - case EOB_ACT_LAST_MATCH:
2712: - /* This happens because yy_g_n_b()
2713: - * sees that we've accumulated a
2714: - * token and flags that we need to
2715: - * try matching the token before
2716: - * proceeding. But for input(),
2717: - * there's no matching to consider.
2718: - * So convert the EOB_ACT_LAST_MATCH
2719: - * to EOB_ACT_END_OF_FILE.
2720: - */
2721: -
2722: - /* Reset buffer status. */
2723: - yyrestart(yyin ,yyscanner);
2724: -
2725: - /*FALLTHROUGH*/
2726: -
2727: - case EOB_ACT_END_OF_FILE:
2728: - {
2729: - if ( yywrap(yyscanner ) )
2730: - return EOF;
2731: -
2732: - if ( ! yyg->yy_did_buffer_switch_on_eof )
2733: - YY_NEW_FILE;
2734: -#ifdef __cplusplus
2735: - return yyinput(yyscanner);
2736: -#else
2737: - return input(yyscanner);
2738: -#endif
2739: - }
2740: -
2741: - case EOB_ACT_CONTINUE_SCAN:
2742: - yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
2743: - break;
2744: - }
2745: - }
2746: - }
2747: -
2748: - c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
2749: - *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
2750: - yyg->yy_hold_char = *++yyg->yy_c_buf_p;
2751: -
2752: - return c;
2753: -}
2754: -#endif /* ifndef YY_NO_INPUT */
2755: -
2756: -/** Immediately switch to a different input stream.
2757: - * @param input_file A readable stream.
2758: - * @param yyscanner The scanner object.
2759: - * @note This function does not reset the start condition to @c INITIAL .
2760: - */
2761: - void yyrestart (FILE * input_file , yyscan_t yyscanner)
2762: -{
2763: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2764: -
2765: - if ( ! YY_CURRENT_BUFFER ){
2766: - yyensure_buffer_stack (yyscanner);
2767: - YY_CURRENT_BUFFER_LVALUE =
2768: - yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
2769: - }
2770: -
2771: - yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
2772: - yy_load_buffer_state(yyscanner );
2773: -}
2774: -
2775: -/** Switch to a different input buffer.
2776: - * @param new_buffer The new input buffer.
2777: - * @param yyscanner The scanner object.
2778: - */
2779: - void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
2780: -{
2781: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2782: -
2783: - /* TODO. We should be able to replace this entire function body
2784: - * with
2785: - * yypop_buffer_state();
2786: - * yypush_buffer_state(new_buffer);
2787: - */
2788: - yyensure_buffer_stack (yyscanner);
2789: - if ( YY_CURRENT_BUFFER == new_buffer )
2790: - return;
2791: -
2792: - if ( YY_CURRENT_BUFFER )
2793: - {
2794: - /* Flush out information for old buffer. */
2795: - *yyg->yy_c_buf_p = yyg->yy_hold_char;
2796: - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
2797: - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
2798: - }
2799: -
2800: - YY_CURRENT_BUFFER_LVALUE = new_buffer;
2801: - yy_load_buffer_state(yyscanner );
2802: -
2803: - /* We don't actually know whether we did this switch during
2804: - * EOF (yywrap()) processing, but the only time this flag
2805: - * is looked at is after yywrap() is called, so it's safe
2806: - * to go ahead and always set it.
2807: - */
2808: - yyg->yy_did_buffer_switch_on_eof = 1;
2809: -}
2810: -
2811: -static void yy_load_buffer_state (yyscan_t yyscanner)
2812: -{
2813: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2814: - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
2815: - yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
2816: - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
2817: - yyg->yy_hold_char = *yyg->yy_c_buf_p;
2818: -}
2819: -
2820: -/** Allocate and initialize an input buffer state.
2821: - * @param file A readable stream.
2822: - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
2823: - * @param yyscanner The scanner object.
2824: - * @return the allocated buffer state.
2825: - */
2826: - YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
2827: -{
2828: - YY_BUFFER_STATE b;
2829: -
2830: - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
2831: - if ( ! b )
2832: - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
2833: -
2834: - b->yy_buf_size = (yy_size_t)size;
2835: -
2836: - /* yy_ch_buf has to be 2 characters longer than the size given because
2837: - * we need to put in 2 end-of-buffer characters.
2838: - */
2839: - b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
2840: - if ( ! b->yy_ch_buf )
2841: - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
2842: -
2843: - b->yy_is_our_buffer = 1;
2844: -
2845: - yy_init_buffer(b,file ,yyscanner);
2846: -
2847: - return b;
2848: -}
2849: -
2850: -/** Destroy the buffer.
2851: - * @param b a buffer created with yy_create_buffer()
2852: - * @param yyscanner The scanner object.
2853: - */
2854: - void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
2855: -{
2856: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2857: -
2858: - if ( ! b )
2859: - return;
2860: -
2861: - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
2862: - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
2863: -
2864: - if ( b->yy_is_our_buffer )
2865: - yyfree((void *) b->yy_ch_buf ,yyscanner );
2866: -
2867: - yyfree((void *) b ,yyscanner );
2868: -}
2869: -
2870: -/* Initializes or reinitializes a buffer.
2871: - * This function is sometimes called more than once on the same buffer,
2872: - * such as during a yyrestart() or at EOF.
2873: - */
2874: - static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
2875: -
2876: -{
2877: - int oerrno = errno;
2878: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2879: -
2880: - yy_flush_buffer(b ,yyscanner);
2881: -
2882: - b->yy_input_file = file;
2883: - b->yy_fill_buffer = 1;
2884: -
2885: - /* If b is the current buffer, then yy_init_buffer was _probably_
2886: - * called from yyrestart() or through yy_get_next_buffer.
2887: - * In that case, we don't want to reset the lineno or column.
2888: - */
2889: - if (b != YY_CURRENT_BUFFER){
2890: - b->yy_bs_lineno = 1;
2891: - b->yy_bs_column = 0;
2892: - }
2893: -
2894: - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
2895: -
2896: - errno = oerrno;
2897: -}
2898: -
2899: -/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
2900: - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
2901: - * @param yyscanner The scanner object.
2902: - */
2903: - void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
2904: -{
2905: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2906: - if ( ! b )
2907: - return;
2908: -
2909: - b->yy_n_chars = 0;
2910: -
2911: - /* We always need two end-of-buffer characters. The first causes
2912: - * a transition to the end-of-buffer state. The second causes
2913: - * a jam in that state.
2914: - */
2915: - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
2916: - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
2917: -
2918: - b->yy_buf_pos = &b->yy_ch_buf[0];
2919: -
2920: - b->yy_at_bol = 1;
2921: - b->yy_buffer_status = YY_BUFFER_NEW;
2922: -
2923: - if ( b == YY_CURRENT_BUFFER )
2924: - yy_load_buffer_state(yyscanner );
2925: -}
2926: -
2927: -/** Pushes the new state onto the stack. The new state becomes
2928: - * the current state. This function will allocate the stack
2929: - * if necessary.
2930: - * @param new_buffer The new state.
2931: - * @param yyscanner The scanner object.
2932: - */
2933: -void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
2934: -{
2935: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2936: - if (new_buffer == NULL)
2937: - return;
2938: -
2939: - yyensure_buffer_stack(yyscanner);
2940: -
2941: - /* This block is copied from yy_switch_to_buffer. */
2942: - if ( YY_CURRENT_BUFFER )
2943: - {
2944: - /* Flush out information for old buffer. */
2945: - *yyg->yy_c_buf_p = yyg->yy_hold_char;
2946: - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
2947: - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
2948: - }
2949: -
2950: - /* Only push if top exists. Otherwise, replace top. */
2951: - if (YY_CURRENT_BUFFER)
2952: - yyg->yy_buffer_stack_top++;
2953: - YY_CURRENT_BUFFER_LVALUE = new_buffer;
2954: -
2955: - /* copied from yy_switch_to_buffer. */
2956: - yy_load_buffer_state(yyscanner );
2957: - yyg->yy_did_buffer_switch_on_eof = 1;
2958: -}
2959: -
2960: -/** Removes and deletes the top of the stack, if present.
2961: - * The next element becomes the new top.
2962: - * @param yyscanner The scanner object.
2963: - */
2964: -void yypop_buffer_state (yyscan_t yyscanner)
2965: -{
2966: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2967: - if (!YY_CURRENT_BUFFER)
2968: - return;
2969: -
2970: - yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
2971: - YY_CURRENT_BUFFER_LVALUE = NULL;
2972: - if (yyg->yy_buffer_stack_top > 0)
2973: - --yyg->yy_buffer_stack_top;
2974: -
2975: - if (YY_CURRENT_BUFFER) {
2976: - yy_load_buffer_state(yyscanner );
2977: - yyg->yy_did_buffer_switch_on_eof = 1;
2978: - }
2979: -}
2980: -
2981: -/* Allocates the stack if it does not exist.
2982: - * Guarantees space for at least one push.
2983: - */
2984: -static void yyensure_buffer_stack (yyscan_t yyscanner)
2985: -{
2986: - yy_size_t num_to_alloc;
2987: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2988: -
2989: - if (!yyg->yy_buffer_stack) {
2990: -
2991: - /* First allocation is just for 2 elements, since we don't know if this
2992: - * scanner will even need a stack. We use 2 instead of 1 to avoid an
2993: - * immediate realloc on the next call.
2994: - */
2995: - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
2996: - yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
2997: - (num_to_alloc * sizeof(struct yy_buffer_state*)
2998: - , yyscanner);
2999: - if ( ! yyg->yy_buffer_stack )
3000: - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
3001: -
3002: - memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
3003: -
3004: - yyg->yy_buffer_stack_max = num_to_alloc;
3005: - yyg->yy_buffer_stack_top = 0;
3006: - return;
3007: - }
3008: -
3009: - if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
3010: -
3011: - /* Increase the buffer to prepare for a possible push. */
3012: - yy_size_t grow_size = 8 /* arbitrary grow size */;
3013: -
3014: - num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
3015: - yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
3016: - (yyg->yy_buffer_stack,
3017: - num_to_alloc * sizeof(struct yy_buffer_state*)
3018: - , yyscanner);
3019: - if ( ! yyg->yy_buffer_stack )
3020: - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
3021: -
3022: - /* zero only the new slots.*/
3023: - memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
3024: - yyg->yy_buffer_stack_max = num_to_alloc;
3025: - }
3026: -}
3027: -
3028: -/** Setup the input buffer state to scan directly from a user-specified character buffer.
3029: - * @param base the character buffer
3030: - * @param size the size in bytes of the character buffer
3031: - * @param yyscanner The scanner object.
3032: - * @return the newly allocated buffer state object.
3033: - */
3034: -YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
3035: -{
3036: - YY_BUFFER_STATE b;
3037: -
3038: - if ( size < 2 ||
3039: - base[size-2] != YY_END_OF_BUFFER_CHAR ||
3040: - base[size-1] != YY_END_OF_BUFFER_CHAR )
3041: - /* They forgot to leave room for the EOB's. */
3042: - return 0;
3043: -
3044: - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
3045: - if ( ! b )
3046: - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
3047: -
3048: - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
3049: - b->yy_buf_pos = b->yy_ch_buf = base;
3050: - b->yy_is_our_buffer = 0;
3051: - b->yy_input_file = 0;
3052: - b->yy_n_chars = b->yy_buf_size;
3053: - b->yy_is_interactive = 0;
3054: - b->yy_at_bol = 1;
3055: - b->yy_fill_buffer = 0;
3056: - b->yy_buffer_status = YY_BUFFER_NEW;
3057: -
3058: - yy_switch_to_buffer(b ,yyscanner );
3059: -
3060: - return b;
3061: -}
3062: -
3063: -/** Setup the input buffer state to scan a string. The next call to yylex() will
3064: - * scan from a @e copy of @a str.
3065: - * @param yystr a NUL-terminated string to scan
3066: - * @param yyscanner The scanner object.
3067: - * @return the newly allocated buffer state object.
3068: - * @note If you want to scan bytes that may contain NUL values, then use
3069: - * yy_scan_bytes() instead.
3070: - */
3071: -YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
3072: -{
3073: -
3074: - return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
3075: -}
3076: -
3077: -/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
3078: - * scan from a @e copy of @a bytes.
3079: - * @param yybytes the byte buffer to scan
3080: - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
3081: - * @param yyscanner The scanner object.
3082: - * @return the newly allocated buffer state object.
3083: - */
3084: -YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner)
3085: -{
3086: - YY_BUFFER_STATE b;
3087: - char *buf;
3088: - yy_size_t n;
3089: - yy_size_t i;
3090: -
3091: - /* Get memory for full buffer, including space for trailing EOB's. */
3092: - n = _yybytes_len + 2;
3093: - buf = (char *) yyalloc(n ,yyscanner );
3094: - if ( ! buf )
3095: - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
3096: -
3097: - for ( i = 0; i < _yybytes_len; ++i )
3098: - buf[i] = yybytes[i];
3099: -
3100: - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
3101: -
3102: - b = yy_scan_buffer(buf,n ,yyscanner);
3103: - if ( ! b )
3104: - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
3105: -
3106: - /* It's okay to grow etc. this buffer, and we should throw it
3107: - * away when we're done.
3108: - */
3109: - b->yy_is_our_buffer = 1;
3110: -
3111: - return b;
3112: -}
3113: -
3114: -#ifndef YY_EXIT_FAILURE
3115: -#define YY_EXIT_FAILURE 2
3116: -#endif
3117: -
3118: -static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
3119: -{
3120: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3121: - (void)yyg;
3122: - (void) fprintf( stderr, "%s\n", msg );
3123: - exit( YY_EXIT_FAILURE );
3124: -}
3125: -
3126: -/* Redefine yyless() so it works in section 3 code. */
3127: -
3128: -#undef yyless
3129: -#define yyless(n) \
3130: - do \
3131: - { \
3132: - /* Undo effects of setting up yytext. */ \
3133: - yy_size_t yyless_macro_arg = (n); \
3134: - YY_LESS_LINENO(yyless_macro_arg);\
3135: - yytext[yyleng] = yyg->yy_hold_char; \
3136: - yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
3137: - yyg->yy_hold_char = *yyg->yy_c_buf_p; \
3138: - *yyg->yy_c_buf_p = '\0'; \
3139: - yyleng = yyless_macro_arg; \
3140: - } \
3141: - while ( 0 )
3142: -
3143: -/* Accessor methods (get/set functions) to struct members. */
3144: -
3145: -/** Get the user-defined data for this scanner.
3146: - * @param yyscanner The scanner object.
3147: - */
3148: -YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
3149: -{
3150: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3151: - return yyextra;
3152: -}
3153: -
3154: -/** Get the current line number.
3155: - * @param yyscanner The scanner object.
3156: - */
3157: -int yyget_lineno (yyscan_t yyscanner)
3158: -{
3159: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3160: -
3161: - if (! YY_CURRENT_BUFFER)
3162: - return 0;
3163: -
3164: - return yylineno;
3165: -}
3166: -
3167: -/** Get the current column number.
3168: - * @param yyscanner The scanner object.
3169: - */
3170: -int yyget_column (yyscan_t yyscanner)
3171: -{
3172: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3173: -
3174: - if (! YY_CURRENT_BUFFER)
3175: - return 0;
3176: -
3177: - return yycolumn;
3178: -}
3179: -
3180: -/** Get the input stream.
3181: - * @param yyscanner The scanner object.
3182: - */
3183: -FILE *yyget_in (yyscan_t yyscanner)
3184: -{
3185: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3186: - return yyin;
3187: -}
3188: -
3189: -/** Get the output stream.
3190: - * @param yyscanner The scanner object.
3191: - */
3192: -FILE *yyget_out (yyscan_t yyscanner)
3193: -{
3194: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3195: - return yyout;
3196: -}
3197: -
3198: -/** Get the length of the current token.
3199: - * @param yyscanner The scanner object.
3200: - */
3201: -yy_size_t yyget_leng (yyscan_t yyscanner)
3202: -{
3203: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3204: - return yyleng;
3205: -}
3206: -
3207: -/** Get the current token.
3208: - * @param yyscanner The scanner object.
3209: - */
3210: -
3211: -char *yyget_text (yyscan_t yyscanner)
3212: -{
3213: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3214: - return yytext;
3215: -}
3216: -
3217: -/** Set the user-defined data. This data is never touched by the scanner.
3218: - * @param user_defined The data to be associated with this scanner.
3219: - * @param yyscanner The scanner object.
3220: - */
3221: -void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
3222: -{
3223: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3224: - yyextra = user_defined ;
3225: -}
3226: -
3227: -/** Set the current line number.
3228: - * @param _line_number line number
3229: - * @param yyscanner The scanner object.
3230: - */
3231: -void yyset_lineno (int _line_number , yyscan_t yyscanner)
3232: -{
3233: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3234: -
3235: - /* lineno is only valid if an input buffer exists. */
3236: - if (! YY_CURRENT_BUFFER )
3237: - YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
3238: -
3239: - yylineno = _line_number;
3240: -}
3241: -
3242: -/** Set the current column.
3243: - * @param _column_no column number
3244: - * @param yyscanner The scanner object.
3245: - */
3246: -void yyset_column (int _column_no , yyscan_t yyscanner)
3247: -{
3248: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3249: -
3250: - /* column is only valid if an input buffer exists. */
3251: - if (! YY_CURRENT_BUFFER )
3252: - YY_FATAL_ERROR( "yyset_column called with no buffer" );
3253: -
3254: - yycolumn = _column_no;
3255: -}
3256: -
3257: -/** Set the input stream. This does not discard the current
3258: - * input buffer.
3259: - * @param _in_str A readable stream.
3260: - * @param yyscanner The scanner object.
3261: - * @see yy_switch_to_buffer
3262: - */
3263: -void yyset_in (FILE * _in_str , yyscan_t yyscanner)
3264: -{
3265: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3266: - yyin = _in_str ;
3267: -}
3268: -
3269: -void yyset_out (FILE * _out_str , yyscan_t yyscanner)
3270: -{
3271: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3272: - yyout = _out_str ;
3273: -}
3274: -
3275: -int yyget_debug (yyscan_t yyscanner)
3276: -{
3277: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3278: - return yy_flex_debug;
3279: -}
3280: -
3281: -void yyset_debug (int _bdebug , yyscan_t yyscanner)
3282: -{
3283: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3284: - yy_flex_debug = _bdebug ;
3285: -}
3286: -
3287: -/* Accessor methods for yylval and yylloc */
3288: -
3289: -/* User-visible API */
3290: -
3291: -/* yylex_init is special because it creates the scanner itself, so it is
3292: - * the ONLY reentrant function that doesn't take the scanner as the last argument.
3293: - * That's why we explicitly handle the declaration, instead of using our macros.
3294: - */
3295: -
3296: -int yylex_init(yyscan_t* ptr_yy_globals)
3297: -
3298: -{
3299: - if (ptr_yy_globals == NULL){
3300: - errno = EINVAL;
3301: - return 1;
3302: - }
3303: -
3304: - *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
3305: -
3306: - if (*ptr_yy_globals == NULL){
3307: - errno = ENOMEM;
3308: - return 1;
3309: - }
3310: -
3311: - /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
3312: - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
3313: -
3314: - return yy_init_globals ( *ptr_yy_globals );
3315: -}
3316: -
3317: -/* yylex_init_extra has the same functionality as yylex_init, but follows the
3318: - * convention of taking the scanner as the last argument. Note however, that
3319: - * this is a *pointer* to a scanner, as it will be allocated by this call (and
3320: - * is the reason, too, why this function also must handle its own declaration).
3321: - * The user defined value in the first argument will be available to yyalloc in
3322: - * the yyextra field.
3323: - */
3324: -
3325: -int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
3326: -
3327: -{
3328: - struct yyguts_t dummy_yyguts;
3329: -
3330: - yyset_extra (yy_user_defined, &dummy_yyguts);
3331: -
3332: - if (ptr_yy_globals == NULL){
3333: - errno = EINVAL;
3334: - return 1;
3335: - }
3336: -
3337: - *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
3338: -
3339: - if (*ptr_yy_globals == NULL){
3340: - errno = ENOMEM;
3341: - return 1;
3342: - }
3343: -
3344: - /* By setting to 0xAA, we expose bugs in
3345: - yy_init_globals. Leave at 0x00 for releases. */
3346: - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
3347: -
3348: - yyset_extra (yy_user_defined, *ptr_yy_globals);
3349: -
3350: - return yy_init_globals ( *ptr_yy_globals );
3351: -}
3352: -
3353: -static int yy_init_globals (yyscan_t yyscanner)
3354: -{
3355: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3356: - /* Initialization is the same as for the non-reentrant scanner.
3357: - * This function is called from yylex_destroy(), so don't allocate here.
3358: - */
3359: -
3360: - yyg->yy_buffer_stack = 0;
3361: - yyg->yy_buffer_stack_top = 0;
3362: - yyg->yy_buffer_stack_max = 0;
3363: - yyg->yy_c_buf_p = (char *) 0;
3364: - yyg->yy_init = 0;
3365: - yyg->yy_start = 0;
3366: -
3367: - yyg->yy_start_stack_ptr = 0;
3368: - yyg->yy_start_stack_depth = 0;
3369: - yyg->yy_start_stack = NULL;
3370: -
3371: -/* Defined in main.c */
3372: -#ifdef YY_STDINIT
3373: - yyin = stdin;
3374: - yyout = stdout;
3375: -#else
3376: - yyin = (FILE *) 0;
3377: - yyout = (FILE *) 0;
3378: -#endif
3379: -
3380: - /* For future reference: Set errno on error, since we are called by
3381: - * yylex_init()
3382: - */
3383: - return 0;
3384: -}
3385: -
3386: -/* yylex_destroy is for both reentrant and non-reentrant scanners. */
3387: -int yylex_destroy (yyscan_t yyscanner)
3388: -{
3389: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3390: -
3391: - /* Pop the buffer stack, destroying each element. */
3392: - while(YY_CURRENT_BUFFER){
3393: - yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
3394: - YY_CURRENT_BUFFER_LVALUE = NULL;
3395: - yypop_buffer_state(yyscanner);
3396: - }
3397: -
3398: - /* Destroy the stack itself. */
3399: - yyfree(yyg->yy_buffer_stack ,yyscanner);
3400: - yyg->yy_buffer_stack = NULL;
3401: -
3402: - /* Destroy the start condition stack. */
3403: - yyfree(yyg->yy_start_stack ,yyscanner );
3404: - yyg->yy_start_stack = NULL;
3405: -
3406: - /* Reset the globals. This is important in a non-reentrant scanner so the next time
3407: - * yylex() is called, initialization will occur. */
3408: - yy_init_globals( yyscanner);
3409: -
3410: - /* Destroy the main struct (reentrant only). */
3411: - yyfree ( yyscanner , yyscanner );
3412: - yyscanner = NULL;
3413: - return 0;
3414: -}
3415: -
3416: -/*
3417: - * Internal utility routines.
3418: - */
3419: -
3420: -#ifndef yytext_ptr
3421: -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
3422: -{
3423: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3424: - (void)yyg;
3425: -
3426: - int i;
3427: - for ( i = 0; i < n; ++i )
3428: - s1[i] = s2[i];
3429: -}
3430: -#endif
3431: -
3432: -#ifdef YY_NEED_STRLEN
3433: -static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
3434: -{
3435: - int n;
3436: - for ( n = 0; s[n]; ++n )
3437: - ;
3438: -
3439: - return n;
3440: -}
3441: -#endif
3442: -
3443: -void *yyalloc (yy_size_t size , yyscan_t yyscanner)
3444: -{
3445: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3446: - (void)yyg;
3447: - return (void *) malloc( size );
3448: -}
3449: -
3450: -void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
3451: -{
3452: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3453: - (void)yyg;
3454: -
3455: - /* The cast to (char *) in the following accommodates both
3456: - * implementations that use char* generic pointers, and those
3457: - * that use void* generic pointers. It works with the latter
3458: - * because both ANSI C and C++ allow castless assignment from
3459: - * any pointer type to void*, and deal with argument conversions
3460: - * as though doing an assignment.
3461: - */
3462: - return (void *) realloc( (char *) ptr, size );
3463: -}
3464: -
3465: -void yyfree (void * ptr , yyscan_t yyscanner)
3466: -{
3467: - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3468: - (void)yyg;
3469: - free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
3470: -}
3471: -
3472: -#define YYTABLES_NAME "yytables"
3473: -
3474: -#line 171 "lex.l"
3475: -
3476: -
3477: -
3478: diff --git a/src/lib/lex.l b/src/lib/lex.l
3479: index 13c48a7..38a1484 100644
3480: --- a/src/lib/lex.l
3481: +++ b/src/lib/lex.l
3482: @@ -19,89 +19,18 @@
3483:
3484: %{
3485: #define YYSTYPE lreg_t
3486: -#define YY_DECL int yylex(YYSTYPE *lvalp, void *yyscanner)
3487: -#define YY_NO_INPUT
3488: +
3489: #include <ctype.h>
3490: #include <strings.h>
3491:
3492: -#include "config.h"
3493: -#include "lac.h"
3494: -#include "sexpr_parse.h"
3495: -
3496: -
3497: -#ifdef HAVE_READLINE
3498: -#ifdef HAVE_READLINE_READLINE_H
3499: -#include <readline/readline.h>
3500: -#else
3501: -#include <readline.h>
3502: -#endif
3503: -#ifdef HAVE_READLINE_HISTORY_H
3504: -#include <readline/history.h>
3505: -#else
3506: -#include <history.h>
3507: -#endif
3508: -
3509: -static int readline_getc(void)
3510: -{
3511: - static int curchar = 0;
3512: - static char *buf = NULL;
3513: -
3514: - /* First run */
3515: - if ( buf == NULL ) {
3516: - buf = readline("LAC>");
3517: - if ( buf != NULL && *buf != '\0' )
3518: - add_history(buf);
3519: - curchar = 0;
3520: - }
3521: -
3522: - if ( buf == NULL )
3523: - return EOF;
3524: - if ( buf[curchar] == '\0' ) {
3525: - free(buf);
3526: - buf = NULL;
3527: - return '\n';
3528: - }
3529: -
3530: - return buf[curchar++];
3531: -}
3532: -
3533: -#else
3534: -#define readline_getc() getchar()
3535: -#endif
3536: -
3537: -#define YY_INPUT(buf,result,max_size) \
3538: - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
3539: - { \
3540: - int c = '*'; \
3541: - size_t n; \
3542: - for ( n = 0; n < max_size && \
3543: - (c = readline_getc())!=EOF && c!='\n'; ++n ) \
3544: - buf[n] = (char) c; \
3545: - if ( c == '\n' ) \
3546: - buf[n++] = (char) c; \
3547: - if ( c == EOF && ferror( yyin ) ) \
3548: - YY_FATAL_ERROR( "input in flex scanner failed" ); \
3549: - result = n; \
3550: - } \
3551: - else \
3552: - { \
3553: - errno=0; \
3554: - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
3555: - { \
3556: - if( errno != EINTR) \
3557: - { \
3558: - YY_FATAL_ERROR( "input in flex scanner failed" ); \
3559: - break; \
3560: - } \
3561: - errno=0; \
3562: - clearerr(yyin); \
3563: - } \
3564: - }\
3565: -
3566: +#include <lac.h>
3567: +#include "sexpr.h"
3568: +#include "private.h"
3569: %}
3570:
3571: %option noyywrap
3572: %option reentrant
3573: +%option bison-bridge
3574:
3575: WHITESPACE [\ \t\n]
3576: DIGIT [0-9]
3577: @@ -121,9 +50,7 @@ SIGN [+|-]
3578:
3579: errno = 0;
3580: n = strtol(yytext, (char **)NULL, 10);
3581: - if ( errno == ERANGE )
3582: - raise_exception("Integer overflow in input", NIL);
3583: - *lvalp = lac_extty_box(LREG_INTEGER, (void *)n, 0);
3584: + *yylval = lac_extty_box(LREG_INTEGER, (void *)n, 0);
3585: return INTEGER;
3586: }
3587:
3588: @@ -134,22 +61,22 @@ SIGN [+|-]
3589: n = strtol(yytext+2, (char **)NULL, 16);
3590: if ( errno == ERANGE )
3591: raise_exception("Integer overflow in input", NIL);
3592: - *lvalp = lac_extty_box(LREG_INTEGER, (void *)n, 0);
3593: + *yylval = lac_extty_box(LREG_INTEGER, (void *)n, 0);
3594: return INTEGER;
3595: -}
3596: + }
3597:
3598: (NIL|nil) {
3599: - *lvalp = NIL;
3600: + *yylval = NIL;
3601: return NIHIL;
3602: -}
3603: + }
3604:
3605: \"[^\"]*\" {
3606: size_t len = strlen(yytext);
3607: char *s = lac_alloc(len - 1);
3608: memcpy(s, yytext+1, len - 2);
3609: - *lvalp = lreg_raw(s, LREG_STRING);
3610: + *yylval = lreg_raw(s, LREG_STRING);
3611: return STRING;
3612: -}
3613: + }
3614:
3615: (({DIGIT}+({SPECIAL}|{ALPHA}))|{ALPHA}|{SP_INIT})({SPECIAL}|{ALPHA}|{DIGIT})* {
3616: int i;
3617: @@ -157,15 +84,138 @@ SIGN [+|-]
3618: char *s = lac_alloc(len + 1);
3619: for (i = 0; i < len; i++)
3620: *(s+i) = toupper((int)*(yytext+i));
3621: - *lvalp = intern_symbol(s);
3622: + *yylval = intern_symbol(s);
3623: return SYMBOL;
3624: -};
3625: + }
3626:
3627: ,@ { return COMMA_AT; }
3628:
3629: -<<EOF>> { return ENDOFFILE; }
3630: +\' { return QUOTE; }
3631: +
3632: +` { return QUASI; }
3633: +
3634: +, { return COMMA; }
3635: +
3636: +\( { return OPAREN; }
3637: +
3638: +\) { return CPAREN; }
3639:
3640: -. { return *yytext; }
3641: +\. { return DOT; }
3642: +
3643: +<<EOF>> { return -1; }
3644: +
3645: +. { return -1; }
3646:
3647:
3648: %%
3649: +
3650: +static void _sexpr_parse(yyscan_t yyscan, struct parse_cb *cb)
3651: +{
3652: + int v;
3653: + lreg_t lr;
3654: + void *parser;
3655: +
3656: + parser = ParseAlloc(malloc);
3657: +
3658: + while((v = yylex(&lr, yyscan)) != -1) {
3659: + Parse(parser, v, lr, cb);
3660: + }
3661: + Parse(parser, ENDPARSE, lr, cb);
3662: +
3663: + /* XXX: ON EXCEPTION, destroy parser and retrow. */
3664: +
3665: + ParseFree(parser, free);
3666: + yylex_destroy(yyscan);
3667: +}
3668: +
3669: +lreg_t sexpr_parse_string(char *s, lreg_t (*fn)(lreg_t,void*), void *opq)
3670: +{
3671: + yyscan_t yyscan;
3672: + struct parse_cb cb;
3673: +
3674: + cb.fn = fn;
3675: + cb.opq = opq;
3676: + cb.res = NIL;
3677: +
3678: + yylex_init(&yyscan);
3679: + yy_scan_string(s, yyscan);
3680: +
3681: + _sexpr_parse(yyscan, &cb);
3682: + return cb.res;
3683: +}
3684: +
3685: +lreg_t sexpr_parse_file(FILE *f, lreg_t (*fn)(lreg_t,void*), void *opq)
3686: +{
3687: + yyscan_t yyscan;
3688: + struct parse_cb cb;
3689: +
3690: + cb.fn = fn;
3691: + cb.opq = opq;
3692: + cb.res = NIL;
3693: +
3694: + yylex_init(&yyscan);
3695: + yyset_in(f, yyscan);
3696: +
3697: + _sexpr_parse(yyscan, &cb);
3698: + return cb.res;
3699: +}
3700: +
3701: +
3702: +/*
3703: + * Print
3704: + */
3705: +
3706: +static void sexpr_print_cons(FILE *f, lreg_t lr, const char *h)
3707: +{
3708: + lreg_t a = car(lr);
3709: + lreg_t d = cdr(lr);
3710: +
3711: + printf(h);
3712: + sexpr_fprint(f, a);
3713: +
3714: + if (d == NIL) {
3715: + fprintf(f, ")");
3716: + return;
3717: + }
3718: +
3719: + if (lreg_raw_type(d) == LREG_CONS)
3720: + sexpr_print_cons(f, d, " ");
3721: + else
3722: + {
3723: + fprintf(f, " . ");
3724: + sexpr_fprint(f, cdr(lr));
3725: + fprintf(f, ")");
3726: + }
3727: +}
3728: +
3729: +void sexpr_fprint(FILE *f, lreg_t lr)
3730: +{
3731: + switch ( lreg_type(lr) )
3732: + {
3733: + case LREG_NIL:
3734: + fprintf(f, "()");
3735: + break;
3736: + case LREG_SYMBOL:
3737: + fprintf(f, "%s", (char *)lreg_raw_ptr(lr));
3738: + break;
3739: + case LREG_STRING:
3740: + fprintf(f, "\"%s\"", (char *)lreg_raw_ptr(lr));
3741: + break;
3742: + case LREG_CONS:
3743: + sexpr_print_cons(f, lr, "(");
3744: + break;
3745: + case LREG_MACRO:
3746: + fprintf(f, "<#MACRO>");
3747: + break;
3748: + case LREG_LAMBDA:
3749: + fprintf(f, "<#LAMBDA>");
3750: + break;
3751: + case LREG_LLPROC:
3752: + fprintf(f, "<#LLPROC>");
3753: + break;
3754: + default:
3755: + if ( !lac_extty_print(f, lr) )
3756: + fprintf(f, "<??? %d>",(int)lreg_type(lr));
3757: + }
3758: + return;
3759: +}
3760: diff --git a/src/lib/private.h b/src/lib/private.h
3761: index 4cc76bd..4e6a085 100644
3762: --- a/src/lib/private.h
3763: +++ b/src/lib/private.h
3764: @@ -124,6 +124,7 @@ static inline lreg_t get_proc_body(lreg_t lr)
3765: siglongjmp(p->buf, 1); \
3766: } while(0)
3767:
3768: +
3769: /*
3770: * Environment management.
3771: */
3772: @@ -135,4 +136,18 @@ int env_set(lenv_t * env, lreg_t key, lreg_t value);
3773: void env_pushnew(lenv_t * env, lenv_t * new);
3774:
3775:
3776: +/*
3777: + * Parser Interface.
3778: + */
3779: +
3780: +struct parse_cb {
3781: + lreg_t (*fn)(lreg_t, void *);
3782: + void *opq;
3783: + lreg_t res;
3784: +};
3785: +
3786: +void *ParseAlloc(void *(*)(size_t));
3787: +void Parse(void *, int, lreg_t, struct parse_cb *);
3788: +void ParseFree(void *, void (*)(void*));
3789: +
3790: #endif /* PRIVATE_H */
3791: diff --git a/src/lib/sexpr.c b/src/lib/sexpr.c
3792: new file mode 100644
3793: index 0000000..bd24ab5
3794: --- /dev/null
3795: +++ b/src/lib/sexpr.c
3796: @@ -0,0 +1,1152 @@
3797: +/*
3798: +** 2000-05-29
3799: +**
3800: +** The author disclaims copyright to this source code. In place of
3801: +** a legal notice, here is a blessing:
3802: +**
3803: +** May you do good and not evil.
3804: +** May you find forgiveness for yourself and forgive others.
3805: +** May you share freely, never taking more than you give.
3806: +**
3807: +*************************************************************************
3808: +** Driver template for the LEMON parser generator.
3809: +**
3810: +** The "lemon" program processes an LALR(1) input grammar file, then uses
3811: +** this template to construct a parser. The "lemon" program inserts text
3812: +** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
3813: +** interstitial "-" characters) contained in this template is changed into
3814: +** the value of the %name directive from the grammar. Otherwise, the content
3815: +** of this template is copied straight through into the generate parser
3816: +** source file.
3817: +**
3818: +** The following is the concatenation of all %include directives from the
3819: +** input grammar file:
3820: +*/
3821: +#include <stdio.h>
3822: +/************ Begin %include sections from the grammar ************************/
3823: +#line 1 "sexpr.lmn"
3824: + #include <lac.h>
3825: +#line 2 "sexpr.lmn"
3826: + #include <assert.h>
3827: +#line 3 "sexpr.lmn"
3828: + #include "private.h"
3829: +#line 34 "sexpr.c"
3830: +/**************** End of %include directives **********************************/
3831: +/* These constants specify the various numeric values for terminal symbols
3832: +** in a format understandable to "makeheaders". This section is blank unless
3833: +** "lemon" is run with the "-m" command-line option.
3834: +***************** Begin makeheaders token definitions *************************/
3835: +/**************** End makeheaders token definitions ***************************/
3836: +
3837: +/* The next sections is a series of control #defines.
3838: +** various aspects of the generated parser.
3839: +** YYCODETYPE is the data type used to store the integer codes
3840: +** that represent terminal and non-terminal symbols.
3841: +** "unsigned char" is used if there are fewer than
3842: +** 256 symbols. Larger types otherwise.
3843: +** YYNOCODE is a number of type YYCODETYPE that is not used for
3844: +** any terminal or nonterminal symbol.
3845: +** YYFALLBACK If defined, this indicates that one or more tokens
3846: +** (also known as: "terminal symbols") have fall-back
3847: +** values which should be used if the original symbol
3848: +** would not parse. This permits keywords to sometimes
3849: +** be used as identifiers, for example.
3850: +** YYACTIONTYPE is the data type used for "action codes" - numbers
3851: +** that indicate what to do in response to the next
3852: +** token.
3853: +** ParseTOKENTYPE is the data type used for minor type for terminal
3854: +** symbols. Background: A "minor type" is a semantic
3855: +** value associated with a terminal or non-terminal
3856: +** symbols. For example, for an "ID" terminal symbol,
3857: +** the minor type might be the name of the identifier.
3858: +** Each non-terminal can have a different minor type.
3859: +** Terminal symbols all have the same minor type, though.
3860: +** This macros defines the minor type for terminal
3861: +** symbols.
3862: +** YYMINORTYPE is the data type used for all minor types.
3863: +** This is typically a union of many types, one of
3864: +** which is ParseTOKENTYPE. The entry in the union
3865: +** for terminal symbols is called "yy0".
3866: +** YYSTACKDEPTH is the maximum depth of the parser's stack. If
3867: +** zero the stack is dynamically sized using realloc()
3868: +** ParseARG_SDECL A static variable declaration for the %extra_argument
3869: +** ParseARG_PDECL A parameter declaration for the %extra_argument
3870: +** ParseARG_STORE Code to store %extra_argument into yypParser
3871: +** ParseARG_FETCH Code to extract %extra_argument from yypParser
3872: +** YYERRORSYMBOL is the code number of the error symbol. If not
3873: +** defined, then do no error processing.
3874: +** YYNSTATE the combined number of states.
3875: +** YYNRULE the number of rules in the grammar
3876: +** YY_MAX_SHIFT Maximum value for shift actions
3877: +** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
3878: +** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
3879: +** YY_MIN_REDUCE Maximum value for reduce actions
3880: +** YY_ERROR_ACTION The yy_action[] code for syntax error
3881: +** YY_ACCEPT_ACTION The yy_action[] code for accept
3882: +** YY_NO_ACTION The yy_action[] code for no-op
3883: +*/
3884: +#ifndef INTERFACE
3885: +# define INTERFACE 1
3886: +#endif
3887: +/************* Begin control #defines *****************************************/
3888: +#define YYCODETYPE unsigned char
3889: +#define YYNOCODE 21
3890: +#define YYACTIONTYPE unsigned char
3891: +#define ParseTOKENTYPE lreg_t
3892: +typedef union {
3893: + int yyinit;
3894: + ParseTOKENTYPE yy0;
3895: + lreg_t yy6;
3896: + int yy41;
3897: +} YYMINORTYPE;
3898: +#ifndef YYSTACKDEPTH
3899: +#define YYSTACKDEPTH 100
3900: +#endif
3901: +#define ParseARG_SDECL struct parse_cb *cb ;
3902: +#define ParseARG_PDECL , struct parse_cb *cb
3903: +#define ParseARG_FETCH struct parse_cb *cb = yypParser->cb
3904: +#define ParseARG_STORE yypParser->cb = cb
3905: +#define YYERRORSYMBOL 13
3906: +#define YYERRSYMDT yy41
3907: +#define YYNSTATE 14
3908: +#define YYNRULE 19
3909: +#define YY_MAX_SHIFT 13
3910: +#define YY_MIN_SHIFTREDUCE 29
3911: +#define YY_MAX_SHIFTREDUCE 47
3912: +#define YY_MIN_REDUCE 48
3913: +#define YY_MAX_REDUCE 66
3914: +#define YY_ERROR_ACTION 67
3915: +#define YY_ACCEPT_ACTION 68
3916: +#define YY_NO_ACTION 69
3917: +/************* End control #defines *******************************************/
3918: +
3919: +/* Define the yytestcase() macro to be a no-op if is not already defined
3920: +** otherwise.
3921: +**
3922: +** Applications can choose to define yytestcase() in the %include section
3923: +** to a macro that can assist in verifying code coverage. For production
3924: +** code the yytestcase() macro should be turned off. But it is useful
3925: +** for testing.
3926: +*/
3927: +#ifndef yytestcase
3928: +# define yytestcase(X)
3929: +#endif
3930: +
3931: +
3932: +/* Next are the tables used to determine what action to take based on the
3933: +** current state and lookahead token. These tables are used to implement
3934: +** functions that take a state number and lookahead value and return an
3935: +** action integer.
3936: +**
3937: +** Suppose the action integer is N. Then the action is determined as
3938: +** follows
3939: +**
3940: +** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
3941: +** token onto the stack and goto state N.
3942: +**
3943: +** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
3944: +** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
3945: +**
3946: +** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
3947: +** and YY_MAX_REDUCE
3948: +**
3949: +** N == YY_ERROR_ACTION A syntax error has occurred.
3950: +**
3951: +** N == YY_ACCEPT_ACTION The parser accepts its input.
3952: +**
3953: +** N == YY_NO_ACTION No such action. Denotes unused
3954: +** slots in the yy_action[] table.
3955: +**
3956: +** The action table is constructed as a single large table named yy_action[].
3957: +** Given state S and lookahead X, the action is computed as either:
3958: +**
3959: +** (A) N = yy_action[ yy_shift_ofst[S] + X ]
3960: +** (B) N = yy_default[S]
3961: +**
3962: +** The (A) formula is preferred. The B formula is used instead if:
3963: +** (1) The yy_shift_ofst[S]+X value is out of range, or
3964: +** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or
3965: +** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT.
3966: +** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that
3967: +** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X.
3968: +** Hence only tests (1) and (2) need to be evaluated.)
3969: +**
3970: +** The formulas above are for computing the action when the lookahead is
3971: +** a terminal symbol. If the lookahead is a non-terminal (as occurs after
3972: +** a reduce action) then the yy_reduce_ofst[] array is used in place of
3973: +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
3974: +** YY_SHIFT_USE_DFLT.
3975: +**
3976: +** The following are the tables generated in this section:
3977: +**
3978: +** yy_action[] A single table containing all actions.
3979: +** yy_lookahead[] A table containing the lookahead for each entry in
3980: +** yy_action. Used to detect hash collisions.
3981: +** yy_shift_ofst[] For each state, the offset into yy_action for
3982: +** shifting terminals.
3983: +** yy_reduce_ofst[] For each state, the offset into yy_action for
3984: +** shifting non-terminals after a reduce.
3985: +** yy_default[] Default action for each state.
3986: +**
3987: +*********** Begin parsing tables **********************************************/
3988: +#define YY_ACTTAB_COUNT (90)
3989: +static const YYACTIONTYPE yy_action[] = {
3990: + /* 0 */ 9, 8, 7, 6, 3, 5, 66, 42, 43, 44,
3991: + /* 10 */ 45, 9, 8, 7, 6, 3, 39, 37, 42, 43,
3992: + /* 20 */ 44, 45, 13, 9, 8, 7, 6, 3, 36, 65,
3993: + /* 30 */ 42, 43, 44, 45, 9, 8, 7, 6, 3, 50,
3994: + /* 40 */ 50, 42, 43, 44, 45, 2, 50, 50, 31, 38,
3995: + /* 50 */ 11, 2, 50, 50, 31, 38, 40, 10, 50, 68,
3996: + /* 60 */ 4, 50, 50, 1, 50, 29, 31, 38, 31, 38,
3997: + /* 70 */ 12, 50, 35, 31, 38, 31, 38, 50, 34, 50,
3998: + /* 80 */ 33, 31, 38, 31, 38, 32, 50, 50, 31, 38,
3999: +};
4000: +static const YYCODETYPE yy_lookahead[] = {
4001: + /* 0 */ 2, 3, 4, 5, 6, 7, 0, 9, 10, 11,
4002: + /* 10 */ 12, 2, 3, 4, 5, 6, 8, 8, 9, 10,
4003: + /* 20 */ 11, 12, 1, 2, 3, 4, 5, 6, 8, 0,
4004: + /* 30 */ 9, 10, 11, 12, 2, 3, 4, 5, 6, 20,
4005: + /* 40 */ 20, 9, 10, 11, 12, 14, 20, 20, 17, 18,
4006: + /* 50 */ 19, 14, 20, 20, 17, 18, 19, 13, 20, 15,
4007: + /* 60 */ 16, 20, 20, 14, 20, 14, 17, 18, 17, 18,
4008: + /* 70 */ 14, 20, 14, 17, 18, 17, 18, 20, 14, 20,
4009: + /* 80 */ 14, 17, 18, 17, 18, 14, 20, 20, 17, 18,
4010: +};
4011: +#define YY_SHIFT_USE_DFLT (90)
4012: +#define YY_SHIFT_COUNT (13)
4013: +#define YY_SHIFT_MIN (-2)
4014: +#define YY_SHIFT_MAX (32)
4015: +static const signed char yy_shift_ofst[] = {
4016: + /* 0 */ 90, -2, 32, 9, 21, 32, 32, 32, 32, 32,
4017: + /* 10 */ 6, 8, 20, 29,
4018: +};
4019: +#define YY_REDUCE_USE_DFLT (-1)
4020: +#define YY_REDUCE_COUNT (9)
4021: +#define YY_REDUCE_MIN (0)
4022: +#define YY_REDUCE_MAX (71)
4023: +static const signed char yy_reduce_ofst[] = {
4024: + /* 0 */ 44, 31, 37, 49, 51, 56, 58, 64, 66, 71,
4025: +};
4026: +static const YYACTIONTYPE yy_default[] = {
4027: + /* 0 */ 49, 60, 60, 67, 67, 67, 67, 67, 67, 67,
4028: + /* 10 */ 67, 67, 67, 67,
4029: +};
4030: +/********** End of lemon-generated parsing tables *****************************/
4031: +
4032: +/* The next table maps tokens (terminal symbols) into fallback tokens.
4033: +** If a construct like the following:
4034: +**
4035: +** %fallback ID X Y Z.
4036: +**
4037: +** appears in the grammar, then ID becomes a fallback token for X, Y,
4038: +** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
4039: +** but it does not parse, the type of the token is changed to ID and
4040: +** the parse is retried before an error is thrown.
4041: +**
4042: +** This feature can be used, for example, to cause some keywords in a language
4043: +** to revert to identifiers if they keyword does not apply in the context where
4044: +** it appears.
4045: +*/
4046: +#ifdef YYFALLBACK
4047: +static const YYCODETYPE yyFallback[] = {
4048: +};
4049: +#endif /* YYFALLBACK */
4050: +
4051: +/* The following structure represents a single element of the
4052: +** parser's stack. Information stored includes:
4053: +**
4054: +** + The state number for the parser at this level of the stack.
4055: +**
4056: +** + The value of the token stored at this level of the stack.
4057: +** (In other words, the "major" token.)
4058: +**
4059: +** + The semantic value stored at this level of the stack. This is
4060: +** the information used by the action routines in the grammar.
4061: +** It is sometimes called the "minor" token.
4062: +**
4063: +** After the "shift" half of a SHIFTREDUCE action, the stateno field
4064: +** actually contains the reduce action for the second half of the
4065: +** SHIFTREDUCE.
4066: +*/
4067: +struct yyStackEntry {
4068: + YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
4069: + YYCODETYPE major; /* The major token value. This is the code
4070: + ** number for the token at this stack level */
4071: + YYMINORTYPE minor; /* The user-supplied minor token value. This
4072: + ** is the value of the token */
4073: +};
4074: +typedef struct yyStackEntry yyStackEntry;
4075: +
4076: +/* The state of the parser is completely contained in an instance of
4077: +** the following structure */
4078: +struct yyParser {
4079: + yyStackEntry *yytos; /* Pointer to top element of the stack */
4080: +#ifdef YYTRACKMAXSTACKDEPTH
4081: + int yyhwm; /* High-water mark of the stack */
4082: +#endif
4083: +#ifndef YYNOERRORRECOVERY
4084: + int yyerrcnt; /* Shifts left before out of the error */
4085: +#endif
4086: + ParseARG_SDECL /* A place to hold %extra_argument */
4087: +#if YYSTACKDEPTH<=0
4088: + int yystksz; /* Current side of the stack */
4089: + yyStackEntry *yystack; /* The parser's stack */
4090: + yyStackEntry yystk0; /* First stack entry */
4091: +#else
4092: + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
4093: +#endif
4094: +};
4095: +typedef struct yyParser yyParser;
4096: +
4097: +#ifndef NDEBUG
4098: +#include <stdio.h>
4099: +static FILE *yyTraceFILE = 0;
4100: +static char *yyTracePrompt = 0;
4101: +#endif /* NDEBUG */
4102: +
4103: +#ifndef NDEBUG
4104: +/*
4105: +** Turn parser tracing on by giving a stream to which to write the trace
4106: +** and a prompt to preface each trace message. Tracing is turned off
4107: +** by making either argument NULL
4108: +**
4109: +** Inputs:
4110: +** <ul>
4111: +** <li> A FILE* to which trace output should be written.
4112: +** If NULL, then tracing is turned off.
4113: +** <li> A prefix string written at the beginning of every
4114: +** line of trace output. If NULL, then tracing is
4115: +** turned off.
4116: +** </ul>
4117: +**
4118: +** Outputs:
4119: +** None.
4120: +*/
4121: +void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
4122: + yyTraceFILE = TraceFILE;
4123: + yyTracePrompt = zTracePrompt;
4124: + if( yyTraceFILE==0 ) yyTracePrompt = 0;
4125: + else if( yyTracePrompt==0 ) yyTraceFILE = 0;
4126: +}
4127: +#endif /* NDEBUG */
4128: +
4129: +#ifndef NDEBUG
4130: +/* For tracing shifts, the names of all terminals and nonterminals
4131: +** are required. The following table supplies these names */
4132: +static const char *const yyTokenName[] = {
4133: + "$", "ENDPARSE", "QUOTE", "QUASI",
4134: + "COMMA_AT", "COMMA", "OPAREN", "DOT",
4135: + "CPAREN", "SYMBOL", "STRING", "INTEGER",
4136: + "NIHIL", "error", "sexpr", "input",
4137: + "sexprlist", "atom", "list", "listelem",
4138: +};
4139: +#endif /* NDEBUG */
4140: +
4141: +#ifndef NDEBUG
4142: +/* For tracing reduce actions, the names of all rules are required.
4143: +*/
4144: +static const char *const yyRuleName[] = {
4145: + /* 0 */ "sexprlist ::= sexprlist sexpr",
4146: + /* 1 */ "sexprlist ::=",
4147: + /* 2 */ "sexpr ::= atom",
4148: + /* 3 */ "sexpr ::= QUOTE sexpr",
4149: + /* 4 */ "sexpr ::= QUASI sexpr",
4150: + /* 5 */ "sexpr ::= COMMA_AT sexpr",
4151: + /* 6 */ "sexpr ::= COMMA sexpr",
4152: + /* 7 */ "sexpr ::= OPAREN sexpr DOT sexpr CPAREN",
4153: + /* 8 */ "sexpr ::= OPAREN CPAREN",
4154: + /* 9 */ "sexpr ::= list",
4155: + /* 10 */ "list ::= OPAREN sexpr listelem CPAREN",
4156: + /* 11 */ "listelem ::= sexpr listelem",
4157: + /* 12 */ "listelem ::=",
4158: + /* 13 */ "atom ::= SYMBOL",
4159: + /* 14 */ "atom ::= STRING",
4160: + /* 15 */ "atom ::= INTEGER",
4161: + /* 16 */ "atom ::= NIHIL",
4162: + /* 17 */ "input ::= sexprlist ENDPARSE",
4163: + /* 18 */ "input ::= error",
4164: +};
4165: +#endif /* NDEBUG */
4166: +
4167: +
4168: +#if YYSTACKDEPTH<=0
4169: +/*
4170: +** Try to increase the size of the parser stack. Return the number
4171: +** of errors. Return 0 on success.
4172: +*/
4173: +static int yyGrowStack(yyParser *p){
4174: + int newSize;
4175: + int idx;
4176: + yyStackEntry *pNew;
4177: +
4178: + newSize = p->yystksz*2 + 100;
4179: + idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
4180: + if( p->yystack==&p->yystk0 ){
4181: + pNew = malloc(newSize*sizeof(pNew[0]));
4182: + if( pNew ) pNew[0] = p->yystk0;
4183: + }else{
4184: + pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
4185: + }
4186: + if( pNew ){
4187: + p->yystack = pNew;
4188: + p->yytos = &p->yystack[idx];
4189: +#ifndef NDEBUG
4190: + if( yyTraceFILE ){
4191: + fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
4192: + yyTracePrompt, p->yystksz, newSize);
4193: + }
4194: +#endif
4195: + p->yystksz = newSize;
4196: + }
4197: + return pNew==0;
4198: +}
4199: +#endif
4200: +
4201: +/* Datatype of the argument to the memory allocated passed as the
4202: +** second argument to ParseAlloc() below. This can be changed by
4203: +** putting an appropriate #define in the %include section of the input
4204: +** grammar.
4205: +*/
4206: +#ifndef YYMALLOCARGTYPE
4207: +# define YYMALLOCARGTYPE size_t
4208: +#endif
4209: +
4210: +/* Initialize a new parser that has already been allocated.
4211: +*/
4212: +void ParseInit(void *yypParser){
4213: + yyParser *pParser = (yyParser*)yypParser;
4214: +#ifdef YYTRACKMAXSTACKDEPTH
4215: + pParser->yyhwm = 0;
4216: +#endif
4217: +#if YYSTACKDEPTH<=0
4218: + pParser->yytos = NULL;
4219: + pParser->yystack = NULL;
4220: + pParser->yystksz = 0;
4221: + if( yyGrowStack(pParser) ){
4222: + pParser->yystack = &pParser->yystk0;
4223: + pParser->yystksz = 1;
4224: + }
4225: +#endif
4226: +#ifndef YYNOERRORRECOVERY
4227: + pParser->yyerrcnt = -1;
4228: +#endif
4229: + pParser->yytos = pParser->yystack;
4230: + pParser->yystack[0].stateno = 0;
4231: + pParser->yystack[0].major = 0;
4232: +}
4233: +
4234: +#ifndef Parse_ENGINEALWAYSONSTACK
4235: +/*
4236: +** This function allocates a new parser.
4237: +** The only argument is a pointer to a function which works like
4238: +** malloc.
4239: +**
4240: +** Inputs:
4241: +** A pointer to the function used to allocate memory.
4242: +**
4243: +** Outputs:
4244: +** A pointer to a parser. This pointer is used in subsequent calls
4245: +** to Parse and ParseFree.
4246: +*/
4247: +void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
4248: + yyParser *pParser;
4249: + pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
4250: + if( pParser ) ParseInit(pParser);
4251: + return pParser;
4252: +}
4253: +#endif /* Parse_ENGINEALWAYSONSTACK */
4254: +
4255: +
4256: +/* The following function deletes the "minor type" or semantic value
4257: +** associated with a symbol. The symbol can be either a terminal
4258: +** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
4259: +** a pointer to the value to be deleted. The code used to do the
4260: +** deletions is derived from the %destructor and/or %token_destructor
4261: +** directives of the input grammar.
4262: +*/
4263: +static void yy_destructor(
4264: + yyParser *yypParser, /* The parser */
4265: + YYCODETYPE yymajor, /* Type code for object to destroy */
4266: + YYMINORTYPE *yypminor /* The object to be destroyed */
4267: +){
4268: + ParseARG_FETCH;
4269: + switch( yymajor ){
4270: + /* Here is inserted the actions which take place when a
4271: + ** terminal or non-terminal is destroyed. This can happen
4272: + ** when the symbol is popped from the stack during a
4273: + ** reduce or during error processing or when a parser is
4274: + ** being destroyed before it is finished parsing.
4275: + **
4276: + ** Note: during a reduce, the only symbols destroyed are those
4277: + ** which appear on the RHS of the rule, but which are *not* used
4278: + ** inside the C code.
4279: + */
4280: +/********* Begin destructor definitions ***************************************/
4281: +/********* End destructor definitions *****************************************/
4282: + default: break; /* If no destructor action specified: do nothing */
4283: + }
4284: +}
4285: +
4286: +/*
4287: +** Pop the parser's stack once.
4288: +**
4289: +** If there is a destructor routine associated with the token which
4290: +** is popped from the stack, then call it.
4291: +*/
4292: +static void yy_pop_parser_stack(yyParser *pParser){
4293: + yyStackEntry *yytos;
4294: + assert( pParser->yytos!=0 );
4295: + assert( pParser->yytos > pParser->yystack );
4296: + yytos = pParser->yytos--;
4297: +#ifndef NDEBUG
4298: + if( yyTraceFILE ){
4299: + fprintf(yyTraceFILE,"%sPopping %s\n",
4300: + yyTracePrompt,
4301: + yyTokenName[yytos->major]);
4302: + }
4303: +#endif
4304: + yy_destructor(pParser, yytos->major, &yytos->minor);
4305: +}
4306: +
4307: +/*
4308: +** Clear all secondary memory allocations from the parser
4309: +*/
4310: +void ParseFinalize(void *p){
4311: + yyParser *pParser = (yyParser*)p;
4312: + while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
4313: +#if YYSTACKDEPTH<=0
4314: + if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
4315: +#endif
4316: +}
4317: +
4318: +#ifndef Parse_ENGINEALWAYSONSTACK
4319: +/*
4320: +** Deallocate and destroy a parser. Destructors are called for
4321: +** all stack elements before shutting the parser down.
4322: +**
4323: +** If the YYPARSEFREENEVERNULL macro exists (for example because it
4324: +** is defined in a %include section of the input grammar) then it is
4325: +** assumed that the input pointer is never NULL.
4326: +*/
4327: +void ParseFree(
4328: + void *p, /* The parser to be deleted */
4329: + void (*freeProc)(void*) /* Function used to reclaim memory */
4330: +){
4331: +#ifndef YYPARSEFREENEVERNULL
4332: + if( p==0 ) return;
4333: +#endif
4334: + ParseFinalize(p);
4335: + (*freeProc)(p);
4336: +}
4337: +#endif /* Parse_ENGINEALWAYSONSTACK */
4338: +
4339: +/*
4340: +** Return the peak depth of the stack for a parser.
4341: +*/
4342: +#ifdef YYTRACKMAXSTACKDEPTH
4343: +int ParseStackPeak(void *p){
4344: + yyParser *pParser = (yyParser*)p;
4345: + return pParser->yyhwm;
4346: +}
4347: +#endif
4348: +
4349: +/*
4350: +** Find the appropriate action for a parser given the terminal
4351: +** look-ahead token iLookAhead.
4352: +*/
4353: +static unsigned int yy_find_shift_action(
4354: + yyParser *pParser, /* The parser */
4355: + YYCODETYPE iLookAhead /* The look-ahead token */
4356: +){
4357: + int i;
4358: + int stateno = pParser->yytos->stateno;
4359: +
4360: + if( stateno>=YY_MIN_REDUCE ) return stateno;
4361: + assert( stateno <= YY_SHIFT_COUNT );
4362: + do{
4363: + i = yy_shift_ofst[stateno];
4364: + assert( iLookAhead!=YYNOCODE );
4365: + i += iLookAhead;
4366: + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
4367: +#ifdef YYFALLBACK
4368: + YYCODETYPE iFallback; /* Fallback token */
4369: + if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
4370: + && (iFallback = yyFallback[iLookAhead])!=0 ){
4371: +#ifndef NDEBUG
4372: + if( yyTraceFILE ){
4373: + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
4374: + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
4375: + }
4376: +#endif
4377: + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
4378: + iLookAhead = iFallback;
4379: + continue;
4380: + }
4381: +#endif
4382: +#ifdef YYWILDCARD
4383: + {
4384: + int j = i - iLookAhead + YYWILDCARD;
4385: + if(
4386: +#if YY_SHIFT_MIN+YYWILDCARD<0
4387: + j>=0 &&
4388: +#endif
4389: +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
4390: + j<YY_ACTTAB_COUNT &&
4391: +#endif
4392: + yy_lookahead[j]==YYWILDCARD && iLookAhead>0
4393: + ){
4394: +#ifndef NDEBUG
4395: + if( yyTraceFILE ){
4396: + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
4397: + yyTracePrompt, yyTokenName[iLookAhead],
4398: + yyTokenName[YYWILDCARD]);
4399: + }
4400: +#endif /* NDEBUG */
4401: + return yy_action[j];
4402: + }
4403: + }
4404: +#endif /* YYWILDCARD */
4405: + return yy_default[stateno];
4406: + }else{
4407: + return yy_action[i];
4408: + }
4409: + }while(1);
4410: +}
4411: +
4412: +/*
4413: +** Find the appropriate action for a parser given the non-terminal
4414: +** look-ahead token iLookAhead.
4415: +*/
4416: +static int yy_find_reduce_action(
4417: + int stateno, /* Current state number */
4418: + YYCODETYPE iLookAhead /* The look-ahead token */
4419: +){
4420: + int i;
4421: +#ifdef YYERRORSYMBOL
4422: + if( stateno>YY_REDUCE_COUNT ){
4423: + return yy_default[stateno];
4424: + }
4425: +#else
4426: + assert( stateno<=YY_REDUCE_COUNT );
4427: +#endif
4428: + i = yy_reduce_ofst[stateno];
4429: + assert( i!=YY_REDUCE_USE_DFLT );
4430: + assert( iLookAhead!=YYNOCODE );
4431: + i += iLookAhead;
4432: +#ifdef YYERRORSYMBOL
4433: + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
4434: + return yy_default[stateno];
4435: + }
4436: +#else
4437: + assert( i>=0 && i<YY_ACTTAB_COUNT );
4438: + assert( yy_lookahead[i]==iLookAhead );
4439: +#endif
4440: + return yy_action[i];
4441: +}
4442: +
4443: +/*
4444: +** The following routine is called if the stack overflows.
4445: +*/
4446: +static void yyStackOverflow(yyParser *yypParser){
4447: + ParseARG_FETCH;
4448: +#ifndef NDEBUG
4449: + if( yyTraceFILE ){
4450: + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
4451: + }
4452: +#endif
4453: + while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
4454: + /* Here code is inserted which will execute if the parser
4455: + ** stack every overflows */
4456: +/******** Begin %stack_overflow code ******************************************/
4457: +/******** End %stack_overflow code ********************************************/
4458: + ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
4459: +}
4460: +
4461: +/*
4462: +** Print tracing information for a SHIFT action
4463: +*/
4464: +#ifndef NDEBUG
4465: +static void yyTraceShift(yyParser *yypParser, int yyNewState){
4466: + if( yyTraceFILE ){
4467: + if( yyNewState<YYNSTATE ){
4468: + fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n",
4469: + yyTracePrompt,yyTokenName[yypParser->yytos->major],
4470: + yyNewState);
4471: + }else{
4472: + fprintf(yyTraceFILE,"%sShift '%s'\n",
4473: + yyTracePrompt,yyTokenName[yypParser->yytos->major]);
4474: + }
4475: + }
4476: +}
4477: +#else
4478: +# define yyTraceShift(X,Y)
4479: +#endif
4480: +
4481: +/*
4482: +** Perform a shift action.
4483: +*/
4484: +static void yy_shift(
4485: + yyParser *yypParser, /* The parser to be shifted */
4486: + int yyNewState, /* The new state to shift in */
4487: + int yyMajor, /* The major token to shift in */
4488: + ParseTOKENTYPE yyMinor /* The minor token to shift in */
4489: +){
4490: + yyStackEntry *yytos;
4491: + yypParser->yytos++;
4492: +#ifdef YYTRACKMAXSTACKDEPTH
4493: + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
4494: + yypParser->yyhwm++;
4495: + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
4496: + }
4497: +#endif
4498: +#if YYSTACKDEPTH>0
4499: + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){
4500: + yypParser->yytos--;
4501: + yyStackOverflow(yypParser);
4502: + return;
4503: + }
4504: +#else
4505: + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
4506: + if( yyGrowStack(yypParser) ){
4507: + yypParser->yytos--;
4508: + yyStackOverflow(yypParser);
4509: + return;
4510: + }
4511: + }
4512: +#endif
4513: + if( yyNewState > YY_MAX_SHIFT ){
4514: + yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
4515: + }
4516: + yytos = yypParser->yytos;
4517: + yytos->stateno = (YYACTIONTYPE)yyNewState;
4518: + yytos->major = (YYCODETYPE)yyMajor;
4519: + yytos->minor.yy0 = yyMinor;
4520: + yyTraceShift(yypParser, yyNewState);
4521: +}
4522: +
4523: +/* The following table contains information about every rule that
4524: +** is used during the reduce.
4525: +*/
4526: +static const struct {
4527: + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
4528: + unsigned char nrhs; /* Number of right-hand side symbols in the rule */
4529: +} yyRuleInfo[] = {
4530: + { 16, 2 },
4531: + { 16, 0 },
4532: + { 14, 1 },
4533: + { 14, 2 },
4534: + { 14, 2 },
4535: + { 14, 2 },
4536: + { 14, 2 },
4537: + { 14, 5 },
4538: + { 14, 2 },
4539: + { 14, 1 },
4540: + { 18, 4 },
4541: + { 19, 2 },
4542: + { 19, 0 },
4543: + { 17, 1 },
4544: + { 17, 1 },
4545: + { 17, 1 },
4546: + { 17, 1 },
4547: + { 15, 2 },
4548: + { 15, 1 },
4549: +};
4550: +
4551: +static void yy_accept(yyParser*); /* Forward Declaration */
4552: +
4553: +/*
4554: +** Perform a reduce action and the shift that must immediately
4555: +** follow the reduce.
4556: +*/
4557: +static void yy_reduce(
4558: + yyParser *yypParser, /* The parser */
4559: + unsigned int yyruleno /* Number of the rule by which to reduce */
4560: +){
4561: + int yygoto; /* The next state */
4562: + int yyact; /* The next action */
4563: + yyStackEntry *yymsp; /* The top of the parser's stack */
4564: + int yysize; /* Amount to pop the stack */
4565: + ParseARG_FETCH;
4566: + yymsp = yypParser->yytos;
4567: +#ifndef NDEBUG
4568: + if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
4569: + yysize = yyRuleInfo[yyruleno].nrhs;
4570: + fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
4571: + yyRuleName[yyruleno], yymsp[-yysize].stateno);
4572: + }
4573: +#endif /* NDEBUG */
4574: +
4575: + /* Check that the stack is large enough to grow by a single entry
4576: + ** if the RHS of the rule is empty. This ensures that there is room
4577: + ** enough on the stack to push the LHS value */
4578: + if( yyRuleInfo[yyruleno].nrhs==0 ){
4579: +#ifdef YYTRACKMAXSTACKDEPTH
4580: + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
4581: + yypParser->yyhwm++;
4582: + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
4583: + }
4584: +#endif
4585: +#if YYSTACKDEPTH>0
4586: + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH-1] ){
4587: + yyStackOverflow(yypParser);
4588: + return;
4589: + }
4590: +#else
4591: + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
4592: + if( yyGrowStack(yypParser) ){
4593: + yyStackOverflow(yypParser);
4594: + return;
4595: + }
4596: + yymsp = yypParser->yytos;
4597: + }
4598: +#endif
4599: + }
4600: +
4601: + switch( yyruleno ){
4602: + /* Beginning here are the reduction cases. A typical example
4603: + ** follows:
4604: + ** case 0:
4605: + ** #line <lineno> <grammarfile>
4606: + ** { ... } // User supplied code
4607: + ** #line <lineno> <thisfile>
4608: + ** break;
4609: + */
4610: +/********** Begin reduce actions **********************************************/
4611: + YYMINORTYPE yylhsminor;
4612: + case 0: /* sexprlist ::= sexprlist sexpr */
4613: +#line 15 "sexpr.lmn"
4614: +{ if (cb != NULL) { cb->res = cb->fn(yymsp[0].minor.yy6, cb->opq); } }
4615: +#line 820 "sexpr.c"
4616: + break;
4617: + case 1: /* sexprlist ::= */
4618: +#line 16 "sexpr.lmn"
4619: +{ /* */ }
4620: +#line 825 "sexpr.c"
4621: + break;
4622: + case 2: /* sexpr ::= atom */
4623: + case 9: /* sexpr ::= list */ yytestcase(yyruleno==9);
4624: +#line 18 "sexpr.lmn"
4625: +{ yylhsminor.yy6 = yymsp[0].minor.yy0; }
4626: +#line 831 "sexpr.c"
4627: + yymsp[0].minor.yy6 = yylhsminor.yy6;
4628: + break;
4629: + case 3: /* sexpr ::= QUOTE sexpr */
4630: +#line 19 "sexpr.lmn"
4631: +{ yymsp[-1].minor.yy6 = cons(sym_quote, cons(yymsp[0].minor.yy6, NIL)); }
4632: +#line 837 "sexpr.c"
4633: + break;
4634: + case 4: /* sexpr ::= QUASI sexpr */
4635: +#line 20 "sexpr.lmn"
4636: +{ yymsp[-1].minor.yy6 = cons(sym_quasiquote, cons(yymsp[0].minor.yy6, NIL)); }
4637: +#line 842 "sexpr.c"
4638: + break;
4639: + case 5: /* sexpr ::= COMMA_AT sexpr */
4640: +#line 21 "sexpr.lmn"
4641: +{ yymsp[-1].minor.yy6 = cons(sym_splice, cons(yymsp[0].minor.yy6, NIL)); }
4642: +#line 847 "sexpr.c"
4643: + break;
4644: + case 6: /* sexpr ::= COMMA sexpr */
4645: +#line 22 "sexpr.lmn"
4646: +{ yymsp[-1].minor.yy6 = cons(sym_unquote, cons(yymsp[0].minor.yy6, NIL)); }
4647: +#line 852 "sexpr.c"
4648: + break;
4649: + case 7: /* sexpr ::= OPAREN sexpr DOT sexpr CPAREN */
4650: +#line 23 "sexpr.lmn"
4651: +{ yymsp[-4].minor.yy6 = cons(yymsp[-3].minor.yy6,yymsp[-1].minor.yy6); }
4652: +#line 857 "sexpr.c"
4653: + break;
4654: + case 8: /* sexpr ::= OPAREN CPAREN */
4655: +#line 24 "sexpr.lmn"
4656: +{ yymsp[-1].minor.yy6 = NIL; }
4657: +#line 862 "sexpr.c"
4658: + break;
4659: + case 10: /* list ::= OPAREN sexpr listelem CPAREN */
4660: +#line 27 "sexpr.lmn"
4661: +{ yymsp[-3].minor.yy0 = cons(yymsp[-2].minor.yy6,yymsp[-1].minor.yy0); }
4662: +#line 867 "sexpr.c"
4663: + break;
4664: + case 11: /* listelem ::= sexpr listelem */
4665: +#line 29 "sexpr.lmn"
4666: +{ yylhsminor.yy0 = cons(yymsp[-1].minor.yy6, yymsp[0].minor.yy0); }
4667: +#line 872 "sexpr.c"
4668: + yymsp[-1].minor.yy0 = yylhsminor.yy0;
4669: + break;
4670: + case 12: /* listelem ::= */
4671: +#line 30 "sexpr.lmn"
4672: +{ yymsp[1].minor.yy0 = NIL; }
4673: +#line 878 "sexpr.c"
4674: + break;
4675: + case 13: /* atom ::= SYMBOL */
4676: + case 14: /* atom ::= STRING */ yytestcase(yyruleno==14);
4677: + case 15: /* atom ::= INTEGER */ yytestcase(yyruleno==15);
4678: + case 16: /* atom ::= NIHIL */ yytestcase(yyruleno==16);
4679: +#line 32 "sexpr.lmn"
4680: +{ yylhsminor.yy0 = yymsp[0].minor.yy0; }
4681: +#line 886 "sexpr.c"
4682: + yymsp[0].minor.yy0 = yylhsminor.yy0;
4683: + break;
4684: + default:
4685: + /* (17) input ::= sexprlist ENDPARSE */ yytestcase(yyruleno==17);
4686: + /* (18) input ::= error */ yytestcase(yyruleno==18);
4687: + break;
4688: +/********** End reduce actions ************************************************/
4689: + };
4690: + assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
4691: + yygoto = yyRuleInfo[yyruleno].lhs;
4692: + yysize = yyRuleInfo[yyruleno].nrhs;
4693: + yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
4694: + if( yyact <= YY_MAX_SHIFTREDUCE ){
4695: + if( yyact>YY_MAX_SHIFT ){
4696: + yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
4697: + }
4698: + yymsp -= yysize-1;
4699: + yypParser->yytos = yymsp;
4700: + yymsp->stateno = (YYACTIONTYPE)yyact;
4701: + yymsp->major = (YYCODETYPE)yygoto;
4702: + yyTraceShift(yypParser, yyact);
4703: + }else{
4704: + assert( yyact == YY_ACCEPT_ACTION );
4705: + yypParser->yytos -= yysize;
4706: + yy_accept(yypParser);
4707: + }
4708: +}
4709: +
4710: +/*
4711: +** The following code executes when the parse fails
4712: +*/
4713: +#ifndef YYNOERRORRECOVERY
4714: +static void yy_parse_failed(
4715: + yyParser *yypParser /* The parser */
4716: +){
4717: + ParseARG_FETCH;
4718: +#ifndef NDEBUG
4719: + if( yyTraceFILE ){
4720: + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
4721: + }
4722: +#endif
4723: + while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
4724: + /* Here code is inserted which will be executed whenever the
4725: + ** parser fails */
4726: +/************ Begin %parse_failure code ***************************************/
4727: +/************ End %parse_failure code *****************************************/
4728: + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
4729: +}
4730: +#endif /* YYNOERRORRECOVERY */
4731: +
4732: +/*
4733: +** The following code executes when a syntax error first occurs.
4734: +*/
4735: +static void yy_syntax_error(
4736: + yyParser *yypParser, /* The parser */
4737: + int yymajor, /* The major type of the error token */
4738: + ParseTOKENTYPE yyminor /* The minor type of the error token */
4739: +){
4740: + ParseARG_FETCH;
4741: +#define TOKEN yyminor
4742: +/************ Begin %syntax_error code ****************************************/
4743: +#line 8 "sexpr.lmn"
4744: +
4745: + printf("SYNTAX ERROR!\n");
4746: +#line 951 "sexpr.c"
4747: +/************ End %syntax_error code ******************************************/
4748: + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
4749: +}
4750: +
4751: +/*
4752: +** The following is executed when the parser accepts
4753: +*/
4754: +static void yy_accept(
4755: + yyParser *yypParser /* The parser */
4756: +){
4757: + ParseARG_FETCH;
4758: +#ifndef NDEBUG
4759: + if( yyTraceFILE ){
4760: + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
4761: + }
4762: +#endif
4763: +#ifndef YYNOERRORRECOVERY
4764: + yypParser->yyerrcnt = -1;
4765: +#endif
4766: + assert( yypParser->yytos==yypParser->yystack );
4767: + /* Here code is inserted which will be executed whenever the
4768: + ** parser accepts */
4769: +/*********** Begin %parse_accept code *****************************************/
4770: +/*********** End %parse_accept code *******************************************/
4771: + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
4772: +}
4773: +
4774: +/* The main parser program.
4775: +** The first argument is a pointer to a structure obtained from
4776: +** "ParseAlloc" which describes the current state of the parser.
4777: +** The second argument is the major token number. The third is
4778: +** the minor token. The fourth optional argument is whatever the
4779: +** user wants (and specified in the grammar) and is available for
4780: +** use by the action routines.
4781: +**
4782: +** Inputs:
4783: +** <ul>
4784: +** <li> A pointer to the parser (an opaque structure.)
4785: +** <li> The major token number.
4786: +** <li> The minor token number.
4787: +** <li> An option argument of a grammar-specified type.
4788: +** </ul>
4789: +**
4790: +** Outputs:
4791: +** None.
4792: +*/
4793: +void Parse(
4794: + void *yyp, /* The parser */
4795: + int yymajor, /* The major token code number */
4796: + ParseTOKENTYPE yyminor /* The value for the token */
4797: + ParseARG_PDECL /* Optional %extra_argument parameter */
4798: +){
4799: + YYMINORTYPE yyminorunion;
4800: + unsigned int yyact; /* The parser action. */
4801: +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
4802: + int yyendofinput; /* True if we are at the end of input */
4803: +#endif
4804: +#ifdef YYERRORSYMBOL
4805: + int yyerrorhit = 0; /* True if yymajor has invoked an error */
4806: +#endif
4807: + yyParser *yypParser; /* The parser */
4808: +
4809: + yypParser = (yyParser*)yyp;
4810: + assert( yypParser->yytos!=0 );
4811: +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
4812: + yyendofinput = (yymajor==0);
4813: +#endif
4814: + ParseARG_STORE;
4815: +
4816: +#ifndef NDEBUG
4817: + if( yyTraceFILE ){
4818: + fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]);
4819: + }
4820: +#endif
4821: +
4822: + do{
4823: + yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
4824: + if( yyact <= YY_MAX_SHIFTREDUCE ){
4825: + yy_shift(yypParser,yyact,yymajor,yyminor);
4826: +#ifndef YYNOERRORRECOVERY
4827: + yypParser->yyerrcnt--;
4828: +#endif
4829: + yymajor = YYNOCODE;
4830: + }else if( yyact <= YY_MAX_REDUCE ){
4831: + yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
4832: + }else{
4833: + assert( yyact == YY_ERROR_ACTION );
4834: + yyminorunion.yy0 = yyminor;
4835: +#ifdef YYERRORSYMBOL
4836: + int yymx;
4837: +#endif
4838: +#ifndef NDEBUG
4839: + if( yyTraceFILE ){
4840: + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
4841: + }
4842: +#endif
4843: +#ifdef YYERRORSYMBOL
4844: + /* A syntax error has occurred.
4845: + ** The response to an error depends upon whether or not the
4846: + ** grammar defines an error token "ERROR".
4847: + **
4848: + ** This is what we do if the grammar does define ERROR:
4849: + **
4850: + ** * Call the %syntax_error function.
4851: + **
4852: + ** * Begin popping the stack until we enter a state where
4853: + ** it is legal to shift the error symbol, then shift
4854: + ** the error symbol.
4855: + **
4856: + ** * Set the error count to three.
4857: + **
4858: + ** * Begin accepting and shifting new tokens. No new error
4859: + ** processing will occur until three tokens have been
4860: + ** shifted successfully.
4861: + **
4862: + */
4863: + if( yypParser->yyerrcnt<0 ){
4864: + yy_syntax_error(yypParser,yymajor,yyminor);
4865: + }
4866: + yymx = yypParser->yytos->major;
4867: + if( yymx==YYERRORSYMBOL || yyerrorhit ){
4868: +#ifndef NDEBUG
4869: + if( yyTraceFILE ){
4870: + fprintf(yyTraceFILE,"%sDiscard input token %s\n",
4871: + yyTracePrompt,yyTokenName[yymajor]);
4872: + }
4873: +#endif
4874: + yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
4875: + yymajor = YYNOCODE;
4876: + }else{
4877: + while( yypParser->yytos >= yypParser->yystack
4878: + && yymx != YYERRORSYMBOL
4879: + && (yyact = yy_find_reduce_action(
4880: + yypParser->yytos->stateno,
4881: + YYERRORSYMBOL)) >= YY_MIN_REDUCE
4882: + ){
4883: + yy_pop_parser_stack(yypParser);
4884: + }
4885: + if( yypParser->yytos < yypParser->yystack || yymajor==0 ){
4886: + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
4887: + yy_parse_failed(yypParser);
4888: +#ifndef YYNOERRORRECOVERY
4889: + yypParser->yyerrcnt = -1;
4890: +#endif
4891: + yymajor = YYNOCODE;
4892: + }else if( yymx!=YYERRORSYMBOL ){
4893: + yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor);
4894: + }
4895: + }
4896: + yypParser->yyerrcnt = 3;
4897: + yyerrorhit = 1;
4898: +#elif defined(YYNOERRORRECOVERY)
4899: + /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
4900: + ** do any kind of error recovery. Instead, simply invoke the syntax
4901: + ** error routine and continue going as if nothing had happened.
4902: + **
4903: + ** Applications can set this macro (for example inside %include) if
4904: + ** they intend to abandon the parse upon the first syntax error seen.
4905: + */
4906: + yy_syntax_error(yypParser,yymajor, yyminor);
4907: + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
4908: + yymajor = YYNOCODE;
4909: +
4910: +#else /* YYERRORSYMBOL is not defined */
4911: + /* This is what we do if the grammar does not define ERROR:
4912: + **
4913: + ** * Report an error message, and throw away the input token.
4914: + **
4915: + ** * If the input token is $, then fail the parse.
4916: + **
4917: + ** As before, subsequent error messages are suppressed until
4918: + ** three input tokens have been successfully shifted.
4919: + */
4920: + if( yypParser->yyerrcnt<=0 ){
4921: + yy_syntax_error(yypParser,yymajor, yyminor);
4922: + }
4923: + yypParser->yyerrcnt = 3;
4924: + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
4925: + if( yyendofinput ){
4926: + yy_parse_failed(yypParser);
4927: +#ifndef YYNOERRORRECOVERY
4928: + yypParser->yyerrcnt = -1;
4929: +#endif
4930: + }
4931: + yymajor = YYNOCODE;
4932: +#endif
4933: + }
4934: + }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack );
4935: +#ifndef NDEBUG
4936: + if( yyTraceFILE ){
4937: + yyStackEntry *i;
4938: + char cDiv = '[';
4939: + fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
4940: + for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){
4941: + fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]);
4942: + cDiv = ' ';
4943: + }
4944: + fprintf(yyTraceFILE,"]\n");
4945: + }
4946: +#endif
4947: + return;
4948: +}
4949: diff --git a/src/lib/sexpr.h b/src/lib/sexpr.h
4950: new file mode 100644
4951: index 0000000..2b52833
4952: --- /dev/null
4953: +++ b/src/lib/sexpr.h
4954: @@ -0,0 +1,12 @@
4955: +#define ENDPARSE 1
4956: +#define QUOTE 2
4957: +#define QUASI 3
4958: +#define COMMA_AT 4
4959: +#define COMMA 5
4960: +#define OPAREN 6
4961: +#define DOT 7
4962: +#define CPAREN 8
4963: +#define SYMBOL 9
4964: +#define STRING 10
4965: +#define INTEGER 11
4966: +#define NIHIL 12
4967: diff --git a/src/lib/sexpr.y b/src/lib/sexpr.y
4968: new file mode 100644
4969: index 0000000..4e61add
4970: --- /dev/null
4971: +++ b/src/lib/sexpr.y
4972: @@ -0,0 +1,35 @@
4973: +%include { #include <lac.h> }
4974: +%include { #include <assert.h> }
4975: +%include { #include "private.h" }
4976: +%token_type { lreg_t }
4977: +%type sexpr { lreg_t }
4978: +%extra_argument { struct parse_cb *cb }
4979: +
4980: +%syntax_error {
4981: + printf("SYNTAX ERROR!\n");
4982: +}
4983: +
4984: +input ::= sexprlist ENDPARSE.
4985: +input ::= error.
4986: +
4987: +sexprlist ::= sexprlist sexpr(A). { if (cb != NULL) { cb->res = cb->fn(A, cb->opq); } }
4988: +sexprlist ::= . { /* */ }
4989: +
4990: +sexpr(A) ::= atom(B). { A = B; }
4991: +sexpr(A) ::= QUOTE sexpr(B). { A = cons(sym_quote, cons(B, NIL)); }
4992: +sexpr(A) ::= QUASI sexpr(B). { A = cons(sym_quasiquote, cons(B, NIL)); }
4993: +sexpr(A) ::= COMMA_AT sexpr(B). { A = cons(sym_splice, cons(B, NIL)); }
4994: +sexpr(A) ::= COMMA sexpr(B). { A = cons(sym_unquote, cons(B, NIL)); }
4995: +sexpr(A) ::= OPAREN sexpr(B) DOT sexpr(C) CPAREN. { A = cons(B,C); }
4996: +sexpr(A) ::= OPAREN CPAREN. { A = NIL; }
4997: +sexpr(A) ::= list(B). { A = B; }
4998: +
4999: +list(A) ::= OPAREN sexpr(B) listelem(C) CPAREN. { A = cons(B,C); }
5000: +
5001: +listelem(A) ::= sexpr(B) listelem(C). { A = cons(B, C); }
5002: +listelem(A) ::= . { A = NIL; }
5003: +
5004: +atom(A) ::= SYMBOL(B). { A = B; }
5005: +atom(A) ::= STRING(B). { A = B; }
5006: +atom(A) ::= INTEGER(B). { A = B; }
5007: +atom(A) ::= NIHIL(B). { A = B; }
5008: diff --git a/src/lib/sexpr_parse.c b/src/lib/sexpr_parse.c
5009: deleted file mode 100644
5010: index bb0ed3c..0000000
5011: --- a/src/lib/sexpr_parse.c
5012: +++ /dev/null
5013: @@ -1,1646 +0,0 @@
5014: -/* A Bison parser, made by GNU Bison 3.0.4. */
5015: -
5016: -/* Bison implementation for Yacc-like parsers in C
5017: -
5018: - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
5019: -
5020: - This program is free software: you can redistribute it and/or modify
5021: - it under the terms of the GNU General Public License as published by
5022: - the Free Software Foundation, either version 3 of the License, or
5023: - (at your option) any later version.
5024: -
5025: - This program is distributed in the hope that it will be useful,
5026: - but WITHOUT ANY WARRANTY; without even the implied warranty of
5027: - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5028: - GNU General Public License for more details.
5029: -
5030: - You should have received a copy of the GNU General Public License
5031: - along with this program. If not, see <http://www.gnu.org/licenses/>. */
5032: -
5033: -/* As a special exception, you may create a larger work that contains
5034: - part or all of the Bison parser skeleton and distribute that work
5035: - under terms of your choice, so long as that work isn't itself a
5036: - parser generator using the skeleton or a modified version thereof
5037: - as a parser skeleton. Alternatively, if you modify or redistribute
5038: - the parser skeleton itself, you may (at your option) remove this
5039: - special exception, which will cause the skeleton and the resulting
5040: - Bison output files to be licensed under the GNU General Public
5041: - License without this special exception.
5042: -
5043: - This special exception was added by the Free Software Foundation in
5044: - version 2.2 of Bison. */
5045: -
5046: -/* C LALR(1) parser skeleton written by Richard Stallman, by
5047: - simplifying the original so-called "semantic" parser. */
5048: -
5049: -/* All symbols defined below should begin with yy or YY, to avoid
5050: - infringing on user name space. This should be done even for local
5051: - variables, as they might otherwise be expanded by user macros.
5052: - There are some unavoidable exceptions within include files to
5053: - define necessary library symbols; they are noted "INFRINGES ON
5054: - USER NAME SPACE" below. */
5055: -
5056: -/* Identify Bison output. */
5057: -#define YYBISON 1
5058: -
5059: -/* Bison version. */
5060: -#define YYBISON_VERSION "3.0.4"
5061: -
5062: -/* Skeleton name. */
5063: -#define YYSKELETON_NAME "yacc.c"
5064: -
5065: -/* Pure parsers. */
5066: -#define YYPURE 2
5067: -
5068: -/* Push parsers. */
5069: -#define YYPUSH 0
5070: -
5071: -/* Pull parsers. */
5072: -#define YYPULL 1
5073: -
5074: -
5075: -
5076: -
5077: -/* Copy the first part of user declarations. */
5078: -#line 20 "sexpr_parse.y" /* yacc.c:339 */
5079: -
5080: -#include <stdio.h>
5081: -#include <string.h>
5082: -#include <gc/gc.h>
5083: -#include "lac.h"
5084: -#include "sexpr_parse.h"
5085: -
5086: -int yylex(lreg_t *, void *);
5087: -void yyerror (lreg_t *lr, void *scanner, const char *msgp) /* Called by yyparse on error */
5088: -{
5089: -}
5090: -
5091: -
5092: -#line 80 "sexpr_parse.c" /* yacc.c:339 */
5093: -
5094: -# ifndef YY_NULLPTR
5095: -# if defined __cplusplus && 201103L <= __cplusplus
5096: -# define YY_NULLPTR nullptr
5097: -# else
5098: -# define YY_NULLPTR 0
5099: -# endif
5100: -# endif
5101: -
5102: -/* Enabling verbose error messages. */
5103: -#ifdef YYERROR_VERBOSE
5104: -# undef YYERROR_VERBOSE
5105: -# define YYERROR_VERBOSE 1
5106: -#else
5107: -# define YYERROR_VERBOSE 0
5108: -#endif
5109: -
5110: -/* In a future release of Bison, this section will be replaced
5111: - by #include "y.tab.h". */
5112: -#ifndef YY_YY_SEXPR_PARSE_H_INCLUDED
5113: -# define YY_YY_SEXPR_PARSE_H_INCLUDED
5114: -/* Debug traces. */
5115: -#ifndef YYDEBUG
5116: -# define YYDEBUG 0
5117: -#endif
5118: -#if YYDEBUG
5119: -extern int yydebug;
5120: -#endif
5121: -
5122: -/* Token type. */
5123: -#ifndef YYTOKENTYPE
5124: -# define YYTOKENTYPE
5125: - enum yytokentype
5126: - {
5127: - ENDOFFILE = 258,
5128: - NIHIL = 259,
5129: - STRING = 260,
5130: - INTEGER = 261,
5131: - SYMBOL = 262,
5132: - DELIMITER = 263,
5133: - COMMA_AT = 264
5134: - };
5135: -#endif
5136: -/* Tokens. */
5137: -#define ENDOFFILE 258
5138: -#define NIHIL 259
5139: -#define STRING 260
5140: -#define INTEGER 261
5141: -#define SYMBOL 262
5142: -#define DELIMITER 263
5143: -#define COMMA_AT 264
5144: -
5145: -/* Value type. */
5146: -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
5147: -typedef lreg_t YYSTYPE;
5148: -# define YYSTYPE_IS_TRIVIAL 1
5149: -# define YYSTYPE_IS_DECLARED 1
5150: -#endif
5151: -
5152: -
5153: -
5154: -int yyparse (lreg_t *result, void *scan);
5155: -
5156: -#endif /* !YY_YY_SEXPR_PARSE_H_INCLUDED */
5157: -
5158: -/* Copy the second part of user declarations. */
5159: -
5160: -#line 148 "sexpr_parse.c" /* yacc.c:358 */
5161: -
5162: -#ifdef short
5163: -# undef short
5164: -#endif
5165: -
5166: -#ifdef YYTYPE_UINT8
5167: -typedef YYTYPE_UINT8 yytype_uint8;
5168: -#else
5169: -typedef unsigned char yytype_uint8;
5170: -#endif
5171: -
5172: -#ifdef YYTYPE_INT8
5173: -typedef YYTYPE_INT8 yytype_int8;
5174: -#else
5175: -typedef signed char yytype_int8;
5176: -#endif
5177: -
5178: -#ifdef YYTYPE_UINT16
5179: -typedef YYTYPE_UINT16 yytype_uint16;
5180: -#else
5181: -typedef unsigned short int yytype_uint16;
5182: -#endif
5183: -
5184: -#ifdef YYTYPE_INT16
5185: -typedef YYTYPE_INT16 yytype_int16;
5186: -#else
5187: -typedef short int yytype_int16;
5188: -#endif
5189: -
5190: -#ifndef YYSIZE_T
5191: -# ifdef __SIZE_TYPE__
5192: -# define YYSIZE_T __SIZE_TYPE__
5193: -# elif defined size_t
5194: -# define YYSIZE_T size_t
5195: -# elif ! defined YYSIZE_T
5196: -# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
5197: -# define YYSIZE_T size_t
5198: -# else
5199: -# define YYSIZE_T unsigned int
5200: -# endif
5201: -#endif
5202: -
5203: -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
5204: -
5205: -#ifndef YY_
5206: -# if defined YYENABLE_NLS && YYENABLE_NLS
5207: -# if ENABLE_NLS
5208: -# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
5209: -# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
5210: -# endif
5211: -# endif
5212: -# ifndef YY_
5213: -# define YY_(Msgid) Msgid
5214: -# endif
5215: -#endif
5216: -
5217: -#ifndef YY_ATTRIBUTE
5218: -# if (defined __GNUC__ \
5219: - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
5220: - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
5221: -# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
5222: -# else
5223: -# define YY_ATTRIBUTE(Spec) /* empty */
5224: -# endif
5225: -#endif
5226: -
5227: -#ifndef YY_ATTRIBUTE_PURE
5228: -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
5229: -#endif
5230: -
5231: -#ifndef YY_ATTRIBUTE_UNUSED
5232: -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
5233: -#endif
5234: -
5235: -#if !defined _Noreturn \
5236: - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
5237: -# if defined _MSC_VER && 1200 <= _MSC_VER
5238: -# define _Noreturn __declspec (noreturn)
5239: -# else
5240: -# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
5241: -# endif
5242: -#endif
5243: -
5244: -/* Suppress unused-variable warnings by "using" E. */
5245: -#if ! defined lint || defined __GNUC__
5246: -# define YYUSE(E) ((void) (E))
5247: -#else
5248: -# define YYUSE(E) /* empty */
5249: -#endif
5250: -
5251: -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
5252: -/* Suppress an incorrect diagnostic about yylval being uninitialized. */
5253: -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
5254: - _Pragma ("GCC diagnostic push") \
5255: - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
5256: - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
5257: -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
5258: - _Pragma ("GCC diagnostic pop")
5259: -#else
5260: -# define YY_INITIAL_VALUE(Value) Value
5261: -#endif
5262: -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
5263: -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
5264: -# define YY_IGNORE_MAYBE_UNINITIALIZED_END
5265: -#endif
5266: -#ifndef YY_INITIAL_VALUE
5267: -# define YY_INITIAL_VALUE(Value) /* Nothing. */
5268: -#endif
5269: -
5270: -
5271: -#if ! defined yyoverflow || YYERROR_VERBOSE
5272: -
5273: -/* The parser invokes alloca or malloc; define the necessary symbols. */
5274: -
5275: -# ifdef YYSTACK_USE_ALLOCA
5276: -# if YYSTACK_USE_ALLOCA
5277: -# ifdef __GNUC__
5278: -# define YYSTACK_ALLOC __builtin_alloca
5279: -# elif defined __BUILTIN_VA_ARG_INCR
5280: -# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
5281: -# elif defined _AIX
5282: -# define YYSTACK_ALLOC __alloca
5283: -# elif defined _MSC_VER
5284: -# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
5285: -# define alloca _alloca
5286: -# else
5287: -# define YYSTACK_ALLOC alloca
5288: -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
5289: -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
5290: - /* Use EXIT_SUCCESS as a witness for stdlib.h. */
5291: -# ifndef EXIT_SUCCESS
5292: -# define EXIT_SUCCESS 0
5293: -# endif
5294: -# endif
5295: -# endif
5296: -# endif
5297: -# endif
5298: -
5299: -# ifdef YYSTACK_ALLOC
5300: - /* Pacify GCC's 'empty if-body' warning. */
5301: -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
5302: -# ifndef YYSTACK_ALLOC_MAXIMUM
5303: - /* The OS might guarantee only one guard page at the bottom of the stack,
5304: - and a page size can be as small as 4096 bytes. So we cannot safely
5305: - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
5306: - to allow for a few compiler-allocated temporary stack slots. */
5307: -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
5308: -# endif
5309: -# else
5310: -# define YYSTACK_ALLOC YYMALLOC
5311: -# define YYSTACK_FREE YYFREE
5312: -# ifndef YYSTACK_ALLOC_MAXIMUM
5313: -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
5314: -# endif
5315: -# if (defined __cplusplus && ! defined EXIT_SUCCESS \
5316: - && ! ((defined YYMALLOC || defined malloc) \
5317: - && (defined YYFREE || defined free)))
5318: -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
5319: -# ifndef EXIT_SUCCESS
5320: -# define EXIT_SUCCESS 0
5321: -# endif
5322: -# endif
5323: -# ifndef YYMALLOC
5324: -# define YYMALLOC malloc
5325: -# if ! defined malloc && ! defined EXIT_SUCCESS
5326: -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
5327: -# endif
5328: -# endif
5329: -# ifndef YYFREE
5330: -# define YYFREE free
5331: -# if ! defined free && ! defined EXIT_SUCCESS
5332: -void free (void *); /* INFRINGES ON USER NAME SPACE */
5333: -# endif
5334: -# endif
5335: -# endif
5336: -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
5337: -
5338: -
5339: -#if (! defined yyoverflow \
5340: - && (! defined __cplusplus \
5341: - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
5342: -
5343: -/* A type that is properly aligned for any stack member. */
5344: -union yyalloc
5345: -{
5346: - yytype_int16 yyss_alloc;
5347: - YYSTYPE yyvs_alloc;
5348: -};
5349: -
5350: -/* The size of the maximum gap between one aligned stack and the next. */
5351: -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
5352: -
5353: -/* The size of an array large to enough to hold all stacks, each with
5354: - N elements. */
5355: -# define YYSTACK_BYTES(N) \
5356: - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
5357: - + YYSTACK_GAP_MAXIMUM)
5358: -
5359: -# define YYCOPY_NEEDED 1
5360: -
5361: -/* Relocate STACK from its old location to the new one. The
5362: - local variables YYSIZE and YYSTACKSIZE give the old and new number of
5363: - elements in the stack, and YYPTR gives the new location of the
5364: - stack. Advance YYPTR to a properly aligned location for the next
5365: - stack. */
5366: -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
5367: - do \
5368: - { \
5369: - YYSIZE_T yynewbytes; \
5370: - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
5371: - Stack = &yyptr->Stack_alloc; \
5372: - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
5373: - yyptr += yynewbytes / sizeof (*yyptr); \
5374: - } \
5375: - while (0)
5376: -
5377: -#endif
5378: -
5379: -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
5380: -/* Copy COUNT objects from SRC to DST. The source and destination do
5381: - not overlap. */
5382: -# ifndef YYCOPY
5383: -# if defined __GNUC__ && 1 < __GNUC__
5384: -# define YYCOPY(Dst, Src, Count) \
5385: - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
5386: -# else
5387: -# define YYCOPY(Dst, Src, Count) \
5388: - do \
5389: - { \
5390: - YYSIZE_T yyi; \
5391: - for (yyi = 0; yyi < (Count); yyi++) \
5392: - (Dst)[yyi] = (Src)[yyi]; \
5393: - } \
5394: - while (0)
5395: -# endif
5396: -# endif
5397: -#endif /* !YYCOPY_NEEDED */
5398: -
5399: -/* YYFINAL -- State number of the termination state. */
5400: -#define YYFINAL 2
5401: -/* YYLAST -- Last index in YYTABLE. */
5402: -#define YYLAST 59
5403: -
5404: -/* YYNTOKENS -- Number of terminals. */
5405: -#define YYNTOKENS 16
5406: -/* YYNNTS -- Number of nonterminals. */
5407: -#define YYNNTS 6
5408: -/* YYNRULES -- Number of rules. */
5409: -#define YYNRULES 19
5410: -/* YYNSTATES -- Number of states. */
5411: -#define YYNSTATES 29
5412: -
5413: -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
5414: - by yylex, with out-of-bounds checking. */
5415: -#define YYUNDEFTOK 2
5416: -#define YYMAXUTOK 264
5417: -
5418: -#define YYTRANSLATE(YYX) \
5419: - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
5420: -
5421: -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
5422: - as returned by yylex, without out-of-bounds checking. */
5423: -static const yytype_uint8 yytranslate[] =
5424: -{
5425: - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5426: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5427: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5428: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 10,
5429: - 13, 15, 2, 2, 12, 2, 14, 2, 2, 2,
5430: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5431: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5432: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5433: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5434: - 2, 2, 2, 2, 2, 2, 11, 2, 2, 2,
5435: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5436: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5437: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5438: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5439: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5440: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5441: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5442: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5443: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5444: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5445: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5446: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5447: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5448: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5449: - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5450: - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5451: - 5, 6, 7, 8, 9
5452: -};
5453: -
5454: -#if YYDEBUG
5455: - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
5456: -static const yytype_uint8 yyrline[] =
5457: -{
5458: - 0, 50, 50, 50, 51, 53, 54, 55, 56, 57,
5459: - 58, 59, 60, 62, 64, 65, 67, 67, 67, 67
5460: -};
5461: -#endif
5462: -
5463: -#if YYDEBUG || YYERROR_VERBOSE || 0
5464: -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
5465: - First, the terminals, then, starting at YYNTOKENS, nonterminals. */
5466: -static const char *const yytname[] =
5467: -{
5468: - "$end", "error", "$undefined", "ENDOFFILE", "NIHIL", "STRING",
5469: - "INTEGER", "SYMBOL", "DELIMITER", "COMMA_AT", "'\\''", "'`'", "','",
5470: - "'('", "'.'", "')'", "$accept", "input", "sexpr", "list", "listelem",
5471: - "atom", YY_NULLPTR
5472: -};
5473: -#endif
5474: -
5475: -# ifdef YYPRINT
5476: -/* YYTOKNUM[NUM] -- (External) token number corresponding to the
5477: - (internal) symbol number NUM (which must be that of a token). */
5478: -static const yytype_uint16 yytoknum[] =
5479: -{
5480: - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
5481: - 39, 96, 44, 40, 46, 41
5482: -};
5483: -# endif
5484: -
5485: -#define YYPACT_NINF -21
5486: -
5487: -#define yypact_value_is_default(Yystate) \
5488: - (!!((Yystate) == (-21)))
5489: -
5490: -#define YYTABLE_NINF -1
5491: -
5492: -#define yytable_value_is_error(Yytable_value) \
5493: - 0
5494: -
5495: - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
5496: - STATE-NUM. */
5497: -static const yytype_int8 yypact[] =
5498: -{
5499: - -21, 13, -21, -21, -21, -21, -21, -21, 46, 46,
5500: - 46, 46, 23, -21, -21, -21, -21, -21, -21, -21,
5501: - -21, 35, 46, 46, -14, -13, -21, -21, -21
5502: -};
5503: -
5504: - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
5505: - Performed when YYTABLE does not specify something else to do. Zero
5506: - means the default is an error. */
5507: -static const yytype_uint8 yydefact[] =
5508: -{
5509: - 2, 0, 1, 3, 19, 17, 18, 16, 0, 0,
5510: - 0, 0, 0, 4, 12, 5, 8, 6, 7, 9,
5511: - 11, 14, 0, 14, 0, 0, 15, 13, 10
5512: -};
5513: -
5514: - /* YYPGOTO[NTERM-NUM]. */
5515: -static const yytype_int8 yypgoto[] =
5516: -{
5517: - -21, -21, -1, -21, -20, -21
5518: -};
5519: -
5520: - /* YYDEFGOTO[NTERM-NUM]. */
5521: -static const yytype_int8 yydefgoto[] =
5522: -{
5523: - -1, 1, 23, 14, 24, 15
5524: -};
5525: -
5526: - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
5527: - positive, shift that token. If negative, reduce the rule whose
5528: - number is the opposite. If YYTABLE_NINF, syntax error. */
5529: -static const yytype_uint8 yytable[] =
5530: -{
5531: - 13, 27, 28, 26, 0, 0, 0, 16, 17, 18,
5532: - 19, 21, 0, 2, 0, 0, 3, 4, 5, 6,
5533: - 7, 25, 8, 9, 10, 11, 12, 4, 5, 6,
5534: - 7, 0, 8, 9, 10, 11, 12, 0, 20, 4,
5535: - 5, 6, 7, 0, 8, 9, 10, 11, 12, 22,
5536: - 4, 5, 6, 7, 0, 8, 9, 10, 11, 12
5537: -};
5538: -
5539: -static const yytype_int8 yycheck[] =
5540: -{
5541: - 1, 15, 15, 23, -1, -1, -1, 8, 9, 10,
5542: - 11, 12, -1, 0, -1, -1, 3, 4, 5, 6,
5543: - 7, 22, 9, 10, 11, 12, 13, 4, 5, 6,
5544: - 7, -1, 9, 10, 11, 12, 13, -1, 15, 4,
5545: - 5, 6, 7, -1, 9, 10, 11, 12, 13, 14,
5546: - 4, 5, 6, 7, -1, 9, 10, 11, 12, 13
5547: -};
5548: -
5549: - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
5550: - symbol of state STATE-NUM. */
5551: -static const yytype_uint8 yystos[] =
5552: -{
5553: - 0, 17, 0, 3, 4, 5, 6, 7, 9, 10,
5554: - 11, 12, 13, 18, 19, 21, 18, 18, 18, 18,
5555: - 15, 18, 14, 18, 20, 18, 20, 15, 15
5556: -};
5557: -
5558: - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
5559: -static const yytype_uint8 yyr1[] =
5560: -{
5561: - 0, 16, 17, 17, 17, 18, 18, 18, 18, 18,
5562: - 18, 18, 18, 19, 20, 20, 21, 21, 21, 21
5563: -};
5564: -
5565: - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
5566: -static const yytype_uint8 yyr2[] =
5567: -{
5568: - 0, 2, 0, 2, 2, 1, 2, 2, 2, 2,
5569: - 5, 2, 1, 4, 0, 2, 1, 1, 1, 1
5570: -};
5571: -
5572: -
5573: -#define yyerrok (yyerrstatus = 0)
5574: -#define yyclearin (yychar = YYEMPTY)
5575: -#define YYEMPTY (-2)
5576: -#define YYEOF 0
5577: -
5578: -#define YYACCEPT goto yyacceptlab
5579: -#define YYABORT goto yyabortlab
5580: -#define YYERROR goto yyerrorlab
5581: -
5582: -
5583: -#define YYRECOVERING() (!!yyerrstatus)
5584: -
5585: -#define YYBACKUP(Token, Value) \
5586: -do \
5587: - if (yychar == YYEMPTY) \
5588: - { \
5589: - yychar = (Token); \
5590: - yylval = (Value); \
5591: - YYPOPSTACK (yylen); \
5592: - yystate = *yyssp; \
5593: - goto yybackup; \
5594: - } \
5595: - else \
5596: - { \
5597: - yyerror (result, scan, YY_("syntax error: cannot back up")); \
5598: - YYERROR; \
5599: - } \
5600: -while (0)
5601: -
5602: -/* Error token number */
5603: -#define YYTERROR 1
5604: -#define YYERRCODE 256
5605: -
5606: -
5607: -
5608: -/* Enable debugging if requested. */
5609: -#if YYDEBUG
5610: -
5611: -# ifndef YYFPRINTF
5612: -# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
5613: -# define YYFPRINTF fprintf
5614: -# endif
5615: -
5616: -# define YYDPRINTF(Args) \
5617: -do { \
5618: - if (yydebug) \
5619: - YYFPRINTF Args; \
5620: -} while (0)
5621: -
5622: -/* This macro is provided for backward compatibility. */
5623: -#ifndef YY_LOCATION_PRINT
5624: -# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
5625: -#endif
5626: -
5627: -
5628: -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
5629: -do { \
5630: - if (yydebug) \
5631: - { \
5632: - YYFPRINTF (stderr, "%s ", Title); \
5633: - yy_symbol_print (stderr, \
5634: - Type, Value, result, scan); \
5635: - YYFPRINTF (stderr, "\n"); \
5636: - } \
5637: -} while (0)
5638: -
5639: -
5640: -/*----------------------------------------.
5641: -| Print this symbol's value on YYOUTPUT. |
5642: -`----------------------------------------*/
5643: -
5644: -static void
5645: -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, lreg_t *result, void *scan)
5646: -{
5647: - FILE *yyo = yyoutput;
5648: - YYUSE (yyo);
5649: - YYUSE (result);
5650: - YYUSE (scan);
5651: - if (!yyvaluep)
5652: - return;
5653: -# ifdef YYPRINT
5654: - if (yytype < YYNTOKENS)
5655: - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
5656: -# endif
5657: - YYUSE (yytype);
5658: -}
5659: -
5660: -
5661: -/*--------------------------------.
5662: -| Print this symbol on YYOUTPUT. |
5663: -`--------------------------------*/
5664: -
5665: -static void
5666: -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, lreg_t *result, void *scan)
5667: -{
5668: - YYFPRINTF (yyoutput, "%s %s (",
5669: - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
5670: -
5671: - yy_symbol_value_print (yyoutput, yytype, yyvaluep, result, scan);
5672: - YYFPRINTF (yyoutput, ")");
5673: -}
5674: -
5675: -/*------------------------------------------------------------------.
5676: -| yy_stack_print -- Print the state stack from its BOTTOM up to its |
5677: -| TOP (included). |
5678: -`------------------------------------------------------------------*/
5679: -
5680: -static void
5681: -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
5682: -{
5683: - YYFPRINTF (stderr, "Stack now");
5684: - for (; yybottom <= yytop; yybottom++)
5685: - {
5686: - int yybot = *yybottom;
5687: - YYFPRINTF (stderr, " %d", yybot);
5688: - }
5689: - YYFPRINTF (stderr, "\n");
5690: -}
5691: -
5692: -# define YY_STACK_PRINT(Bottom, Top) \
5693: -do { \
5694: - if (yydebug) \
5695: - yy_stack_print ((Bottom), (Top)); \
5696: -} while (0)
5697: -
5698: -
5699: -/*------------------------------------------------.
5700: -| Report that the YYRULE is going to be reduced. |
5701: -`------------------------------------------------*/
5702: -
5703: -static void
5704: -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, lreg_t *result, void *scan)
5705: -{
5706: - unsigned long int yylno = yyrline[yyrule];
5707: - int yynrhs = yyr2[yyrule];
5708: - int yyi;
5709: - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
5710: - yyrule - 1, yylno);
5711: - /* The symbols being reduced. */
5712: - for (yyi = 0; yyi < yynrhs; yyi++)
5713: - {
5714: - YYFPRINTF (stderr, " $%d = ", yyi + 1);
5715: - yy_symbol_print (stderr,
5716: - yystos[yyssp[yyi + 1 - yynrhs]],
5717: - &(yyvsp[(yyi + 1) - (yynrhs)])
5718: - , result, scan);
5719: - YYFPRINTF (stderr, "\n");
5720: - }
5721: -}
5722: -
5723: -# define YY_REDUCE_PRINT(Rule) \
5724: -do { \
5725: - if (yydebug) \
5726: - yy_reduce_print (yyssp, yyvsp, Rule, result, scan); \
5727: -} while (0)
5728: -
5729: -/* Nonzero means print parse trace. It is left uninitialized so that
5730: - multiple parsers can coexist. */
5731: -int yydebug;
5732: -#else /* !YYDEBUG */
5733: -# define YYDPRINTF(Args)
5734: -# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
5735: -# define YY_STACK_PRINT(Bottom, Top)
5736: -# define YY_REDUCE_PRINT(Rule)
5737: -#endif /* !YYDEBUG */
5738: -
5739: -
5740: -/* YYINITDEPTH -- initial size of the parser's stacks. */
5741: -#ifndef YYINITDEPTH
5742: -# define YYINITDEPTH 200
5743: -#endif
5744: -
5745: -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
5746: - if the built-in stack extension method is used).
5747: -
5748: - Do not make this value too large; the results are undefined if
5749: - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
5750: - evaluated with infinite-precision integer arithmetic. */
5751: -
5752: -#ifndef YYMAXDEPTH
5753: -# define YYMAXDEPTH 10000
5754: -#endif
5755: -
5756: -
5757: -#if YYERROR_VERBOSE
5758: -
5759: -# ifndef yystrlen
5760: -# if defined __GLIBC__ && defined _STRING_H
5761: -# define yystrlen strlen
5762: -# else
5763: -/* Return the length of YYSTR. */
5764: -static YYSIZE_T
5765: -yystrlen (const char *yystr)
5766: -{
5767: - YYSIZE_T yylen;
5768: - for (yylen = 0; yystr[yylen]; yylen++)
5769: - continue;
5770: - return yylen;
5771: -}
5772: -# endif
5773: -# endif
5774: -
5775: -# ifndef yystpcpy
5776: -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
5777: -# define yystpcpy stpcpy
5778: -# else
5779: -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
5780: - YYDEST. */
5781: -static char *
5782: -yystpcpy (char *yydest, const char *yysrc)
5783: -{
5784: - char *yyd = yydest;
5785: - const char *yys = yysrc;
5786: -
5787: - while ((*yyd++ = *yys++) != '\0')
5788: - continue;
5789: -
5790: - return yyd - 1;
5791: -}
5792: -# endif
5793: -# endif
5794: -
5795: -# ifndef yytnamerr
5796: -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
5797: - quotes and backslashes, so that it's suitable for yyerror. The
5798: - heuristic is that double-quoting is unnecessary unless the string
5799: - contains an apostrophe, a comma, or backslash (other than
5800: - backslash-backslash). YYSTR is taken from yytname. If YYRES is
5801: - null, do not copy; instead, return the length of what the result
5802: - would have been. */
5803: -static YYSIZE_T
5804: -yytnamerr (char *yyres, const char *yystr)
5805: -{
5806: - if (*yystr == '"')
5807: - {
5808: - YYSIZE_T yyn = 0;
5809: - char const *yyp = yystr;
5810: -
5811: - for (;;)
5812: - switch (*++yyp)
5813: - {
5814: - case '\'':
5815: - case ',':
5816: - goto do_not_strip_quotes;
5817: -
5818: - case '\\':
5819: - if (*++yyp != '\\')
5820: - goto do_not_strip_quotes;
5821: - /* Fall through. */
5822: - default:
5823: - if (yyres)
5824: - yyres[yyn] = *yyp;
5825: - yyn++;
5826: - break;
5827: -
5828: - case '"':
5829: - if (yyres)
5830: - yyres[yyn] = '\0';
5831: - return yyn;
5832: - }
5833: - do_not_strip_quotes: ;
5834: - }
5835: -
5836: - if (! yyres)
5837: - return yystrlen (yystr);
5838: -
5839: - return yystpcpy (yyres, yystr) - yyres;
5840: -}
5841: -# endif
5842: -
5843: -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
5844: - about the unexpected token YYTOKEN for the state stack whose top is
5845: - YYSSP.
5846: -
5847: - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
5848: - not large enough to hold the message. In that case, also set
5849: - *YYMSG_ALLOC to the required number of bytes. Return 2 if the
5850: - required number of bytes is too large to store. */
5851: -static int
5852: -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
5853: - yytype_int16 *yyssp, int yytoken)
5854: -{
5855: - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
5856: - YYSIZE_T yysize = yysize0;
5857: - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
5858: - /* Internationalized format string. */
5859: - const char *yyformat = YY_NULLPTR;
5860: - /* Arguments of yyformat. */
5861: - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
5862: - /* Number of reported tokens (one for the "unexpected", one per
5863: - "expected"). */
5864: - int yycount = 0;
5865: -
5866: - /* There are many possibilities here to consider:
5867: - - If this state is a consistent state with a default action, then
5868: - the only way this function was invoked is if the default action
5869: - is an error action. In that case, don't check for expected
5870: - tokens because there are none.
5871: - - The only way there can be no lookahead present (in yychar) is if
5872: - this state is a consistent state with a default action. Thus,
5873: - detecting the absence of a lookahead is sufficient to determine
5874: - that there is no unexpected or expected token to report. In that
5875: - case, just report a simple "syntax error".
5876: - - Don't assume there isn't a lookahead just because this state is a
5877: - consistent state with a default action. There might have been a
5878: - previous inconsistent state, consistent state with a non-default
5879: - action, or user semantic action that manipulated yychar.
5880: - - Of course, the expected token list depends on states to have
5881: - correct lookahead information, and it depends on the parser not
5882: - to perform extra reductions after fetching a lookahead from the
5883: - scanner and before detecting a syntax error. Thus, state merging
5884: - (from LALR or IELR) and default reductions corrupt the expected
5885: - token list. However, the list is correct for canonical LR with
5886: - one exception: it will still contain any token that will not be
5887: - accepted due to an error action in a later state.
5888: - */
5889: - if (yytoken != YYEMPTY)
5890: - {
5891: - int yyn = yypact[*yyssp];
5892: - yyarg[yycount++] = yytname[yytoken];
5893: - if (!yypact_value_is_default (yyn))
5894: - {
5895: - /* Start YYX at -YYN if negative to avoid negative indexes in
5896: - YYCHECK. In other words, skip the first -YYN actions for
5897: - this state because they are default actions. */
5898: - int yyxbegin = yyn < 0 ? -yyn : 0;
5899: - /* Stay within bounds of both yycheck and yytname. */
5900: - int yychecklim = YYLAST - yyn + 1;
5901: - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
5902: - int yyx;
5903: -
5904: - for (yyx = yyxbegin; yyx < yyxend; ++yyx)
5905: - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
5906: - && !yytable_value_is_error (yytable[yyx + yyn]))
5907: - {
5908: - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
5909: - {
5910: - yycount = 1;
5911: - yysize = yysize0;
5912: - break;
5913: - }
5914: - yyarg[yycount++] = yytname[yyx];
5915: - {
5916: - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
5917: - if (! (yysize <= yysize1
5918: - && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
5919: - return 2;
5920: - yysize = yysize1;
5921: - }
5922: - }
5923: - }
5924: - }
5925: -
5926: - switch (yycount)
5927: - {
5928: -# define YYCASE_(N, S) \
5929: - case N: \
5930: - yyformat = S; \
5931: - break
5932: - YYCASE_(0, YY_("syntax error"));
5933: - YYCASE_(1, YY_("syntax error, unexpected %s"));
5934: - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
5935: - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
5936: - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
5937: - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
5938: -# undef YYCASE_
5939: - }
5940: -
5941: - {
5942: - YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
5943: - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
5944: - return 2;
5945: - yysize = yysize1;
5946: - }
5947: -
5948: - if (*yymsg_alloc < yysize)
5949: - {
5950: - *yymsg_alloc = 2 * yysize;
5951: - if (! (yysize <= *yymsg_alloc
5952: - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
5953: - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
5954: - return 1;
5955: - }
5956: -
5957: - /* Avoid sprintf, as that infringes on the user's name space.
5958: - Don't have undefined behavior even if the translation
5959: - produced a string with the wrong number of "%s"s. */
5960: - {
5961: - char *yyp = *yymsg;
5962: - int yyi = 0;
5963: - while ((*yyp = *yyformat) != '\0')
5964: - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
5965: - {
5966: - yyp += yytnamerr (yyp, yyarg[yyi++]);
5967: - yyformat += 2;
5968: - }
5969: - else
5970: - {
5971: - yyp++;
5972: - yyformat++;
5973: - }
5974: - }
5975: - return 0;
5976: -}
5977: -#endif /* YYERROR_VERBOSE */
5978: -
5979: -/*-----------------------------------------------.
5980: -| Release the memory associated to this symbol. |
5981: -`-----------------------------------------------*/
5982: -
5983: -static void
5984: -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, lreg_t *result, void *scan)
5985: -{
5986: - YYUSE (yyvaluep);
5987: - YYUSE (result);
5988: - YYUSE (scan);
5989: - if (!yymsg)
5990: - yymsg = "Deleting";
5991: - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
5992: -
5993: - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
5994: - YYUSE (yytype);
5995: - YY_IGNORE_MAYBE_UNINITIALIZED_END
5996: -}
5997: -
5998: -
5999: -
6000: -
6001: -/*----------.
6002: -| yyparse. |
6003: -`----------*/
6004: -
6005: -int
6006: -yyparse (lreg_t *result, void *scan)
6007: -{
6008: -/* The lookahead symbol. */
6009: -int yychar;
6010: -
6011: -
6012: -/* The semantic value of the lookahead symbol. */
6013: -/* Default value used for initialization, for pacifying older GCCs
6014: - or non-GCC compilers. */
6015: -YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
6016: -YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
6017: -
6018: - /* Number of syntax errors so far. */
6019: - int yynerrs;
6020: -
6021: - int yystate;
6022: - /* Number of tokens to shift before error messages enabled. */
6023: - int yyerrstatus;
6024: -
6025: - /* The stacks and their tools:
6026: - 'yyss': related to states.
6027: - 'yyvs': related to semantic values.
6028: -
6029: - Refer to the stacks through separate pointers, to allow yyoverflow
6030: - to reallocate them elsewhere. */
6031: -
6032: - /* The state stack. */
6033: - yytype_int16 yyssa[YYINITDEPTH];
6034: - yytype_int16 *yyss;
6035: - yytype_int16 *yyssp;
6036: -
6037: - /* The semantic value stack. */
6038: - YYSTYPE yyvsa[YYINITDEPTH];
6039: - YYSTYPE *yyvs;
6040: - YYSTYPE *yyvsp;
6041: -
6042: - YYSIZE_T yystacksize;
6043: -
6044: - int yyn;
6045: - int yyresult;
6046: - /* Lookahead token as an internal (translated) token number. */
6047: - int yytoken = 0;
6048: - /* The variables used to return semantic value and location from the
6049: - action routines. */
6050: - YYSTYPE yyval;
6051: -
6052: -#if YYERROR_VERBOSE
6053: - /* Buffer for error messages, and its allocated size. */
6054: - char yymsgbuf[128];
6055: - char *yymsg = yymsgbuf;
6056: - YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
6057: -#endif
6058: -
6059: -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
6060: -
6061: - /* The number of symbols on the RHS of the reduced rule.
6062: - Keep to zero when no symbol should be popped. */
6063: - int yylen = 0;
6064: -
6065: - yyssp = yyss = yyssa;
6066: - yyvsp = yyvs = yyvsa;
6067: - yystacksize = YYINITDEPTH;
6068: -
6069: - YYDPRINTF ((stderr, "Starting parse\n"));
6070: -
6071: - yystate = 0;
6072: - yyerrstatus = 0;
6073: - yynerrs = 0;
6074: - yychar = YYEMPTY; /* Cause a token to be read. */
6075: - goto yysetstate;
6076: -
6077: -/*------------------------------------------------------------.
6078: -| yynewstate -- Push a new state, which is found in yystate. |
6079: -`------------------------------------------------------------*/
6080: - yynewstate:
6081: - /* In all cases, when you get here, the value and location stacks
6082: - have just been pushed. So pushing a state here evens the stacks. */
6083: - yyssp++;
6084: -
6085: - yysetstate:
6086: - *yyssp = yystate;
6087: -
6088: - if (yyss + yystacksize - 1 <= yyssp)
6089: - {
6090: - /* Get the current used size of the three stacks, in elements. */
6091: - YYSIZE_T yysize = yyssp - yyss + 1;
6092: -
6093: -#ifdef yyoverflow
6094: - {
6095: - /* Give user a chance to reallocate the stack. Use copies of
6096: - these so that the &'s don't force the real ones into
6097: - memory. */
6098: - YYSTYPE *yyvs1 = yyvs;
6099: - yytype_int16 *yyss1 = yyss;
6100: -
6101: - /* Each stack pointer address is followed by the size of the
6102: - data in use in that stack, in bytes. This used to be a
6103: - conditional around just the two extra args, but that might
6104: - be undefined if yyoverflow is a macro. */
6105: - yyoverflow (YY_("memory exhausted"),
6106: - &yyss1, yysize * sizeof (*yyssp),
6107: - &yyvs1, yysize * sizeof (*yyvsp),
6108: - &yystacksize);
6109: -
6110: - yyss = yyss1;
6111: - yyvs = yyvs1;
6112: - }
6113: -#else /* no yyoverflow */
6114: -# ifndef YYSTACK_RELOCATE
6115: - goto yyexhaustedlab;
6116: -# else
6117: - /* Extend the stack our own way. */
6118: - if (YYMAXDEPTH <= yystacksize)
6119: - goto yyexhaustedlab;
6120: - yystacksize *= 2;
6121: - if (YYMAXDEPTH < yystacksize)
6122: - yystacksize = YYMAXDEPTH;
6123: -
6124: - {
6125: - yytype_int16 *yyss1 = yyss;
6126: - union yyalloc *yyptr =
6127: - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
6128: - if (! yyptr)
6129: - goto yyexhaustedlab;
6130: - YYSTACK_RELOCATE (yyss_alloc, yyss);
6131: - YYSTACK_RELOCATE (yyvs_alloc, yyvs);
6132: -# undef YYSTACK_RELOCATE
6133: - if (yyss1 != yyssa)
6134: - YYSTACK_FREE (yyss1);
6135: - }
6136: -# endif
6137: -#endif /* no yyoverflow */
6138: -
6139: - yyssp = yyss + yysize - 1;
6140: - yyvsp = yyvs + yysize - 1;
6141: -
6142: - YYDPRINTF ((stderr, "Stack size increased to %lu\n",
6143: - (unsigned long int) yystacksize));
6144: -
6145: - if (yyss + yystacksize - 1 <= yyssp)
6146: - YYABORT;
6147: - }
6148: -
6149: - YYDPRINTF ((stderr, "Entering state %d\n", yystate));
6150: -
6151: - if (yystate == YYFINAL)
6152: - YYACCEPT;
6153: -
6154: - goto yybackup;
6155: -
6156: -/*-----------.
6157: -| yybackup. |
6158: -`-----------*/
6159: -yybackup:
6160: -
6161: - /* Do appropriate processing given the current state. Read a
6162: - lookahead token if we need one and don't already have one. */
6163: -
6164: - /* First try to decide what to do without reference to lookahead token. */
6165: - yyn = yypact[yystate];
6166: - if (yypact_value_is_default (yyn))
6167: - goto yydefault;
6168: -
6169: - /* Not known => get a lookahead token if don't already have one. */
6170: -
6171: - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
6172: - if (yychar == YYEMPTY)
6173: - {
6174: - YYDPRINTF ((stderr, "Reading a token: "));
6175: - yychar = yylex (&yylval, scan);
6176: - }
6177: -
6178: - if (yychar <= YYEOF)
6179: - {
6180: - yychar = yytoken = YYEOF;
6181: - YYDPRINTF ((stderr, "Now at end of input.\n"));
6182: - }
6183: - else
6184: - {
6185: - yytoken = YYTRANSLATE (yychar);
6186: - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
6187: - }
6188: -
6189: - /* If the proper action on seeing token YYTOKEN is to reduce or to
6190: - detect an error, take that action. */
6191: - yyn += yytoken;
6192: - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
6193: - goto yydefault;
6194: - yyn = yytable[yyn];
6195: - if (yyn <= 0)
6196: - {
6197: - if (yytable_value_is_error (yyn))
6198: - goto yyerrlab;
6199: - yyn = -yyn;
6200: - goto yyreduce;
6201: - }
6202: -
6203: - /* Count tokens shifted since error; after three, turn off error
6204: - status. */
6205: - if (yyerrstatus)
6206: - yyerrstatus--;
6207: -
6208: - /* Shift the lookahead token. */
6209: - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
6210: -
6211: - /* Discard the shifted token. */
6212: - yychar = YYEMPTY;
6213: -
6214: - yystate = yyn;
6215: - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
6216: - *++yyvsp = yylval;
6217: - YY_IGNORE_MAYBE_UNINITIALIZED_END
6218: -
6219: - goto yynewstate;
6220: -
6221: -
6222: -/*-----------------------------------------------------------.
6223: -| yydefault -- do the default action for the current state. |
6224: -`-----------------------------------------------------------*/
6225: -yydefault:
6226: - yyn = yydefact[yystate];
6227: - if (yyn == 0)
6228: - goto yyerrlab;
6229: - goto yyreduce;
6230: -
6231: -
6232: -/*-----------------------------.
6233: -| yyreduce -- Do a reduction. |
6234: -`-----------------------------*/
6235: -yyreduce:
6236: - /* yyn is the number of a rule to reduce with. */
6237: - yylen = yyr2[yyn];
6238: -
6239: - /* If YYLEN is nonzero, implement the default value of the action:
6240: - '$$ = $1'.
6241: -
6242: - Otherwise, the following line sets YYVAL to garbage.
6243: - This behavior is undocumented and Bison
6244: - users should not rely upon it. Assigning to YYVAL
6245: - unconditionally makes the parser a bit smaller, and it avoids a
6246: - GCC warning that YYVAL may be used uninitialized. */
6247: - yyval = yyvsp[1-yylen];
6248: -
6249: -
6250: - YY_REDUCE_PRINT (yyn);
6251: - switch (yyn)
6252: - {
6253: - case 3:
6254: -#line 50 "sexpr_parse.y" /* yacc.c:1646 */
6255: - { return -1;}
6256: -#line 1244 "sexpr_parse.c" /* yacc.c:1646 */
6257: - break;
6258: -
6259: - case 4:
6260: -#line 51 "sexpr_parse.y" /* yacc.c:1646 */
6261: - { *result = (yyvsp[0]); YYACCEPT;}
6262: -#line 1250 "sexpr_parse.c" /* yacc.c:1646 */
6263: - break;
6264: -
6265: - case 6:
6266: -#line 54 "sexpr_parse.y" /* yacc.c:1646 */
6267: - { (yyval) = cons(sym_quote, cons((yyvsp[0]), NIL)); }
6268: -#line 1256 "sexpr_parse.c" /* yacc.c:1646 */
6269: - break;
6270: -
6271: - case 7:
6272: -#line 55 "sexpr_parse.y" /* yacc.c:1646 */
6273: - { (yyval) = cons(sym_quasiquote, cons((yyvsp[0]), NIL)); }
6274: -#line 1262 "sexpr_parse.c" /* yacc.c:1646 */
6275: - break;
6276: -
6277: - case 8:
6278: -#line 56 "sexpr_parse.y" /* yacc.c:1646 */
6279: - { (yyval) = cons(sym_splice, cons((yyvsp[0]), NIL)); }
6280: -#line 1268 "sexpr_parse.c" /* yacc.c:1646 */
6281: - break;
6282: -
6283: - case 9:
6284: -#line 57 "sexpr_parse.y" /* yacc.c:1646 */
6285: - { (yyval) = cons(sym_unquote, cons((yyvsp[0]), NIL)); }
6286: -#line 1274 "sexpr_parse.c" /* yacc.c:1646 */
6287: - break;
6288: -
6289: - case 10:
6290: -#line 58 "sexpr_parse.y" /* yacc.c:1646 */
6291: - { (yyval) = cons((yyvsp[-3]),(yyvsp[-1])); }
6292: -#line 1280 "sexpr_parse.c" /* yacc.c:1646 */
6293: - break;
6294: -
6295: - case 11:
6296: -#line 59 "sexpr_parse.y" /* yacc.c:1646 */
6297: - { (yyval) = NIL; }
6298: -#line 1286 "sexpr_parse.c" /* yacc.c:1646 */
6299: - break;
6300: -
6301: - case 12:
6302: -#line 60 "sexpr_parse.y" /* yacc.c:1646 */
6303: - { (yyval) = (yyvsp[0]); }
6304: -#line 1292 "sexpr_parse.c" /* yacc.c:1646 */
6305: - break;
6306: -
6307: - case 13:
6308: -#line 62 "sexpr_parse.y" /* yacc.c:1646 */
6309: - { (yyval) = cons((yyvsp[-2]),(yyvsp[-1])); }
6310: -#line 1298 "sexpr_parse.c" /* yacc.c:1646 */
6311: - break;
6312: -
6313: - case 14:
6314: -#line 64 "sexpr_parse.y" /* yacc.c:1646 */
6315: - { (yyval) = NIL; }
6316: -#line 1304 "sexpr_parse.c" /* yacc.c:1646 */
6317: - break;
6318: -
6319: - case 15:
6320: -#line 65 "sexpr_parse.y" /* yacc.c:1646 */
6321: - { (yyval) = cons((yyvsp[-1]),(yyvsp[0])); }
6322: -#line 1310 "sexpr_parse.c" /* yacc.c:1646 */
6323: - break;
6324: -
6325: -
6326: -#line 1314 "sexpr_parse.c" /* yacc.c:1646 */
6327: - default: break;
6328: - }
6329: - /* User semantic actions sometimes alter yychar, and that requires
6330: - that yytoken be updated with the new translation. We take the
6331: - approach of translating immediately before every use of yytoken.
6332: - One alternative is translating here after every semantic action,
6333: - but that translation would be missed if the semantic action invokes
6334: - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
6335: - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
6336: - incorrect destructor might then be invoked immediately. In the
6337: - case of YYERROR or YYBACKUP, subsequent parser actions might lead
6338: - to an incorrect destructor call or verbose syntax error message
6339: - before the lookahead is translated. */
6340: - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
6341: -
6342: - YYPOPSTACK (yylen);
6343: - yylen = 0;
6344: - YY_STACK_PRINT (yyss, yyssp);
6345: -
6346: - *++yyvsp = yyval;
6347: -
6348: - /* Now 'shift' the result of the reduction. Determine what state
6349: - that goes to, based on the state we popped back to and the rule
6350: - number reduced by. */
6351: -
6352: - yyn = yyr1[yyn];
6353: -
6354: - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
6355: - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
6356: - yystate = yytable[yystate];
6357: - else
6358: - yystate = yydefgoto[yyn - YYNTOKENS];
6359: -
6360: - goto yynewstate;
6361: -
6362: -
6363: -/*--------------------------------------.
6364: -| yyerrlab -- here on detecting error. |
6365: -`--------------------------------------*/
6366: -yyerrlab:
6367: - /* Make sure we have latest lookahead translation. See comments at
6368: - user semantic actions for why this is necessary. */
6369: - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
6370: -
6371: - /* If not already recovering from an error, report this error. */
6372: - if (!yyerrstatus)
6373: - {
6374: - ++yynerrs;
6375: -#if ! YYERROR_VERBOSE
6376: - yyerror (result, scan, YY_("syntax error"));
6377: -#else
6378: -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
6379: - yyssp, yytoken)
6380: - {
6381: - char const *yymsgp = YY_("syntax error");
6382: - int yysyntax_error_status;
6383: - yysyntax_error_status = YYSYNTAX_ERROR;
6384: - if (yysyntax_error_status == 0)
6385: - yymsgp = yymsg;
6386: - else if (yysyntax_error_status == 1)
6387: - {
6388: - if (yymsg != yymsgbuf)
6389: - YYSTACK_FREE (yymsg);
6390: - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
6391: - if (!yymsg)
6392: - {
6393: - yymsg = yymsgbuf;
6394: - yymsg_alloc = sizeof yymsgbuf;
6395: - yysyntax_error_status = 2;
6396: - }
6397: - else
6398: - {
6399: - yysyntax_error_status = YYSYNTAX_ERROR;
6400: - yymsgp = yymsg;
6401: - }
6402: - }
6403: - yyerror (result, scan, yymsgp);
6404: - if (yysyntax_error_status == 2)
6405: - goto yyexhaustedlab;
6406: - }
6407: -# undef YYSYNTAX_ERROR
6408: -#endif
6409: - }
6410: -
6411: -
6412: -
6413: - if (yyerrstatus == 3)
6414: - {
6415: - /* If just tried and failed to reuse lookahead token after an
6416: - error, discard it. */
6417: -
6418: - if (yychar <= YYEOF)
6419: - {
6420: - /* Return failure if at end of input. */
6421: - if (yychar == YYEOF)
6422: - YYABORT;
6423: - }
6424: - else
6425: - {
6426: - yydestruct ("Error: discarding",
6427: - yytoken, &yylval, result, scan);
6428: - yychar = YYEMPTY;
6429: - }
6430: - }
6431: -
6432: - /* Else will try to reuse lookahead token after shifting the error
6433: - token. */
6434: - goto yyerrlab1;
6435: -
6436: -
6437: -/*---------------------------------------------------.
6438: -| yyerrorlab -- error raised explicitly by YYERROR. |
6439: -`---------------------------------------------------*/
6440: -yyerrorlab:
6441: -
6442: - /* Pacify compilers like GCC when the user code never invokes
6443: - YYERROR and the label yyerrorlab therefore never appears in user
6444: - code. */
6445: - if (/*CONSTCOND*/ 0)
6446: - goto yyerrorlab;
6447: -
6448: - /* Do not reclaim the symbols of the rule whose action triggered
6449: - this YYERROR. */
6450: - YYPOPSTACK (yylen);
6451: - yylen = 0;
6452: - YY_STACK_PRINT (yyss, yyssp);
6453: - yystate = *yyssp;
6454: - goto yyerrlab1;
6455: -
6456: -
6457: -/*-------------------------------------------------------------.
6458: -| yyerrlab1 -- common code for both syntax error and YYERROR. |
6459: -`-------------------------------------------------------------*/
6460: -yyerrlab1:
6461: - yyerrstatus = 3; /* Each real token shifted decrements this. */
6462: -
6463: - for (;;)
6464: - {
6465: - yyn = yypact[yystate];
6466: - if (!yypact_value_is_default (yyn))
6467: - {
6468: - yyn += YYTERROR;
6469: - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
6470: - {
6471: - yyn = yytable[yyn];
6472: - if (0 < yyn)
6473: - break;
6474: - }
6475: - }
6476: -
6477: - /* Pop the current state because it cannot handle the error token. */
6478: - if (yyssp == yyss)
6479: - YYABORT;
6480: -
6481: -
6482: - yydestruct ("Error: popping",
6483: - yystos[yystate], yyvsp, result, scan);
6484: - YYPOPSTACK (1);
6485: - yystate = *yyssp;
6486: - YY_STACK_PRINT (yyss, yyssp);
6487: - }
6488: -
6489: - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
6490: - *++yyvsp = yylval;
6491: - YY_IGNORE_MAYBE_UNINITIALIZED_END
6492: -
6493: -
6494: - /* Shift the error token. */
6495: - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
6496: -
6497: - yystate = yyn;
6498: - goto yynewstate;
6499: -
6500: -
6501: -/*-------------------------------------.
6502: -| yyacceptlab -- YYACCEPT comes here. |
6503: -`-------------------------------------*/
6504: -yyacceptlab:
6505: - yyresult = 0;
6506: - goto yyreturn;
6507: -
6508: -/*-----------------------------------.
6509: -| yyabortlab -- YYABORT comes here. |
6510: -`-----------------------------------*/
6511: -yyabortlab:
6512: - yyresult = 1;
6513: - goto yyreturn;
6514: -
6515: -#if !defined yyoverflow || YYERROR_VERBOSE
6516: -/*-------------------------------------------------.
6517: -| yyexhaustedlab -- memory exhaustion comes here. |
6518: -`-------------------------------------------------*/
6519: -yyexhaustedlab:
6520: - yyerror (result, scan, YY_("memory exhausted"));
6521: - yyresult = 2;
6522: - /* Fall through. */
6523: -#endif
6524: -
6525: -yyreturn:
6526: - if (yychar != YYEMPTY)
6527: - {
6528: - /* Make sure we have latest lookahead translation. See comments at
6529: - user semantic actions for why this is necessary. */
6530: - yytoken = YYTRANSLATE (yychar);
6531: - yydestruct ("Cleanup: discarding lookahead",
6532: - yytoken, &yylval, result, scan);
6533: - }
6534: - /* Do not reclaim the symbols of the rule whose action triggered
6535: - this YYABORT or YYACCEPT. */
6536: - YYPOPSTACK (yylen);
6537: - YY_STACK_PRINT (yyss, yyssp);
6538: - while (yyssp != yyss)
6539: - {
6540: - yydestruct ("Cleanup: popping",
6541: - yystos[*yyssp], yyvsp, result, scan);
6542: - YYPOPSTACK (1);
6543: - }
6544: -#ifndef yyoverflow
6545: - if (yyss != yyssa)
6546: - YYSTACK_FREE (yyss);
6547: -#endif
6548: -#if YYERROR_VERBOSE
6549: - if (yymsg != yymsgbuf)
6550: - YYSTACK_FREE (yymsg);
6551: -#endif
6552: - return yyresult;
6553: -}
6554: -#line 69 "sexpr_parse.y" /* yacc.c:1906 */
6555: -
6556: -
6557: -void yylex_init(void **);
6558: -void yyset_in(FILE *, void *);
6559: -void yylex_destroy(void *);
6560: -
6561: -
6562: -/*
6563: - * Read
6564: - */
6565: -
6566: -void
6567: -sexpr_read_start(FILE *f, void **yyscan)
6568: -{
6569: -
6570: - yylex_init(yyscan);
6571: - yyset_in(f, *yyscan);
6572: -}
6573: -
6574: -int
6575: -sexpr_read(lreg_t *res, void *yyscan)
6576: -{
6577: - int r;
6578: -
6579: - r = yyparse(res, yyscan);
6580: - switch (r) {
6581: - case 0:
6582: - return 1;
6583: - case -1:
6584: - return 0;
6585: - case 1: /* Syntax Error */
6586: - case 2: /* Memory Exhaustion */
6587: - default: /* Unknown */
6588: - raise_exception("parser error", NIL);
6589: - /* Not reached. */
6590: - return 0;
6591: - }
6592: -}
6593: -
6594: -void
6595: -sexpr_read_stop(void *yyscan)
6596: -{
6597: -
6598: - yylex_destroy(yyscan);
6599: -}
6600: -
6601: -
6602: -/*
6603: - * Print
6604: - */
6605: -
6606: -static void sexpr_print_cons(FILE *f, lreg_t lr, const char *h)
6607: -{
6608: - lreg_t a = car(lr);
6609: - lreg_t d = cdr(lr);
6610: -
6611: - printf(h);
6612: - sexpr_print(f, a);
6613: -
6614: - if (d == NIL) {
6615: - fprintf(f, ")");
6616: - return;
6617: - }
6618: -
6619: - if (lreg_raw_type(d) == LREG_CONS)
6620: - sexpr_print_cons(f, d, " ");
6621: - else
6622: - {
6623: - fprintf(f, " . ");
6624: - sexpr_print(f, cdr(lr));
6625: - fprintf(f, ")");
6626: - }
6627: -}
6628: -
6629: -void sexpr_print(FILE *f, lreg_t lr)
6630: -{
6631: - switch ( lreg_type(lr) )
6632: - {
6633: - case LREG_NIL:
6634: - fprintf(f, "()");
6635: - break;
6636: - case LREG_SYMBOL:
6637: - fprintf(f, "%s", (char *)lreg_raw_ptr(lr));
6638: - break;
6639: - case LREG_STRING:
6640: - fprintf(f, "\"%s\"", (char *)lreg_raw_ptr(lr));
6641: - break;
6642: - case LREG_CONS:
6643: - sexpr_print_cons(f, lr, "(");
6644: - break;
6645: - case LREG_MACRO:
6646: - fprintf(f, "<#MACRO>");
6647: - break;
6648: - case LREG_LAMBDA:
6649: - fprintf(f, "<#LAMBDA>");
6650: - break;
6651: - case LREG_LLPROC:
6652: - fprintf(f, "<#LLPROC>");
6653: - break;
6654: - default:
6655: - if ( !lac_extty_print(f, lr) )
6656: - fprintf(f, "<??? %d>",(int)lreg_type(lr));
6657: - }
6658: - return;
6659: -}
6660: diff --git a/src/lib/sexpr_parse.h b/src/lib/sexpr_parse.h
6661: deleted file mode 100644
6662: index f2c1b2f..0000000
6663: --- a/src/lib/sexpr_parse.h
6664: +++ /dev/null
6665: @@ -1,77 +0,0 @@
6666: -/* A Bison parser, made by GNU Bison 3.0.4. */
6667: -
6668: -/* Bison interface for Yacc-like parsers in C
6669: -
6670: - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
6671: -
6672: - This program is free software: you can redistribute it and/or modify
6673: - it under the terms of the GNU General Public License as published by
6674: - the Free Software Foundation, either version 3 of the License, or
6675: - (at your option) any later version.
6676: -
6677: - This program is distributed in the hope that it will be useful,
6678: - but WITHOUT ANY WARRANTY; without even the implied warranty of
6679: - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6680: - GNU General Public License for more details.
6681: -
6682: - You should have received a copy of the GNU General Public License
6683: - along with this program. If not, see <http://www.gnu.org/licenses/>. */
6684: -
6685: -/* As a special exception, you may create a larger work that contains
6686: - part or all of the Bison parser skeleton and distribute that work
6687: - under terms of your choice, so long as that work isn't itself a
6688: - parser generator using the skeleton or a modified version thereof
6689: - as a parser skeleton. Alternatively, if you modify or redistribute
6690: - the parser skeleton itself, you may (at your option) remove this
6691: - special exception, which will cause the skeleton and the resulting
6692: - Bison output files to be licensed under the GNU General Public
6693: - License without this special exception.
6694: -
6695: - This special exception was added by the Free Software Foundation in
6696: - version 2.2 of Bison. */
6697: -
6698: -#ifndef YY_YY_SEXPR_PARSE_H_INCLUDED
6699: -# define YY_YY_SEXPR_PARSE_H_INCLUDED
6700: -/* Debug traces. */
6701: -#ifndef YYDEBUG
6702: -# define YYDEBUG 0
6703: -#endif
6704: -#if YYDEBUG
6705: -extern int yydebug;
6706: -#endif
6707: -
6708: -/* Token type. */
6709: -#ifndef YYTOKENTYPE
6710: -# define YYTOKENTYPE
6711: - enum yytokentype
6712: - {
6713: - ENDOFFILE = 258,
6714: - NIHIL = 259,
6715: - STRING = 260,
6716: - INTEGER = 261,
6717: - SYMBOL = 262,
6718: - DELIMITER = 263,
6719: - COMMA_AT = 264
6720: - };
6721: -#endif
6722: -/* Tokens. */
6723: -#define ENDOFFILE 258
6724: -#define NIHIL 259
6725: -#define STRING 260
6726: -#define INTEGER 261
6727: -#define SYMBOL 262
6728: -#define DELIMITER 263
6729: -#define COMMA_AT 264
6730: -
6731: -/* Value type. */
6732: -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
6733: -typedef lreg_t YYSTYPE;
6734: -# define YYSTYPE_IS_TRIVIAL 1
6735: -# define YYSTYPE_IS_DECLARED 1
6736: -#endif
6737: -
6738: -
6739: -
6740: -int yyparse (lreg_t *result, void *scan);
6741: -
6742: -#endif /* !YY_YY_SEXPR_PARSE_H_INCLUDED */
6743: diff --git a/src/lib/sexpr_parse.y b/src/lib/sexpr_parse.y
6744: deleted file mode 100644
6745: index 122a546..0000000
6746: --- a/src/lib/sexpr_parse.y
6747: +++ /dev/null
6748: @@ -1,173 +0,0 @@
6749: -/*
6750: - lac -- a lisp interpreter library
6751: - Copyright (C) 2010 Gianluca Guida
6752: -
6753: - This program is free software; you can redistribute it and/or modify
6754: - it under the terms of the GNU General Public License as published by
6755: - the Free Software Foundation; either version 2 of the License, or
6756: - (at your option) any later version.
6757: -
6758: - This program is distributed in the hope that it will be useful,
6759: - but WITHOUT ANY WARRANTY; without even the implied warranty of
6760: - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6761: - GNU General Public License for more details.
6762: -
6763: - You should have received a copy of the GNU General Public License along
6764: - with this program; if not, write to the Free Software Foundation, Inc.,
6765: - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6766: -*/
6767: -
6768: -%{
6769: -#include <stdio.h>
6770: -#include <string.h>
6771: -#include <gc/gc.h>
6772: -#include "lac.h"
6773: -#include "sexpr_parse.h"
6774: -
6775: -int yylex(lreg_t *, void *);
6776: -void yyerror (lreg_t *lr, void *scanner, const char *msgp) /* Called by yyparse on error */
6777: -{
6778: -}
6779: -
6780: -%}
6781: -
6782: -%defines
6783: -%define api.pure full
6784: -%define api.value.type { lreg_t }
6785: -%parse-param { lreg_t *result }
6786: -%param { void *scan }
6787: -
6788: -%token ENDOFFILE
6789: -%token NIHIL
6790: -%token STRING
6791: -%token INTEGER
6792: -%token SYMBOL
6793: -%token DELIMITER
6794: -%token COMMA_AT
6795: -
6796: -%%
6797: -
6798: -input: | input ENDOFFILE { return -1;}
6799: - | input sexpr { *result = $2; YYACCEPT;};
6800: -
6801: -sexpr: atom ;
6802: - | '\'' sexpr { $$ = cons(sym_quote, cons($2, NIL)); }
6803: - | '`' sexpr { $$ = cons(sym_quasiquote, cons($2, NIL)); }
6804: - | COMMA_AT sexpr { $$ = cons(sym_splice, cons($2, NIL)); }
6805: - | ',' sexpr { $$ = cons(sym_unquote, cons($2, NIL)); }
6806: - | '(' sexpr '.' sexpr ')' { $$ = cons($2,$4); }
6807: - | '(' ')' { $$ = NIL; }
6808: - | list { $$ = $1; }
6809: -
6810: -list: '(' sexpr listelem ')' { $$ = cons($2,$3); }
6811: -;
6812: -listelem: /*EMPTY*/ { $$ = NIL; }
6813: - | sexpr listelem { $$ = cons($1,$2); }
6814: -
6815: -atom: SYMBOL | STRING | INTEGER | NIHIL
6816: -
6817: -%%
6818: -
6819: -void yylex_init(void **);
6820: -void yyset_in(FILE *, void *);
6821: -void yylex_destroy(void *);
6822: -
6823: -
6824: -/*
6825: - * Read
6826: - */
6827: -
6828: -void
6829: -sexpr_read_start(FILE *f, void **yyscan)
6830: -{
6831: -
6832: - yylex_init(yyscan);
6833: - yyset_in(f, *yyscan);
6834: -}
6835: -
6836: -int
6837: -sexpr_read(lreg_t *res, void *yyscan)
6838: -{
6839: - int r;
6840: -
6841: - r = yyparse(res, yyscan);
6842: - switch (r) {
6843: - case 0:
6844: - return 1;
6845: - case -1:
6846: - return 0;
6847: - case 1: /* Syntax Error */
6848: - case 2: /* Memory Exhaustion */
6849: - default: /* Unknown */
6850: - raise_exception("parser error", NIL);
6851: - /* Not reached. */
6852: - return 0;
6853: - }
6854: -}
6855: -
6856: -void
6857: -sexpr_read_stop(void *yyscan)
6858: -{
6859: -
6860: - yylex_destroy(yyscan);
6861: -}
6862: -
6863: -
6864: -/*
6865: - * Print
6866: - */
6867: -
6868: -static void sexpr_print_cons(FILE *f, lreg_t lr, const char *h)
6869: -{
6870: - lreg_t a = car(lr);
6871: - lreg_t d = cdr(lr);
6872: -
6873: - printf(h);
6874: - sexpr_print(f, a);
6875: -
6876: - if (d == NIL) {
6877: - fprintf(f, ")");
6878: - return;
6879: - }
6880: -
6881: - if (lreg_raw_type(d) == LREG_CONS)
6882: - sexpr_print_cons(f, d, " ");
6883: - else
6884: - {
6885: - fprintf(f, " . ");
6886: - sexpr_print(f, cdr(lr));
6887: - fprintf(f, ")");
6888: - }
6889: -}
6890: -
6891: -void sexpr_print(FILE *f, lreg_t lr)
6892: -{
6893: - switch ( lreg_type(lr) )
6894: - {
6895: - case LREG_NIL:
6896: - fprintf(f, "()");
6897: - break;
6898: - case LREG_SYMBOL:
6899: - fprintf(f, "%s", (char *)lreg_raw_ptr(lr));
6900: - break;
6901: - case LREG_STRING:
6902: - fprintf(f, "\"%s\"", (char *)lreg_raw_ptr(lr));
6903: - break;
6904: - case LREG_CONS:
6905: - sexpr_print_cons(f, lr, "(");
6906: - break;
6907: - case LREG_MACRO:
6908: - fprintf(f, "<#MACRO>");
6909: - break;
6910: - case LREG_LAMBDA:
6911: - fprintf(f, "<#LAMBDA>");
6912: - break;
6913: - case LREG_LLPROC:
6914: - fprintf(f, "<#LLPROC>");
6915: - break;
6916: - default:
6917: - if ( !lac_extty_print(f, lr) )
6918: - fprintf(f, "<??? %d>",(int)lreg_type(lr));
6919: - }
6920: - return;
6921: -}
6922: diff --git a/src/lib/ty_string.c b/src/lib/ty_string.c
6923: index 6c7f5d0..e164ed0 100644
6924: --- a/src/lib/ty_string.c
6925: +++ b/src/lib/ty_string.c
6926: @@ -25,25 +25,6 @@
6927:
6928: #define ARGEVAL(_lr, _e) ((_e) == NULL ? _lr : eval((_lr), (_e)))
6929:
6930: -static void string_print(FILE *fd, lreg_t lr)
6931: -{
6932: - char *s;
6933: -
6934: - s = (char *)lreg_raw_ptr(lr);
6935: - fprintf(fd, "\"%s\" ", s);
6936: -}
6937: -
6938: -static lreg_t string_eq(lreg_t arg1, lreg_t arg2)
6939: -{
6940: - char *s1, *s2;
6941: -
6942: - s1 = (char *)lreg_raw_ptr(arg1);
6943: - s2 = (char *)lreg_raw_ptr(arg2);
6944: - if ( s1 == s2 )
6945: - return sym_true;
6946: - return sym_false;
6947: -}
6948: -
6949: static int string_compare(lreg_t arg1, lreg_t arg2)
6950: {
6951: int d;
6952: diff --git a/src/repl/Makefile.in b/src/repl/Makefile.in
6953: index d858641..8f7a0ab 100644
6954: --- a/src/repl/Makefile.in
6955: +++ b/src/repl/Makefile.in
6956: @@ -91,11 +91,12 @@ host_triplet = @host@
6957: bin_PROGRAMS = lac$(EXEEXT)
6958: subdir = src/repl
6959: ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
6960: -am__aclocal_m4_deps = $(top_srcdir)/m4/lib-ld.m4 \
6961: - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
6962: - $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/libtool.m4 \
6963: - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
6964: - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
6965: +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_prog_flex.m4 \
6966: + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
6967: + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \
6968: + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
6969: + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
6970: + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
6971: $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/std-gnu11.m4 \
6972: $(top_srcdir)/configure.ac
6973: am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
6974: @@ -187,8 +188,6 @@ AUTOMAKE = @AUTOMAKE@
6975: AWK = @AWK@
6976: BDW_GC_CFLAGS = @BDW_GC_CFLAGS@
6977: BDW_GC_LIBS = @BDW_GC_LIBS@
6978: -BISON = @BISON@
6979: -BISON_VERSION = @BISON_VERSION@
6980: CC = @CC@
6981: CCDEPMODE = @CCDEPMODE@
6982: CFLAGS = @CFLAGS@
6983: diff --git a/src/repl/lac.c b/src/repl/lac.c
6984: index f360fd5..bd5d10a 100644
6985: --- a/src/repl/lac.c
6986: +++ b/src/repl/lac.c
6987: @@ -4,25 +4,28 @@
6988: #include <setjmp.h>
6989: #include <unistd.h>
6990: #include <signal.h>
6991: +#include <readline/readline.h>
6992: +#include <readline/history.h>
6993: #include "lac.h"
6994:
6995: lenv_t *null_env;
6996:
6997: -void lac_error_print(FILE *f)
6998: +void
6999: +lac_error_print (FILE * f)
7000: {
7001: - fprintf(f, "(*LAC-ERROR* \"%s", lac_errmsg());
7002: - if (lac_errlreg() != NIL)
7003: + fprintf (f, "(*LAC-ERROR* \"%s", lac_errmsg ());
7004: + if (lac_errlreg () != NIL)
7005: {
7006: - fprintf(f, ": ");
7007: - sexpr_print(f, lac_errlreg());
7008: + fprintf (f, ": ");
7009: + sexpr_fprint (f, lac_errlreg ());
7010: }
7011: - fprintf(f, "\")\n");
7012: + fprintf (f, "\")\n");
7013: }
7014:
7015: void
7016: -sigint(int sig)
7017: +sigint (int sig)
7018: {
7019: - raise_exception("Interrupted", NIL);
7020: + raise_exception ("Interrupted", NIL);
7021: }
7022:
7023: #define TDIFF_SEC(_a, _b) \
7024: @@ -36,56 +39,56 @@ sigint(int sig)
7025: : (_b)->tv_usec + 1000000L - (_a)->tv_usec)
7026:
7027:
7028: -int repl(FILE *infd, FILE *outfd, FILE *errfd)
7029: +int
7030: +repl (FILE * infd, FILE * outfd, FILE * errfd)
7031: {
7032: int r;
7033: - void *scan;
7034: + char *buf = NULL;
7035: lreg_t res = NIL;
7036: struct timeval t1, t2;
7037:
7038: - restart:
7039: - lac_on_error({
7040: - lac_error_print(errfd);
7041: - sexpr_read_stop(scan);
7042: - res = NIL;
7043: - goto restart;
7044: - });
7045: -
7046: - sexpr_read_start(infd, &scan);
7047: - do {
7048: - r = sexpr_read(&res, scan);
7049: -
7050: - gettimeofday(&t1, NULL);
7051: - res = eval(res, null_env);
7052: - gettimeofday(&t2, NULL);
7053: -
7054: - if ( isatty(fileno(outfd)) ) {
7055: - fprintf(outfd, "=> ");
7056: - sexpr_print(outfd, res);
7057: - fprintf(outfd, "\n");
7058: - fprintf(outfd,
7059: - "Evaluation took %ld seconds and %ld microseconds.\n",
7060: - TDIFF_SEC(&t1, &t2), TDIFF_USEC(&t1, &t2));
7061: +restart:
7062: + lac_on_error ({
7063: + lac_error_print (errfd); res = NIL; goto restart;
7064: + });
7065: +
7066: +
7067: + do
7068: + {
7069: + buf = readline ("LAC>");
7070: + if (buf == NULL)
7071: + return -1;
7072: + if (*buf != '\0')
7073: + add_history (buf);
7074: +
7075: + res = sexpr_parse_string (buf,
7076: + (lreg_t (*)(lreg_t, void *))eval,
7077: + (void *)null_env);
7078: + if (isatty (fileno (outfd)))
7079: + {
7080: + fprintf (outfd, "=> ");
7081: + sexpr_fprint (outfd, res);
7082: + fprintf (outfd, "\n");
7083: + }
7084: }
7085: - } while(r);
7086: - sexpr_read_stop(scan);
7087: + while (1);
7088:
7089: - lac_off_error();
7090: + lac_off_error ();
7091: return r;
7092: }
7093:
7094: -int main()
7095: +int
7096: +main ()
7097: {
7098:
7099: - signal(SIGINT, sigint);
7100: + signal (SIGINT, sigint);
7101: +
7102: + lac_on_error ({
7103: + lac_error_print (stderr); exit (-1);
7104: + });
7105:
7106: - lac_on_error({
7107: - lac_error_print(stderr);
7108: - exit(-1);
7109: - });
7110: -
7111: - null_env = lac_init();
7112: - repl(stdin, stdout, stderr);
7113: - fprintf(stdout, "\ngoodbye!\n");
7114: + null_env = lac_init ();
7115: + repl (stdin, stdout, stderr);
7116: + fprintf (stdout, "\ngoodbye!\n");
7117: return 0;
7118: }
7119: diff --git a/tools/lemon.c b/tools/lemon.c
7120: new file mode 100644
7121: index 0000000..aa0f4e3
7122: --- /dev/null
7123: +++ b/tools/lemon.c
7124: @@ -0,0 +1,5436 @@
7125: +/*
7126: +** This file contains all sources (including headers) to the LEMON
7127: +** LALR(1) parser generator. The sources have been combined into a
7128: +** single file to make it easy to include LEMON in the source tree
7129: +** and Makefile of another program.
7130: +**
7131: +** The author of this program disclaims copyright.
7132: +*/
7133: +#include <stdio.h>
7134: +#include <stdarg.h>
7135: +#include <string.h>
7136: +#include <ctype.h>
7137: +#include <stdlib.h>
7138: +#include <assert.h>
7139: +
7140: +#define ISSPACE(X) isspace((unsigned char)(X))
7141: +#define ISDIGIT(X) isdigit((unsigned char)(X))
7142: +#define ISALNUM(X) isalnum((unsigned char)(X))
7143: +#define ISALPHA(X) isalpha((unsigned char)(X))
7144: +#define ISUPPER(X) isupper((unsigned char)(X))
7145: +#define ISLOWER(X) islower((unsigned char)(X))
7146: +
7147: +
7148: +#ifndef __WIN32__
7149: +# if defined(_WIN32) || defined(WIN32)
7150: +# define __WIN32__
7151: +# endif
7152: +#endif
7153: +
7154: +#ifdef __WIN32__
7155: +#ifdef __cplusplus
7156: +extern "C" {
7157: +#endif
7158: +extern int access(const char *path, int mode);
7159: +#ifdef __cplusplus
7160: +}
7161: +#endif
7162: +#else
7163: +#include <unistd.h>
7164: +#endif
7165: +
7166: +/* #define PRIVATE static */
7167: +#define PRIVATE
7168: +
7169: +#ifdef TEST
7170: +#define MAXRHS 5 /* Set low to exercise exception code */
7171: +#else
7172: +#define MAXRHS 1000
7173: +#endif
7174: +
7175: +static int showPrecedenceConflict = 0;
7176: +static char *msort(char*,char**,int(*)(const char*,const char*));
7177: +
7178: +/*
7179: +** Compilers are getting increasingly pedantic about type conversions
7180: +** as C evolves ever closer to Ada.... To work around the latest problems
7181: +** we have to define the following variant of strlen().
7182: +*/
7183: +#define lemonStrlen(X) ((int)strlen(X))
7184: +
7185: +/*
7186: +** Compilers are starting to complain about the use of sprintf() and strcpy(),
7187: +** saying they are unsafe. So we define our own versions of those routines too.
7188: +**
7189: +** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and
7190: +** lemon_addtext(). The first two are replacements for sprintf() and vsprintf().
7191: +** The third is a helper routine for vsnprintf() that adds texts to the end of a
7192: +** buffer, making sure the buffer is always zero-terminated.
7193: +**
7194: +** The string formatter is a minimal subset of stdlib sprintf() supporting only
7195: +** a few simply conversions:
7196: +**
7197: +** %d
7198: +** %s
7199: +** %.*s
7200: +**
7201: +*/
7202: +static void lemon_addtext(
7203: + char *zBuf, /* The buffer to which text is added */
7204: + int *pnUsed, /* Slots of the buffer used so far */
7205: + const char *zIn, /* Text to add */
7206: + int nIn, /* Bytes of text to add. -1 to use strlen() */
7207: + int iWidth /* Field width. Negative to left justify */
7208: +){
7209: + if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){}
7210: + while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; }
7211: + if( nIn==0 ) return;
7212: + memcpy(&zBuf[*pnUsed], zIn, nIn);
7213: + *pnUsed += nIn;
7214: + while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; }
7215: + zBuf[*pnUsed] = 0;
7216: +}
7217: +static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){
7218: + int i, j, k, c;
7219: + int nUsed = 0;
7220: + const char *z;
7221: + char zTemp[50];
7222: + str[0] = 0;
7223: + for(i=j=0; (c = zFormat[i])!=0; i++){
7224: + if( c=='%' ){
7225: + int iWidth = 0;
7226: + lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
7227: + c = zFormat[++i];
7228: + if( ISDIGIT(c) || (c=='-' && ISDIGIT(zFormat[i+1])) ){
7229: + if( c=='-' ) i++;
7230: + while( ISDIGIT(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0';
7231: + if( c=='-' ) iWidth = -iWidth;
7232: + c = zFormat[i];
7233: + }
7234: + if( c=='d' ){
7235: + int v = va_arg(ap, int);
7236: + if( v<0 ){
7237: + lemon_addtext(str, &nUsed, "-", 1, iWidth);
7238: + v = -v;
7239: + }else if( v==0 ){
7240: + lemon_addtext(str, &nUsed, "0", 1, iWidth);
7241: + }
7242: + k = 0;
7243: + while( v>0 ){
7244: + k++;
7245: + zTemp[sizeof(zTemp)-k] = (v%10) + '0';
7246: + v /= 10;
7247: + }
7248: + lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth);
7249: + }else if( c=='s' ){
7250: + z = va_arg(ap, const char*);
7251: + lemon_addtext(str, &nUsed, z, -1, iWidth);
7252: + }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){
7253: + i += 2;
7254: + k = va_arg(ap, int);
7255: + z = va_arg(ap, const char*);
7256: + lemon_addtext(str, &nUsed, z, k, iWidth);
7257: + }else if( c=='%' ){
7258: + lemon_addtext(str, &nUsed, "%", 1, 0);
7259: + }else{
7260: + fprintf(stderr, "illegal format\n");
7261: + exit(1);
7262: + }
7263: + j = i+1;
7264: + }
7265: + }
7266: + lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
7267: + return nUsed;
7268: +}
7269: +static int lemon_sprintf(char *str, const char *format, ...){
7270: + va_list ap;
7271: + int rc;
7272: + va_start(ap, format);
7273: + rc = lemon_vsprintf(str, format, ap);
7274: + va_end(ap);
7275: + return rc;
7276: +}
7277: +static void lemon_strcpy(char *dest, const char *src){
7278: + while( (*(dest++) = *(src++))!=0 ){}
7279: +}
7280: +static void lemon_strcat(char *dest, const char *src){
7281: + while( *dest ) dest++;
7282: + lemon_strcpy(dest, src);
7283: +}
7284: +
7285: +
7286: +/* a few forward declarations... */
7287: +struct rule;
7288: +struct lemon;
7289: +struct action;
7290: +
7291: +static struct action *Action_new(void);
7292: +static struct action *Action_sort(struct action *);
7293: +
7294: +/********** From the file "build.h" ************************************/
7295: +void FindRulePrecedences();
7296: +void FindFirstSets();
7297: +void FindStates();
7298: +void FindLinks();
7299: +void FindFollowSets();
7300: +void FindActions();
7301: +
7302: +/********* From the file "configlist.h" *********************************/
7303: +void Configlist_init(void);
7304: +struct config *Configlist_add(struct rule *, int);
7305: +struct config *Configlist_addbasis(struct rule *, int);
7306: +void Configlist_closure(struct lemon *);
7307: +void Configlist_sort(void);
7308: +void Configlist_sortbasis(void);
7309: +struct config *Configlist_return(void);
7310: +struct config *Configlist_basis(void);
7311: +void Configlist_eat(struct config *);
7312: +void Configlist_reset(void);
7313: +
7314: +/********* From the file "error.h" ***************************************/
7315: +void ErrorMsg(const char *, int,const char *, ...);
7316: +
7317: +/****** From the file "option.h" ******************************************/
7318: +enum option_type { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
7319: + OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR};
7320: +struct s_options {
7321: + enum option_type type;
7322: + const char *label;
7323: + char *arg;
7324: + const char *message;
7325: +};
7326: +int OptInit(char**,struct s_options*,FILE*);
7327: +int OptNArgs(void);
7328: +char *OptArg(int);
7329: +void OptErr(int);
7330: +void OptPrint(void);
7331: +
7332: +/******** From the file "parse.h" *****************************************/
7333: +void Parse(struct lemon *lemp);
7334: +
7335: +/********* From the file "plink.h" ***************************************/
7336: +struct plink *Plink_new(void);
7337: +void Plink_add(struct plink **, struct config *);
7338: +void Plink_copy(struct plink **, struct plink *);
7339: +void Plink_delete(struct plink *);
7340: +
7341: +/********** From the file "report.h" *************************************/
7342: +void Reprint(struct lemon *);
7343: +void ReportOutput(struct lemon *);
7344: +void ReportTable(struct lemon *, int);
7345: +void ReportHeader(struct lemon *);
7346: +void CompressTables(struct lemon *);
7347: +void ResortStates(struct lemon *);
7348: +
7349: +/********** From the file "set.h" ****************************************/
7350: +void SetSize(int); /* All sets will be of size N */
7351: +char *SetNew(void); /* A new set for element 0..N */
7352: +void SetFree(char*); /* Deallocate a set */
7353: +int SetAdd(char*,int); /* Add element to a set */
7354: +int SetUnion(char *,char *); /* A <- A U B, thru element N */
7355: +#define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
7356: +
7357: +/********** From the file "struct.h" *************************************/
7358: +/*
7359: +** Principal data structures for the LEMON parser generator.
7360: +*/
7361: +
7362: +typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean;
7363: +
7364: +/* Symbols (terminals and nonterminals) of the grammar are stored
7365: +** in the following: */
7366: +enum symbol_type {
7367: + TERMINAL,
7368: + NONTERMINAL,
7369: + MULTITERMINAL
7370: +};
7371: +enum e_assoc {
7372: + LEFT,
7373: + RIGHT,
7374: + NONE,
7375: + UNK
7376: +};
7377: +struct symbol {
7378: + const char *name; /* Name of the symbol */
7379: + int index; /* Index number for this symbol */
7380: + enum symbol_type type; /* Symbols are all either TERMINALS or NTs */
7381: + struct rule *rule; /* Linked list of rules of this (if an NT) */
7382: + struct symbol *fallback; /* fallback token in case this token doesn't parse */
7383: + int prec; /* Precedence if defined (-1 otherwise) */
7384: + enum e_assoc assoc; /* Associativity if precedence is defined */
7385: + char *firstset; /* First-set for all rules of this symbol */
7386: + Boolean lambda; /* True if NT and can generate an empty string */
7387: + int useCnt; /* Number of times used */
7388: + char *destructor; /* Code which executes whenever this symbol is
7389: + ** popped from the stack during error processing */
7390: + int destLineno; /* Line number for start of destructor. Set to
7391: + ** -1 for duplicate destructors. */
7392: + char *datatype; /* The data type of information held by this
7393: + ** object. Only used if type==NONTERMINAL */
7394: + int dtnum; /* The data type number. In the parser, the value
7395: + ** stack is a union. The .yy%d element of this
7396: + ** union is the correct data type for this object */
7397: + /* The following fields are used by MULTITERMINALs only */
7398: + int nsubsym; /* Number of constituent symbols in the MULTI */
7399: + struct symbol **subsym; /* Array of constituent symbols */
7400: +};
7401: +
7402: +/* Each production rule in the grammar is stored in the following
7403: +** structure. */
7404: +struct rule {
7405: + struct symbol *lhs; /* Left-hand side of the rule */
7406: + const char *lhsalias; /* Alias for the LHS (NULL if none) */
7407: + int lhsStart; /* True if left-hand side is the start symbol */
7408: + int ruleline; /* Line number for the rule */
7409: + int nrhs; /* Number of RHS symbols */
7410: + struct symbol **rhs; /* The RHS symbols */
7411: + const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
7412: + int line; /* Line number at which code begins */
7413: + const char *code; /* The code executed when this rule is reduced */
7414: + const char *codePrefix; /* Setup code before code[] above */
7415: + const char *codeSuffix; /* Breakdown code after code[] above */
7416: + int noCode; /* True if this rule has no associated C code */
7417: + int codeEmitted; /* True if the code has been emitted already */
7418: + struct symbol *precsym; /* Precedence symbol for this rule */
7419: + int index; /* An index number for this rule */
7420: + int iRule; /* Rule number as used in the generated tables */
7421: + Boolean canReduce; /* True if this rule is ever reduced */
7422: + Boolean doesReduce; /* Reduce actions occur after optimization */
7423: + struct rule *nextlhs; /* Next rule with the same LHS */
7424: + struct rule *next; /* Next rule in the global list */
7425: +};
7426: +
7427: +/* A configuration is a production rule of the grammar together with
7428: +** a mark (dot) showing how much of that rule has been processed so far.
7429: +** Configurations also contain a follow-set which is a list of terminal
7430: +** symbols which are allowed to immediately follow the end of the rule.
7431: +** Every configuration is recorded as an instance of the following: */
7432: +enum cfgstatus {
7433: + COMPLETE,
7434: + INCOMPLETE
7435: +};
7436: +struct config {
7437: + struct rule *rp; /* The rule upon which the configuration is based */
7438: + int dot; /* The parse point */
7439: + char *fws; /* Follow-set for this configuration only */
7440: + struct plink *fplp; /* Follow-set forward propagation links */
7441: + struct plink *bplp; /* Follow-set backwards propagation links */
7442: + struct state *stp; /* Pointer to state which contains this */
7443: + enum cfgstatus status; /* used during followset and shift computations */
7444: + struct config *next; /* Next configuration in the state */
7445: + struct config *bp; /* The next basis configuration */
7446: +};
7447: +
7448: +enum e_action {
7449: + SHIFT,
7450: + ACCEPT,
7451: + REDUCE,
7452: + ERROR,
7453: + SSCONFLICT, /* A shift/shift conflict */
7454: + SRCONFLICT, /* Was a reduce, but part of a conflict */
7455: + RRCONFLICT, /* Was a reduce, but part of a conflict */
7456: + SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
7457: + RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
7458: + NOT_USED, /* Deleted by compression */
7459: + SHIFTREDUCE /* Shift first, then reduce */
7460: +};
7461: +
7462: +/* Every shift or reduce operation is stored as one of the following */
7463: +struct action {
7464: + struct symbol *sp; /* The look-ahead symbol */
7465: + enum e_action type;
7466: + union {
7467: + struct state *stp; /* The new state, if a shift */
7468: + struct rule *rp; /* The rule, if a reduce */
7469: + } x;
7470: + struct symbol *spOpt; /* SHIFTREDUCE optimization to this symbol */
7471: + struct action *next; /* Next action for this state */
7472: + struct action *collide; /* Next action with the same hash */
7473: +};
7474: +
7475: +/* Each state of the generated parser's finite state machine
7476: +** is encoded as an instance of the following structure. */
7477: +struct state {
7478: + struct config *bp; /* The basis configurations for this state */
7479: + struct config *cfp; /* All configurations in this set */
7480: + int statenum; /* Sequential number for this state */
7481: + struct action *ap; /* List of actions for this state */
7482: + int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
7483: + int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
7484: + int iDfltReduce; /* Default action is to REDUCE by this rule */
7485: + struct rule *pDfltReduce;/* The default REDUCE rule. */
7486: + int autoReduce; /* True if this is an auto-reduce state */
7487: +};
7488: +#define NO_OFFSET (-2147483647)
7489: +
7490: +/* A followset propagation link indicates that the contents of one
7491: +** configuration followset should be propagated to another whenever
7492: +** the first changes. */
7493: +struct plink {
7494: + struct config *cfp; /* The configuration to which linked */
7495: + struct plink *next; /* The next propagate link */
7496: +};
7497: +
7498: +/* The state vector for the entire parser generator is recorded as
7499: +** follows. (LEMON uses no global variables and makes little use of
7500: +** static variables. Fields in the following structure can be thought
7501: +** of as begin global variables in the program.) */
7502: +struct lemon {
7503: + struct state **sorted; /* Table of states sorted by state number */
7504: + struct rule *rule; /* List of all rules */
7505: + struct rule *startRule; /* First rule */
7506: + int nstate; /* Number of states */
7507: + int nxstate; /* nstate with tail degenerate states removed */
7508: + int nrule; /* Number of rules */
7509: + int nsymbol; /* Number of terminal and nonterminal symbols */
7510: + int nterminal; /* Number of terminal symbols */
7511: + struct symbol **symbols; /* Sorted array of pointers to symbols */
7512: + int errorcnt; /* Number of errors */
7513: + struct symbol *errsym; /* The error symbol */
7514: + struct symbol *wildcard; /* Token that matches anything */
7515: + char *name; /* Name of the generated parser */
7516: + char *arg; /* Declaration of the 3th argument to parser */
7517: + char *tokentype; /* Type of terminal symbols in the parser stack */
7518: + char *vartype; /* The default type of non-terminal symbols */
7519: + char *start; /* Name of the start symbol for the grammar */
7520: + char *stacksize; /* Size of the parser stack */
7521: + char *include; /* Code to put at the start of the C file */
7522: + char *error; /* Code to execute when an error is seen */
7523: + char *overflow; /* Code to execute on a stack overflow */
7524: + char *failure; /* Code to execute on parser failure */
7525: + char *accept; /* Code to execute when the parser excepts */
7526: + char *extracode; /* Code appended to the generated file */
7527: + char *tokendest; /* Code to execute to destroy token data */
7528: + char *vardest; /* Code for the default non-terminal destructor */
7529: + char *filename; /* Name of the input file */
7530: + char *outname; /* Name of the current output file */
7531: + char *tokenprefix; /* A prefix added to token names in the .h file */
7532: + int nconflict; /* Number of parsing conflicts */
7533: + int nactiontab; /* Number of entries in the yy_action[] table */
7534: + int tablesize; /* Total table size of all tables in bytes */
7535: + int basisflag; /* Print only basis configurations */
7536: + int has_fallback; /* True if any %fallback is seen in the grammar */
7537: + int nolinenosflag; /* True if #line statements should not be printed */
7538: + char *argv0; /* Name of the program */
7539: +};
7540: +
7541: +#define MemoryCheck(X) if((X)==0){ \
7542: + extern void memory_error(); \
7543: + memory_error(); \
7544: +}
7545: +
7546: +/**************** From the file "table.h" *********************************/
7547: +/*
7548: +** All code in this file has been automatically generated
7549: +** from a specification in the file
7550: +** "table.q"
7551: +** by the associative array code building program "aagen".
7552: +** Do not edit this file! Instead, edit the specification
7553: +** file, then rerun aagen.
7554: +*/
7555: +/*
7556: +** Code for processing tables in the LEMON parser generator.
7557: +*/
7558: +/* Routines for handling a strings */
7559: +
7560: +const char *Strsafe(const char *);
7561: +
7562: +void Strsafe_init(void);
7563: +int Strsafe_insert(const char *);
7564: +const char *Strsafe_find(const char *);
7565: +
7566: +/* Routines for handling symbols of the grammar */
7567: +
7568: +struct symbol *Symbol_new(const char *);
7569: +int Symbolcmpp(const void *, const void *);
7570: +void Symbol_init(void);
7571: +int Symbol_insert(struct symbol *, const char *);
7572: +struct symbol *Symbol_find(const char *);
7573: +struct symbol *Symbol_Nth(int);
7574: +int Symbol_count(void);
7575: +struct symbol **Symbol_arrayof(void);
7576: +
7577: +/* Routines to manage the state table */
7578: +
7579: +int Configcmp(const char *, const char *);
7580: +struct state *State_new(void);
7581: +void State_init(void);
7582: +int State_insert(struct state *, struct config *);
7583: +struct state *State_find(struct config *);
7584: +struct state **State_arrayof(/* */);
7585: +
7586: +/* Routines used for efficiency in Configlist_add */
7587: +
7588: +void Configtable_init(void);
7589: +int Configtable_insert(struct config *);
7590: +struct config *Configtable_find(struct config *);
7591: +void Configtable_clear(int(*)(struct config *));
7592: +
7593: +/****************** From the file "action.c" *******************************/
7594: +/*
7595: +** Routines processing parser actions in the LEMON parser generator.
7596: +*/
7597: +
7598: +/* Allocate a new parser action */
7599: +static struct action *Action_new(void){
7600: + static struct action *freelist = 0;
7601: + struct action *newaction;
7602: +
7603: + if( freelist==0 ){
7604: + int i;
7605: + int amt = 100;
7606: + freelist = (struct action *)calloc(amt, sizeof(struct action));
7607: + if( freelist==0 ){
7608: + fprintf(stderr,"Unable to allocate memory for a new parser action.");
7609: + exit(1);
7610: + }
7611: + for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
7612: + freelist[amt-1].next = 0;
7613: + }
7614: + newaction = freelist;
7615: + freelist = freelist->next;
7616: + return newaction;
7617: +}
7618: +
7619: +/* Compare two actions for sorting purposes. Return negative, zero, or
7620: +** positive if the first action is less than, equal to, or greater than
7621: +** the first
7622: +*/
7623: +static int actioncmp(
7624: + struct action *ap1,
7625: + struct action *ap2
7626: +){
7627: + int rc;
7628: + rc = ap1->sp->index - ap2->sp->index;
7629: + if( rc==0 ){
7630: + rc = (int)ap1->type - (int)ap2->type;
7631: + }
7632: + if( rc==0 && (ap1->type==REDUCE || ap1->type==SHIFTREDUCE) ){
7633: + rc = ap1->x.rp->index - ap2->x.rp->index;
7634: + }
7635: + if( rc==0 ){
7636: + rc = (int) (ap2 - ap1);
7637: + }
7638: + return rc;
7639: +}
7640: +
7641: +/* Sort parser actions */
7642: +static struct action *Action_sort(
7643: + struct action *ap
7644: +){
7645: + ap = (struct action *)msort((char *)ap,(char **)&ap->next,
7646: + (int(*)(const char*,const char*))actioncmp);
7647: + return ap;
7648: +}
7649: +
7650: +void Action_add(
7651: + struct action **app,
7652: + enum e_action type,
7653: + struct symbol *sp,
7654: + char *arg
7655: +){
7656: + struct action *newaction;
7657: + newaction = Action_new();
7658: + newaction->next = *app;
7659: + *app = newaction;
7660: + newaction->type = type;
7661: + newaction->sp = sp;
7662: + newaction->spOpt = 0;
7663: + if( type==SHIFT ){
7664: + newaction->x.stp = (struct state *)arg;
7665: + }else{
7666: + newaction->x.rp = (struct rule *)arg;
7667: + }
7668: +}
7669: +/********************** New code to implement the "acttab" module ***********/
7670: +/*
7671: +** This module implements routines use to construct the yy_action[] table.
7672: +*/
7673: +
7674: +/*
7675: +** The state of the yy_action table under construction is an instance of
7676: +** the following structure.
7677: +**
7678: +** The yy_action table maps the pair (state_number, lookahead) into an
7679: +** action_number. The table is an array of integers pairs. The state_number
7680: +** determines an initial offset into the yy_action array. The lookahead
7681: +** value is then added to this initial offset to get an index X into the
7682: +** yy_action array. If the aAction[X].lookahead equals the value of the
7683: +** of the lookahead input, then the value of the action_number output is
7684: +** aAction[X].action. If the lookaheads do not match then the
7685: +** default action for the state_number is returned.
7686: +**
7687: +** All actions associated with a single state_number are first entered
7688: +** into aLookahead[] using multiple calls to acttab_action(). Then the
7689: +** actions for that single state_number are placed into the aAction[]
7690: +** array with a single call to acttab_insert(). The acttab_insert() call
7691: +** also resets the aLookahead[] array in preparation for the next
7692: +** state number.
7693: +*/
7694: +struct lookahead_action {
7695: + int lookahead; /* Value of the lookahead token */
7696: + int action; /* Action to take on the given lookahead */
7697: +};
7698: +typedef struct acttab acttab;
7699: +struct acttab {
7700: + int nAction; /* Number of used slots in aAction[] */
7701: + int nActionAlloc; /* Slots allocated for aAction[] */
7702: + struct lookahead_action
7703: + *aAction, /* The yy_action[] table under construction */
7704: + *aLookahead; /* A single new transaction set */
7705: + int mnLookahead; /* Minimum aLookahead[].lookahead */
7706: + int mnAction; /* Action associated with mnLookahead */
7707: + int mxLookahead; /* Maximum aLookahead[].lookahead */
7708: + int nLookahead; /* Used slots in aLookahead[] */
7709: + int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
7710: +};
7711: +
7712: +/* Return the number of entries in the yy_action table */
7713: +#define acttab_size(X) ((X)->nAction)
7714: +
7715: +/* The value for the N-th entry in yy_action */
7716: +#define acttab_yyaction(X,N) ((X)->aAction[N].action)
7717: +
7718: +/* The value for the N-th entry in yy_lookahead */
7719: +#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
7720: +
7721: +/* Free all memory associated with the given acttab */
7722: +void acttab_free(acttab *p){
7723: + free( p->aAction );
7724: + free( p->aLookahead );
7725: + free( p );
7726: +}
7727: +
7728: +/* Allocate a new acttab structure */
7729: +acttab *acttab_alloc(void){
7730: + acttab *p = (acttab *) calloc( 1, sizeof(*p) );
7731: + if( p==0 ){
7732: + fprintf(stderr,"Unable to allocate memory for a new acttab.");
7733: + exit(1);
7734: + }
7735: + memset(p, 0, sizeof(*p));
7736: + return p;
7737: +}
7738: +
7739: +/* Add a new action to the current transaction set.
7740: +**
7741: +** This routine is called once for each lookahead for a particular
7742: +** state.
7743: +*/
7744: +void acttab_action(acttab *p, int lookahead, int action){
7745: + if( p->nLookahead>=p->nLookaheadAlloc ){
7746: + p->nLookaheadAlloc += 25;
7747: + p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
7748: + sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
7749: + if( p->aLookahead==0 ){
7750: + fprintf(stderr,"malloc failed\n");
7751: + exit(1);
7752: + }
7753: + }
7754: + if( p->nLookahead==0 ){
7755: + p->mxLookahead = lookahead;
7756: + p->mnLookahead = lookahead;
7757: + p->mnAction = action;
7758: + }else{
7759: + if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
7760: + if( p->mnLookahead>lookahead ){
7761: + p->mnLookahead = lookahead;
7762: + p->mnAction = action;
7763: + }
7764: + }
7765: + p->aLookahead[p->nLookahead].lookahead = lookahead;
7766: + p->aLookahead[p->nLookahead].action = action;
7767: + p->nLookahead++;
7768: +}
7769: +
7770: +/*
7771: +** Add the transaction set built up with prior calls to acttab_action()
7772: +** into the current action table. Then reset the transaction set back
7773: +** to an empty set in preparation for a new round of acttab_action() calls.
7774: +**
7775: +** Return the offset into the action table of the new transaction.
7776: +*/
7777: +int acttab_insert(acttab *p){
7778: + int i, j, k, n;
7779: + assert( p->nLookahead>0 );
7780: +
7781: + /* Make sure we have enough space to hold the expanded action table
7782: + ** in the worst case. The worst case occurs if the transaction set
7783: + ** must be appended to the current action table
7784: + */
7785: + n = p->mxLookahead + 1;
7786: + if( p->nAction + n >= p->nActionAlloc ){
7787: + int oldAlloc = p->nActionAlloc;
7788: + p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
7789: + p->aAction = (struct lookahead_action *) realloc( p->aAction,
7790: + sizeof(p->aAction[0])*p->nActionAlloc);
7791: + if( p->aAction==0 ){
7792: + fprintf(stderr,"malloc failed\n");
7793: + exit(1);
7794: + }
7795: + for(i=oldAlloc; i<p->nActionAlloc; i++){
7796: + p->aAction[i].lookahead = -1;
7797: + p->aAction[i].action = -1;
7798: + }
7799: + }
7800: +
7801: + /* Scan the existing action table looking for an offset that is a
7802: + ** duplicate of the current transaction set. Fall out of the loop
7803: + ** if and when the duplicate is found.
7804: + **
7805: + ** i is the index in p->aAction[] where p->mnLookahead is inserted.
7806: + */
7807: + for(i=p->nAction-1; i>=0; i--){
7808: + if( p->aAction[i].lookahead==p->mnLookahead ){
7809: + /* All lookaheads and actions in the aLookahead[] transaction
7810: + ** must match against the candidate aAction[i] entry. */
7811: + if( p->aAction[i].action!=p->mnAction ) continue;
7812: + for(j=0; j<p->nLookahead; j++){
7813: + k = p->aLookahead[j].lookahead - p->mnLookahead + i;
7814: + if( k<0 || k>=p->nAction ) break;
7815: + if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
7816: + if( p->aLookahead[j].action!=p->aAction[k].action ) break;
7817: + }
7818: + if( j<p->nLookahead ) continue;
7819: +
7820: + /* No possible lookahead value that is not in the aLookahead[]
7821: + ** transaction is allowed to match aAction[i] */
7822: + n = 0;
7823: + for(j=0; j<p->nAction; j++){
7824: + if( p->aAction[j].lookahead<0 ) continue;
7825: + if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
7826: + }
7827: + if( n==p->nLookahead ){
7828: + break; /* An exact match is found at offset i */
7829: + }
7830: + }
7831: + }
7832: +
7833: + /* If no existing offsets exactly match the current transaction, find an
7834: + ** an empty offset in the aAction[] table in which we can add the
7835: + ** aLookahead[] transaction.
7836: + */
7837: + if( i<0 ){
7838: + /* Look for holes in the aAction[] table that fit the current
7839: + ** aLookahead[] transaction. Leave i set to the offset of the hole.
7840: + ** If no holes are found, i is left at p->nAction, which means the
7841: + ** transaction will be appended. */
7842: + for(i=0; i<p->nActionAlloc - p->mxLookahead; i++){
7843: + if( p->aAction[i].lookahead<0 ){
7844: + for(j=0; j<p->nLookahead; j++){
7845: + k = p->aLookahead[j].lookahead - p->mnLookahead + i;
7846: + if( k<0 ) break;
7847: + if( p->aAction[k].lookahead>=0 ) break;
7848: + }
7849: + if( j<p->nLookahead ) continue;
7850: + for(j=0; j<p->nAction; j++){
7851: + if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
7852: + }
7853: + if( j==p->nAction ){
7854: + break; /* Fits in empty slots */
7855: + }
7856: + }
7857: + }
7858: + }
7859: + /* Insert transaction set at index i. */
7860: + for(j=0; j<p->nLookahead; j++){
7861: + k = p->aLookahead[j].lookahead - p->mnLookahead + i;
7862: + p->aAction[k] = p->aLookahead[j];
7863: + if( k>=p->nAction ) p->nAction = k+1;
7864: + }
7865: + p->nLookahead = 0;
7866: +
7867: + /* Return the offset that is added to the lookahead in order to get the
7868: + ** index into yy_action of the action */
7869: + return i - p->mnLookahead;
7870: +}
7871: +
7872: +/********************** From the file "build.c" *****************************/
7873: +/*
7874: +** Routines to construction the finite state machine for the LEMON
7875: +** parser generator.
7876: +*/
7877: +
7878: +/* Find a precedence symbol of every rule in the grammar.
7879: +**
7880: +** Those rules which have a precedence symbol coded in the input
7881: +** grammar using the "[symbol]" construct will already have the
7882: +** rp->precsym field filled. Other rules take as their precedence
7883: +** symbol the first RHS symbol with a defined precedence. If there
7884: +** are not RHS symbols with a defined precedence, the precedence
7885: +** symbol field is left blank.
7886: +*/
7887: +void FindRulePrecedences(struct lemon *xp)
7888: +{
7889: + struct rule *rp;
7890: + for(rp=xp->rule; rp; rp=rp->next){
7891: + if( rp->precsym==0 ){
7892: + int i, j;
7893: + for(i=0; i<rp->nrhs && rp->precsym==0; i++){
7894: + struct symbol *sp = rp->rhs[i];
7895: + if( sp->type==MULTITERMINAL ){
7896: + for(j=0; j<sp->nsubsym; j++){
7897: + if( sp->subsym[j]->prec>=0 ){
7898: + rp->precsym = sp->subsym[j];
7899: + break;
7900: + }
7901: + }
7902: + }else if( sp->prec>=0 ){
7903: + rp->precsym = rp->rhs[i];
7904: + }
7905: + }
7906: + }
7907: + }
7908: + return;
7909: +}
7910: +
7911: +/* Find all nonterminals which will generate the empty string.
7912: +** Then go back and compute the first sets of every nonterminal.
7913: +** The first set is the set of all terminal symbols which can begin
7914: +** a string generated by that nonterminal.
7915: +*/
7916: +void FindFirstSets(struct lemon *lemp)
7917: +{
7918: + int i, j;
7919: + struct rule *rp;
7920: + int progress;
7921: +
7922: + for(i=0; i<lemp->nsymbol; i++){
7923: + lemp->symbols[i]->lambda = LEMON_FALSE;
7924: + }
7925: + for(i=lemp->nterminal; i<lemp->nsymbol; i++){
7926: + lemp->symbols[i]->firstset = SetNew();
7927: + }
7928: +
7929: + /* First compute all lambdas */
7930: + do{
7931: + progress = 0;
7932: + for(rp=lemp->rule; rp; rp=rp->next){
7933: + if( rp->lhs->lambda ) continue;
7934: + for(i=0; i<rp->nrhs; i++){
7935: + struct symbol *sp = rp->rhs[i];
7936: + assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE );
7937: + if( sp->lambda==LEMON_FALSE ) break;
7938: + }
7939: + if( i==rp->nrhs ){
7940: + rp->lhs->lambda = LEMON_TRUE;
7941: + progress = 1;
7942: + }
7943: + }
7944: + }while( progress );
7945: +
7946: + /* Now compute all first sets */
7947: + do{
7948: + struct symbol *s1, *s2;
7949: + progress = 0;
7950: + for(rp=lemp->rule; rp; rp=rp->next){
7951: + s1 = rp->lhs;
7952: + for(i=0; i<rp->nrhs; i++){
7953: + s2 = rp->rhs[i];
7954: + if( s2->type==TERMINAL ){
7955: + progress += SetAdd(s1->firstset,s2->index);
7956: + break;
7957: + }else if( s2->type==MULTITERMINAL ){
7958: + for(j=0; j<s2->nsubsym; j++){
7959: + progress += SetAdd(s1->firstset,s2->subsym[j]->index);
7960: + }
7961: + break;
7962: + }else if( s1==s2 ){
7963: + if( s1->lambda==LEMON_FALSE ) break;
7964: + }else{
7965: + progress += SetUnion(s1->firstset,s2->firstset);
7966: + if( s2->lambda==LEMON_FALSE ) break;
7967: + }
7968: + }
7969: + }
7970: + }while( progress );
7971: + return;
7972: +}
7973: +
7974: +/* Compute all LR(0) states for the grammar. Links
7975: +** are added to between some states so that the LR(1) follow sets
7976: +** can be computed later.
7977: +*/
7978: +PRIVATE struct state *getstate(struct lemon *); /* forward reference */
7979: +void FindStates(struct lemon *lemp)
7980: +{
7981: + struct symbol *sp;
7982: + struct rule *rp;
7983: +
7984: + Configlist_init();
7985: +
7986: + /* Find the start symbol */
7987: + if( lemp->start ){
7988: + sp = Symbol_find(lemp->start);
7989: + if( sp==0 ){
7990: + ErrorMsg(lemp->filename,0,
7991: +"The specified start symbol \"%s\" is not \
7992: +in a nonterminal of the grammar. \"%s\" will be used as the start \
7993: +symbol instead.",lemp->start,lemp->startRule->lhs->name);
7994: + lemp->errorcnt++;
7995: + sp = lemp->startRule->lhs;
7996: + }
7997: + }else{
7998: + sp = lemp->startRule->lhs;
7999: + }
8000: +
8001: + /* Make sure the start symbol doesn't occur on the right-hand side of
8002: + ** any rule. Report an error if it does. (YACC would generate a new
8003: + ** start symbol in this case.) */
8004: + for(rp=lemp->rule; rp; rp=rp->next){
8005: + int i;
8006: + for(i=0; i<rp->nrhs; i++){
8007: + if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */
8008: + ErrorMsg(lemp->filename,0,
8009: +"The start symbol \"%s\" occurs on the \
8010: +right-hand side of a rule. This will result in a parser which \
8011: +does not work properly.",sp->name);
8012: + lemp->errorcnt++;
8013: + }
8014: + }
8015: + }
8016: +
8017: + /* The basis configuration set for the first state
8018: + ** is all rules which have the start symbol as their
8019: + ** left-hand side */
8020: + for(rp=sp->rule; rp; rp=rp->nextlhs){
8021: + struct config *newcfp;
8022: + rp->lhsStart = 1;
8023: + newcfp = Configlist_addbasis(rp,0);
8024: + SetAdd(newcfp->fws,0);
8025: + }
8026: +
8027: + /* Compute the first state. All other states will be
8028: + ** computed automatically during the computation of the first one.
8029: + ** The returned pointer to the first state is not used. */
8030: + (void)getstate(lemp);
8031: + return;
8032: +}
8033: +
8034: +/* Return a pointer to a state which is described by the configuration
8035: +** list which has been built from calls to Configlist_add.
8036: +*/
8037: +PRIVATE void buildshifts(struct lemon *, struct state *); /* Forwd ref */
8038: +PRIVATE struct state *getstate(struct lemon *lemp)
8039: +{
8040: + struct config *cfp, *bp;
8041: + struct state *stp;
8042: +
8043: + /* Extract the sorted basis of the new state. The basis was constructed
8044: + ** by prior calls to "Configlist_addbasis()". */
8045: + Configlist_sortbasis();
8046: + bp = Configlist_basis();
8047: +
8048: + /* Get a state with the same basis */
8049: + stp = State_find(bp);
8050: + if( stp ){
8051: + /* A state with the same basis already exists! Copy all the follow-set
8052: + ** propagation links from the state under construction into the
8053: + ** preexisting state, then return a pointer to the preexisting state */
8054: + struct config *x, *y;
8055: + for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
8056: + Plink_copy(&y->bplp,x->bplp);
8057: + Plink_delete(x->fplp);
8058: + x->fplp = x->bplp = 0;
8059: + }
8060: + cfp = Configlist_return();
8061: + Configlist_eat(cfp);
8062: + }else{
8063: + /* This really is a new state. Construct all the details */
8064: + Configlist_closure(lemp); /* Compute the configuration closure */
8065: + Configlist_sort(); /* Sort the configuration closure */
8066: + cfp = Configlist_return(); /* Get a pointer to the config list */
8067: + stp = State_new(); /* A new state structure */
8068: + MemoryCheck(stp);
8069: + stp->bp = bp; /* Remember the configuration basis */
8070: + stp->cfp = cfp; /* Remember the configuration closure */
8071: + stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
8072: + stp->ap = 0; /* No actions, yet. */
8073: + State_insert(stp,stp->bp); /* Add to the state table */
8074: + buildshifts(lemp,stp); /* Recursively compute successor states */
8075: + }
8076: + return stp;
8077: +}
8078: +
8079: +/*
8080: +** Return true if two symbols are the same.
8081: +*/
8082: +int same_symbol(struct symbol *a, struct symbol *b)
8083: +{
8084: + int i;
8085: + if( a==b ) return 1;
8086: + if( a->type!=MULTITERMINAL ) return 0;
8087: + if( b->type!=MULTITERMINAL ) return 0;
8088: + if( a->nsubsym!=b->nsubsym ) return 0;
8089: + for(i=0; i<a->nsubsym; i++){
8090: + if( a->subsym[i]!=b->subsym[i] ) return 0;
8091: + }
8092: + return 1;
8093: +}
8094: +
8095: +/* Construct all successor states to the given state. A "successor"
8096: +** state is any state which can be reached by a shift action.
8097: +*/
8098: +PRIVATE void buildshifts(struct lemon *lemp, struct state *stp)
8099: +{
8100: + struct config *cfp; /* For looping thru the config closure of "stp" */
8101: + struct config *bcfp; /* For the inner loop on config closure of "stp" */
8102: + struct config *newcfg; /* */
8103: + struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
8104: + struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
8105: + struct state *newstp; /* A pointer to a successor state */
8106: +
8107: + /* Each configuration becomes complete after it contibutes to a successor
8108: + ** state. Initially, all configurations are incomplete */
8109: + for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
8110: +
8111: + /* Loop through all configurations of the state "stp" */
8112: + for(cfp=stp->cfp; cfp; cfp=cfp->next){
8113: + if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */
8114: + if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */
8115: + Configlist_reset(); /* Reset the new config set */
8116: + sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */
8117: +
8118: + /* For every configuration in the state "stp" which has the symbol "sp"
8119: + ** following its dot, add the same configuration to the basis set under
8120: + ** construction but with the dot shifted one symbol to the right. */
8121: + for(bcfp=cfp; bcfp; bcfp=bcfp->next){
8122: + if( bcfp->status==COMPLETE ) continue; /* Already used */
8123: + if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
8124: + bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
8125: + if( !same_symbol(bsp,sp) ) continue; /* Must be same as for "cfp" */
8126: + bcfp->status = COMPLETE; /* Mark this config as used */
8127: + newcfg = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
8128: + Plink_add(&newcfg->bplp,bcfp);
8129: + }
8130: +
8131: + /* Get a pointer to the state described by the basis configuration set
8132: + ** constructed in the preceding loop */
8133: + newstp = getstate(lemp);
8134: +
8135: + /* The state "newstp" is reached from the state "stp" by a shift action
8136: + ** on the symbol "sp" */
8137: + if( sp->type==MULTITERMINAL ){
8138: + int i;
8139: + for(i=0; i<sp->nsubsym; i++){
8140: + Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp);
8141: + }
8142: + }else{
8143: + Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
8144: + }
8145: + }
8146: +}
8147: +
8148: +/*
8149: +** Construct the propagation links
8150: +*/
8151: +void FindLinks(struct lemon *lemp)
8152: +{
8153: + int i;
8154: + struct config *cfp, *other;
8155: + struct state *stp;
8156: + struct plink *plp;
8157: +
8158: + /* Housekeeping detail:
8159: + ** Add to every propagate link a pointer back to the state to
8160: + ** which the link is attached. */
8161: + for(i=0; i<lemp->nstate; i++){
8162: + stp = lemp->sorted[i];
8163: + for(cfp=stp->cfp; cfp; cfp=cfp->next){
8164: + cfp->stp = stp;
8165: + }
8166: + }
8167: +
8168: + /* Convert all backlinks into forward links. Only the forward
8169: + ** links are used in the follow-set computation. */
8170: + for(i=0; i<lemp->nstate; i++){
8171: + stp = lemp->sorted[i];
8172: + for(cfp=stp->cfp; cfp; cfp=cfp->next){
8173: + for(plp=cfp->bplp; plp; plp=plp->next){
8174: + other = plp->cfp;
8175: + Plink_add(&other->fplp,cfp);
8176: + }
8177: + }
8178: + }
8179: +}
8180: +
8181: +/* Compute all followsets.
8182: +**
8183: +** A followset is the set of all symbols which can come immediately
8184: +** after a configuration.
8185: +*/
8186: +void FindFollowSets(struct lemon *lemp)
8187: +{
8188: + int i;
8189: + struct config *cfp;
8190: + struct plink *plp;
8191: + int progress;
8192: + int change;
8193: +
8194: + for(i=0; i<lemp->nstate; i++){
8195: + for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
8196: + cfp->status = INCOMPLETE;
8197: + }
8198: + }
8199: +
8200: + do{
8201: + progress = 0;
8202: + for(i=0; i<lemp->nstate; i++){
8203: + for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
8204: + if( cfp->status==COMPLETE ) continue;
8205: + for(plp=cfp->fplp; plp; plp=plp->next){
8206: + change = SetUnion(plp->cfp->fws,cfp->fws);
8207: + if( change ){
8208: + plp->cfp->status = INCOMPLETE;
8209: + progress = 1;
8210: + }
8211: + }
8212: + cfp->status = COMPLETE;
8213: + }
8214: + }
8215: + }while( progress );
8216: +}
8217: +
8218: +static int resolve_conflict(struct action *,struct action *);
8219: +
8220: +/* Compute the reduce actions, and resolve conflicts.
8221: +*/
8222: +void FindActions(struct lemon *lemp)
8223: +{
8224: + int i,j;
8225: + struct config *cfp;
8226: + struct state *stp;
8227: + struct symbol *sp;
8228: + struct rule *rp;
8229: +
8230: + /* Add all of the reduce actions
8231: + ** A reduce action is added for each element of the followset of
8232: + ** a configuration which has its dot at the extreme right.
8233: + */
8234: + for(i=0; i<lemp->nstate; i++){ /* Loop over all states */
8235: + stp = lemp->sorted[i];
8236: + for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
8237: + if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
8238: + for(j=0; j<lemp->nterminal; j++){
8239: + if( SetFind(cfp->fws,j) ){
8240: + /* Add a reduce action to the state "stp" which will reduce by the
8241: + ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
8242: + Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
8243: + }
8244: + }
8245: + }
8246: + }
8247: + }
8248: +
8249: + /* Add the accepting token */
8250: + if( lemp->start ){
8251: + sp = Symbol_find(lemp->start);
8252: + if( sp==0 ) sp = lemp->startRule->lhs;
8253: + }else{
8254: + sp = lemp->startRule->lhs;
8255: + }
8256: + /* Add to the first state (which is always the starting state of the
8257: + ** finite state machine) an action to ACCEPT if the lookahead is the
8258: + ** start nonterminal. */
8259: + Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
8260: +
8261: + /* Resolve conflicts */
8262: + for(i=0; i<lemp->nstate; i++){
8263: + struct action *ap, *nap;
8264: + stp = lemp->sorted[i];
8265: + /* assert( stp->ap ); */
8266: + stp->ap = Action_sort(stp->ap);
8267: + for(ap=stp->ap; ap && ap->next; ap=ap->next){
8268: + for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
8269: + /* The two actions "ap" and "nap" have the same lookahead.
8270: + ** Figure out which one should be used */
8271: + lemp->nconflict += resolve_conflict(ap,nap);
8272: + }
8273: + }
8274: + }
8275: +
8276: + /* Report an error for each rule that can never be reduced. */
8277: + for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE;
8278: + for(i=0; i<lemp->nstate; i++){
8279: + struct action *ap;
8280: + for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
8281: + if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE;
8282: + }
8283: + }
8284: + for(rp=lemp->rule; rp; rp=rp->next){
8285: + if( rp->canReduce ) continue;
8286: + ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
8287: + lemp->errorcnt++;
8288: + }
8289: +}
8290: +
8291: +/* Resolve a conflict between the two given actions. If the
8292: +** conflict can't be resolved, return non-zero.
8293: +**
8294: +** NO LONGER TRUE:
8295: +** To resolve a conflict, first look to see if either action
8296: +** is on an error rule. In that case, take the action which
8297: +** is not associated with the error rule. If neither or both
8298: +** actions are associated with an error rule, then try to
8299: +** use precedence to resolve the conflict.
8300: +**
8301: +** If either action is a SHIFT, then it must be apx. This
8302: +** function won't work if apx->type==REDUCE and apy->type==SHIFT.
8303: +*/
8304: +static int resolve_conflict(
8305: + struct action *apx,
8306: + struct action *apy
8307: +){
8308: + struct symbol *spx, *spy;
8309: + int errcnt = 0;
8310: + assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
8311: + if( apx->type==SHIFT && apy->type==SHIFT ){
8312: + apy->type = SSCONFLICT;
8313: + errcnt++;
8314: + }
8315: + if( apx->type==SHIFT && apy->type==REDUCE ){
8316: + spx = apx->sp;
8317: + spy = apy->x.rp->precsym;
8318: + if( spy==0 || spx->prec<0 || spy->prec<0 ){
8319: + /* Not enough precedence information. */
8320: + apy->type = SRCONFLICT;
8321: + errcnt++;
8322: + }else if( spx->prec>spy->prec ){ /* higher precedence wins */
8323: + apy->type = RD_RESOLVED;
8324: + }else if( spx->prec<spy->prec ){
8325: + apx->type = SH_RESOLVED;
8326: + }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
8327: + apy->type = RD_RESOLVED; /* associativity */
8328: + }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */
8329: + apx->type = SH_RESOLVED;
8330: + }else{
8331: + assert( spx->prec==spy->prec && spx->assoc==NONE );
8332: + apx->type = ERROR;
8333: + }
8334: + }else if( apx->type==REDUCE && apy->type==REDUCE ){
8335: + spx = apx->x.rp->precsym;
8336: + spy = apy->x.rp->precsym;
8337: + if( spx==0 || spy==0 || spx->prec<0 ||
8338: + spy->prec<0 || spx->prec==spy->prec ){
8339: + apy->type = RRCONFLICT;
8340: + errcnt++;
8341: + }else if( spx->prec>spy->prec ){
8342: + apy->type = RD_RESOLVED;
8343: + }else if( spx->prec<spy->prec ){
8344: + apx->type = RD_RESOLVED;
8345: + }
8346: + }else{
8347: + assert(
8348: + apx->type==SH_RESOLVED ||
8349: + apx->type==RD_RESOLVED ||
8350: + apx->type==SSCONFLICT ||
8351: + apx->type==SRCONFLICT ||
8352: + apx->type==RRCONFLICT ||
8353: + apy->type==SH_RESOLVED ||
8354: + apy->type==RD_RESOLVED ||
8355: + apy->type==SSCONFLICT ||
8356: + apy->type==SRCONFLICT ||
8357: + apy->type==RRCONFLICT
8358: + );
8359: + /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
8360: + ** REDUCEs on the list. If we reach this point it must be because
8361: + ** the parser conflict had already been resolved. */
8362: + }
8363: + return errcnt;
8364: +}
8365: +/********************* From the file "configlist.c" *************************/
8366: +/*
8367: +** Routines to processing a configuration list and building a state
8368: +** in the LEMON parser generator.
8369: +*/
8370: +
8371: +static struct config *freelist = 0; /* List of free configurations */
8372: +static struct config *current = 0; /* Top of list of configurations */
8373: +static struct config **currentend = 0; /* Last on list of configs */
8374: +static struct config *basis = 0; /* Top of list of basis configs */
8375: +static struct config **basisend = 0; /* End of list of basis configs */
8376: +
8377: +/* Return a pointer to a new configuration */
8378: +PRIVATE struct config *newconfig(){
8379: + struct config *newcfg;
8380: + if( freelist==0 ){
8381: + int i;
8382: + int amt = 3;
8383: + freelist = (struct config *)calloc( amt, sizeof(struct config) );
8384: + if( freelist==0 ){
8385: + fprintf(stderr,"Unable to allocate memory for a new configuration.");
8386: + exit(1);
8387: + }
8388: + for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
8389: + freelist[amt-1].next = 0;
8390: + }
8391: + newcfg = freelist;
8392: + freelist = freelist->next;
8393: + return newcfg;
8394: +}
8395: +
8396: +/* The configuration "old" is no longer used */
8397: +PRIVATE void deleteconfig(struct config *old)
8398: +{
8399: + old->next = freelist;
8400: + freelist = old;
8401: +}
8402: +
8403: +/* Initialized the configuration list builder */
8404: +void Configlist_init(){
8405: + current = 0;
8406: + currentend = ¤t;
8407: + basis = 0;
8408: + basisend = &basis;
8409: + Configtable_init();
8410: + return;
8411: +}
8412: +
8413: +/* Initialized the configuration list builder */
8414: +void Configlist_reset(){
8415: + current = 0;
8416: + currentend = ¤t;
8417: + basis = 0;
8418: + basisend = &basis;
8419: + Configtable_clear(0);
8420: + return;
8421: +}
8422: +
8423: +/* Add another configuration to the configuration list */
8424: +struct config *Configlist_add(
8425: + struct rule *rp, /* The rule */
8426: + int dot /* Index into the RHS of the rule where the dot goes */
8427: +){
8428: + struct config *cfp, model;
8429: +
8430: + assert( currentend!=0 );
8431: + model.rp = rp;
8432: + model.dot = dot;
8433: + cfp = Configtable_find(&model);
8434: + if( cfp==0 ){
8435: + cfp = newconfig();
8436: + cfp->rp = rp;
8437: + cfp->dot = dot;
8438: + cfp->fws = SetNew();
8439: + cfp->stp = 0;
8440: + cfp->fplp = cfp->bplp = 0;
8441: + cfp->next = 0;
8442: + cfp->bp = 0;
8443: + *currentend = cfp;
8444: + currentend = &cfp->next;
8445: + Configtable_insert(cfp);
8446: + }
8447: + return cfp;
8448: +}
8449: +
8450: +/* Add a basis configuration to the configuration list */
8451: +struct config *Configlist_addbasis(struct rule *rp, int dot)
8452: +{
8453: + struct config *cfp, model;
8454: +
8455: + assert( basisend!=0 );
8456: + assert( currentend!=0 );
8457: + model.rp = rp;
8458: + model.dot = dot;
8459: + cfp = Configtable_find(&model);
8460: + if( cfp==0 ){
8461: + cfp = newconfig();
8462: + cfp->rp = rp;
8463: + cfp->dot = dot;
8464: + cfp->fws = SetNew();
8465: + cfp->stp = 0;
8466: + cfp->fplp = cfp->bplp = 0;
8467: + cfp->next = 0;
8468: + cfp->bp = 0;
8469: + *currentend = cfp;
8470: + currentend = &cfp->next;
8471: + *basisend = cfp;
8472: + basisend = &cfp->bp;
8473: + Configtable_insert(cfp);
8474: + }
8475: + return cfp;
8476: +}
8477: +
8478: +/* Compute the closure of the configuration list */
8479: +void Configlist_closure(struct lemon *lemp)
8480: +{
8481: + struct config *cfp, *newcfp;
8482: + struct rule *rp, *newrp;
8483: + struct symbol *sp, *xsp;
8484: + int i, dot;
8485: +
8486: + assert( currentend!=0 );
8487: + for(cfp=current; cfp; cfp=cfp->next){
8488: + rp = cfp->rp;
8489: + dot = cfp->dot;
8490: + if( dot>=rp->nrhs ) continue;
8491: + sp = rp->rhs[dot];
8492: + if( sp->type==NONTERMINAL ){
8493: + if( sp->rule==0 && sp!=lemp->errsym ){
8494: + ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
8495: + sp->name);
8496: + lemp->errorcnt++;
8497: + }
8498: + for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
8499: + newcfp = Configlist_add(newrp,0);
8500: + for(i=dot+1; i<rp->nrhs; i++){
8501: + xsp = rp->rhs[i];
8502: + if( xsp->type==TERMINAL ){
8503: + SetAdd(newcfp->fws,xsp->index);
8504: + break;
8505: + }else if( xsp->type==MULTITERMINAL ){
8506: + int k;
8507: + for(k=0; k<xsp->nsubsym; k++){
8508: + SetAdd(newcfp->fws, xsp->subsym[k]->index);
8509: + }
8510: + break;
8511: + }else{
8512: + SetUnion(newcfp->fws,xsp->firstset);
8513: + if( xsp->lambda==LEMON_FALSE ) break;
8514: + }
8515: + }
8516: + if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
8517: + }
8518: + }
8519: + }
8520: + return;
8521: +}
8522: +
8523: +/* Sort the configuration list */
8524: +void Configlist_sort(){
8525: + current = (struct config*)msort((char*)current,(char**)&(current->next),
8526: + Configcmp);
8527: + currentend = 0;
8528: + return;
8529: +}
8530: +
8531: +/* Sort the basis configuration list */
8532: +void Configlist_sortbasis(){
8533: + basis = (struct config*)msort((char*)current,(char**)&(current->bp),
8534: + Configcmp);
8535: + basisend = 0;
8536: + return;
8537: +}
8538: +
8539: +/* Return a pointer to the head of the configuration list and
8540: +** reset the list */
8541: +struct config *Configlist_return(){
8542: + struct config *old;
8543: + old = current;
8544: + current = 0;
8545: + currentend = 0;
8546: + return old;
8547: +}
8548: +
8549: +/* Return a pointer to the head of the configuration list and
8550: +** reset the list */
8551: +struct config *Configlist_basis(){
8552: + struct config *old;
8553: + old = basis;
8554: + basis = 0;
8555: + basisend = 0;
8556: + return old;
8557: +}
8558: +
8559: +/* Free all elements of the given configuration list */
8560: +void Configlist_eat(struct config *cfp)
8561: +{
8562: + struct config *nextcfp;
8563: + for(; cfp; cfp=nextcfp){
8564: + nextcfp = cfp->next;
8565: + assert( cfp->fplp==0 );
8566: + assert( cfp->bplp==0 );
8567: + if( cfp->fws ) SetFree(cfp->fws);
8568: + deleteconfig(cfp);
8569: + }
8570: + return;
8571: +}
8572: +/***************** From the file "error.c" *********************************/
8573: +/*
8574: +** Code for printing error message.
8575: +*/
8576: +
8577: +void ErrorMsg(const char *filename, int lineno, const char *format, ...){
8578: + va_list ap;
8579: + fprintf(stderr, "%s:%d: ", filename, lineno);
8580: + va_start(ap, format);
8581: + vfprintf(stderr,format,ap);
8582: + va_end(ap);
8583: + fprintf(stderr, "\n");
8584: +}
8585: +/**************** From the file "main.c" ************************************/
8586: +/*
8587: +** Main program file for the LEMON parser generator.
8588: +*/
8589: +
8590: +/* Report an out-of-memory condition and abort. This function
8591: +** is used mostly by the "MemoryCheck" macro in struct.h
8592: +*/
8593: +void memory_error(){
8594: + fprintf(stderr,"Out of memory. Aborting...\n");
8595: + exit(1);
8596: +}
8597: +
8598: +static int nDefine = 0; /* Number of -D options on the command line */
8599: +static char **azDefine = 0; /* Name of the -D macros */
8600: +
8601: +/* This routine is called with the argument to each -D command-line option.
8602: +** Add the macro defined to the azDefine array.
8603: +*/
8604: +static void handle_D_option(char *z){
8605: + char **paz;
8606: + nDefine++;
8607: + azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine);
8608: + if( azDefine==0 ){
8609: + fprintf(stderr,"out of memory\n");
8610: + exit(1);
8611: + }
8612: + paz = &azDefine[nDefine-1];
8613: + *paz = (char *) malloc( lemonStrlen(z)+1 );
8614: + if( *paz==0 ){
8615: + fprintf(stderr,"out of memory\n");
8616: + exit(1);
8617: + }
8618: + lemon_strcpy(*paz, z);
8619: + for(z=*paz; *z && *z!='='; z++){}
8620: + *z = 0;
8621: +}
8622: +
8623: +static char *user_templatename = NULL;
8624: +static void handle_T_option(char *z){
8625: + user_templatename = (char *) malloc( lemonStrlen(z)+1 );
8626: + if( user_templatename==0 ){
8627: + memory_error();
8628: + }
8629: + lemon_strcpy(user_templatename, z);
8630: +}
8631: +
8632: +/* Merge together to lists of rules ordered by rule.iRule */
8633: +static struct rule *Rule_merge(struct rule *pA, struct rule *pB){
8634: + struct rule *pFirst = 0;
8635: + struct rule **ppPrev = &pFirst;
8636: + while( pA && pB ){
8637: + if( pA->iRule<pB->iRule ){
8638: + *ppPrev = pA;
8639: + ppPrev = &pA->next;
8640: + pA = pA->next;
8641: + }else{
8642: + *ppPrev = pB;
8643: + ppPrev = &pB->next;
8644: + pB = pB->next;
8645: + }
8646: + }
8647: + if( pA ){
8648: + *ppPrev = pA;
8649: + }else{
8650: + *ppPrev = pB;
8651: + }
8652: + return pFirst;
8653: +}
8654: +
8655: +/*
8656: +** Sort a list of rules in order of increasing iRule value
8657: +*/
8658: +static struct rule *Rule_sort(struct rule *rp){
8659: + int i;
8660: + struct rule *pNext;
8661: + struct rule *x[32];
8662: + memset(x, 0, sizeof(x));
8663: + while( rp ){
8664: + pNext = rp->next;
8665: + rp->next = 0;
8666: + for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){
8667: + rp = Rule_merge(x[i], rp);
8668: + x[i] = 0;
8669: + }
8670: + x[i] = rp;
8671: + rp = pNext;
8672: + }
8673: + rp = 0;
8674: + for(i=0; i<sizeof(x)/sizeof(x[0]); i++){
8675: + rp = Rule_merge(x[i], rp);
8676: + }
8677: + return rp;
8678: +}
8679: +
8680: +/* forward reference */
8681: +static const char *minimum_size_type(int lwr, int upr, int *pnByte);
8682: +
8683: +/* Print a single line of the "Parser Stats" output
8684: +*/
8685: +static void stats_line(const char *zLabel, int iValue){
8686: + int nLabel = lemonStrlen(zLabel);
8687: + printf(" %s%.*s %5d\n", zLabel,
8688: + 35-nLabel, "................................",
8689: + iValue);
8690: +}
8691: +
8692: +/* The main program. Parse the command line and do it... */
8693: +int main(int argc, char **argv)
8694: +{
8695: + static int version = 0;
8696: + static int rpflag = 0;
8697: + static int basisflag = 0;
8698: + static int compress = 0;
8699: + static int quiet = 0;
8700: + static int statistics = 0;
8701: + static int mhflag = 0;
8702: + static int nolinenosflag = 0;
8703: + static int noResort = 0;
8704: + static struct s_options options[] = {
8705: + {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
8706: + {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
8707: + {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
8708: + {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"},
8709: + {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
8710: + {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"},
8711: + {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
8712: + {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},
8713: + {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"},
8714: + {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
8715: + "Show conflicts resolved by precedence rules"},
8716: + {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
8717: + {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
8718: + {OPT_FLAG, "s", (char*)&statistics,
8719: + "Print parser stats to standard output."},
8720: + {OPT_FLAG, "x", (char*)&version, "Print the version number."},
8721: + {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
8722: + {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"},
8723: + {OPT_FLAG,0,0,0}
8724: + };
8725: + int i;
8726: + int exitcode;
8727: + struct lemon lem;
8728: + struct rule *rp;
8729: +
8730: + OptInit(argv,options,stderr);
8731: + if( version ){
8732: + printf("Lemon version 1.0\n");
8733: + exit(0);
8734: + }
8735: + if( OptNArgs()!=1 ){
8736: + fprintf(stderr,"Exactly one filename argument is required.\n");
8737: + exit(1);
8738: + }
8739: + memset(&lem, 0, sizeof(lem));
8740: + lem.errorcnt = 0;
8741: +
8742: + /* Initialize the machine */
8743: + Strsafe_init();
8744: + Symbol_init();
8745: + State_init();
8746: + lem.argv0 = argv[0];
8747: + lem.filename = OptArg(0);
8748: + lem.basisflag = basisflag;
8749: + lem.nolinenosflag = nolinenosflag;
8750: + Symbol_new("$");
8751: + lem.errsym = Symbol_new("error");
8752: + lem.errsym->useCnt = 0;
8753: +
8754: + /* Parse the input file */
8755: + Parse(&lem);
8756: + if( lem.errorcnt ) exit(lem.errorcnt);
8757: + if( lem.nrule==0 ){
8758: + fprintf(stderr,"Empty grammar.\n");
8759: + exit(1);
8760: + }
8761: +
8762: + /* Count and index the symbols of the grammar */
8763: + Symbol_new("{default}");
8764: + lem.nsymbol = Symbol_count();
8765: + lem.symbols = Symbol_arrayof();
8766: + for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
8767: + qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp);
8768: + for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
8769: + while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; }
8770: + assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 );
8771: + lem.nsymbol = i - 1;
8772: + for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++);
8773: + lem.nterminal = i;
8774: +
8775: + /* Assign sequential rule numbers. Start with 0. Put rules that have no
8776: + ** reduce action C-code associated with them last, so that the switch()
8777: + ** statement that selects reduction actions will have a smaller jump table.
8778: + */
8779: + for(i=0, rp=lem.rule; rp; rp=rp->next){
8780: + rp->iRule = rp->code ? i++ : -1;
8781: + }
8782: + for(rp=lem.rule; rp; rp=rp->next){
8783: + if( rp->iRule<0 ) rp->iRule = i++;
8784: + }
8785: + lem.startRule = lem.rule;
8786: + lem.rule = Rule_sort(lem.rule);
8787: +
8788: + /* Generate a reprint of the grammar, if requested on the command line */
8789: + if( rpflag ){
8790: + Reprint(&lem);
8791: + }else{
8792: + /* Initialize the size for all follow and first sets */
8793: + SetSize(lem.nterminal+1);
8794: +
8795: + /* Find the precedence for every production rule (that has one) */
8796: + FindRulePrecedences(&lem);
8797: +
8798: + /* Compute the lambda-nonterminals and the first-sets for every
8799: + ** nonterminal */
8800: + FindFirstSets(&lem);
8801: +
8802: + /* Compute all LR(0) states. Also record follow-set propagation
8803: + ** links so that the follow-set can be computed later */
8804: + lem.nstate = 0;
8805: + FindStates(&lem);
8806: + lem.sorted = State_arrayof();
8807: +
8808: + /* Tie up loose ends on the propagation links */
8809: + FindLinks(&lem);
8810: +
8811: + /* Compute the follow set of every reducible configuration */
8812: + FindFollowSets(&lem);
8813: +
8814: + /* Compute the action tables */
8815: + FindActions(&lem);
8816: +
8817: + /* Compress the action tables */
8818: + if( compress==0 ) CompressTables(&lem);
8819: +
8820: + /* Reorder and renumber the states so that states with fewer choices
8821: + ** occur at the end. This is an optimization that helps make the
8822: + ** generated parser tables smaller. */
8823: + if( noResort==0 ) ResortStates(&lem);
8824: +
8825: + /* Generate a report of the parser generated. (the "y.output" file) */
8826: + if( !quiet ) ReportOutput(&lem);
8827: +
8828: + /* Generate the source code for the parser */
8829: + ReportTable(&lem, mhflag);
8830: +
8831: + /* Produce a header file for use by the scanner. (This step is
8832: + ** omitted if the "-m" option is used because makeheaders will
8833: + ** generate the file for us.) */
8834: + if( !mhflag ) ReportHeader(&lem);
8835: + }
8836: + if( statistics ){
8837: + printf("Parser statistics:\n");
8838: + stats_line("terminal symbols", lem.nterminal);
8839: + stats_line("non-terminal symbols", lem.nsymbol - lem.nterminal);
8840: + stats_line("total symbols", lem.nsymbol);
8841: + stats_line("rules", lem.nrule);
8842: + stats_line("states", lem.nxstate);
8843: + stats_line("conflicts", lem.nconflict);
8844: + stats_line("action table entries", lem.nactiontab);
8845: + stats_line("total table size (bytes)", lem.tablesize);
8846: + }
8847: + if( lem.nconflict > 0 ){
8848: + fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
8849: + }
8850: +
8851: + /* return 0 on success, 1 on failure. */
8852: + exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
8853: + exit(exitcode);
8854: + return (exitcode);
8855: +}
8856: +/******************** From the file "msort.c" *******************************/
8857: +/*
8858: +** A generic merge-sort program.
8859: +**
8860: +** USAGE:
8861: +** Let "ptr" be a pointer to some structure which is at the head of
8862: +** a null-terminated list. Then to sort the list call:
8863: +**
8864: +** ptr = msort(ptr,&(ptr->next),cmpfnc);
8865: +**
8866: +** In the above, "cmpfnc" is a pointer to a function which compares
8867: +** two instances of the structure and returns an integer, as in
8868: +** strcmp. The second argument is a pointer to the pointer to the
8869: +** second element of the linked list. This address is used to compute
8870: +** the offset to the "next" field within the structure. The offset to
8871: +** the "next" field must be constant for all structures in the list.
8872: +**
8873: +** The function returns a new pointer which is the head of the list
8874: +** after sorting.
8875: +**
8876: +** ALGORITHM:
8877: +** Merge-sort.
8878: +*/
8879: +
8880: +/*
8881: +** Return a pointer to the next structure in the linked list.
8882: +*/
8883: +#define NEXT(A) (*(char**)(((char*)A)+offset))
8884: +
8885: +/*
8886: +** Inputs:
8887: +** a: A sorted, null-terminated linked list. (May be null).
8888: +** b: A sorted, null-terminated linked list. (May be null).
8889: +** cmp: A pointer to the comparison function.
8890: +** offset: Offset in the structure to the "next" field.
8891: +**
8892: +** Return Value:
8893: +** A pointer to the head of a sorted list containing the elements
8894: +** of both a and b.
8895: +**
8896: +** Side effects:
8897: +** The "next" pointers for elements in the lists a and b are
8898: +** changed.
8899: +*/
8900: +static char *merge(
8901: + char *a,
8902: + char *b,
8903: + int (*cmp)(const char*,const char*),
8904: + int offset
8905: +){
8906: + char *ptr, *head;
8907: +
8908: + if( a==0 ){
8909: + head = b;
8910: + }else if( b==0 ){
8911: + head = a;
8912: + }else{
8913: + if( (*cmp)(a,b)<=0 ){
8914: + ptr = a;
8915: + a = NEXT(a);
8916: + }else{
8917: + ptr = b;
8918: + b = NEXT(b);
8919: + }
8920: + head = ptr;
8921: + while( a && b ){
8922: + if( (*cmp)(a,b)<=0 ){
8923: + NEXT(ptr) = a;
8924: + ptr = a;
8925: + a = NEXT(a);
8926: + }else{
8927: + NEXT(ptr) = b;
8928: + ptr = b;
8929: + b = NEXT(b);
8930: + }
8931: + }
8932: + if( a ) NEXT(ptr) = a;
8933: + else NEXT(ptr) = b;
8934: + }
8935: + return head;
8936: +}
8937: +
8938: +/*
8939: +** Inputs:
8940: +** list: Pointer to a singly-linked list of structures.
8941: +** next: Pointer to pointer to the second element of the list.
8942: +** cmp: A comparison function.
8943: +**
8944: +** Return Value:
8945: +** A pointer to the head of a sorted list containing the elements
8946: +** orginally in list.
8947: +**
8948: +** Side effects:
8949: +** The "next" pointers for elements in list are changed.
8950: +*/
8951: +#define LISTSIZE 30
8952: +static char *msort(
8953: + char *list,
8954: + char **next,
8955: + int (*cmp)(const char*,const char*)
8956: +){
8957: + unsigned long offset;
8958: + char *ep;
8959: + char *set[LISTSIZE];
8960: + int i;
8961: + offset = (unsigned long)((char*)next - (char*)list);
8962: + for(i=0; i<LISTSIZE; i++) set[i] = 0;
8963: + while( list ){
8964: + ep = list;
8965: + list = NEXT(list);
8966: + NEXT(ep) = 0;
8967: + for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
8968: + ep = merge(ep,set[i],cmp,offset);
8969: + set[i] = 0;
8970: + }
8971: + set[i] = ep;
8972: + }
8973: + ep = 0;
8974: + for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
8975: + return ep;
8976: +}
8977: +/************************ From the file "option.c" **************************/
8978: +static char **argv;
8979: +static struct s_options *op;
8980: +static FILE *errstream;
8981: +
8982: +#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
8983: +
8984: +/*
8985: +** Print the command line with a carrot pointing to the k-th character
8986: +** of the n-th field.
8987: +*/
8988: +static void errline(int n, int k, FILE *err)
8989: +{
8990: + int spcnt, i;
8991: + if( argv[0] ) fprintf(err,"%s",argv[0]);
8992: + spcnt = lemonStrlen(argv[0]) + 1;
8993: + for(i=1; i<n && argv[i]; i++){
8994: + fprintf(err," %s",argv[i]);
8995: + spcnt += lemonStrlen(argv[i])+1;
8996: + }
8997: + spcnt += k;
8998: + for(; argv[i]; i++) fprintf(err," %s",argv[i]);
8999: + if( spcnt<20 ){
9000: + fprintf(err,"\n%*s^-- here\n",spcnt,"");
9001: + }else{
9002: + fprintf(err,"\n%*shere --^\n",spcnt-7,"");
9003: + }
9004: +}
9005: +
9006: +/*
9007: +** Return the index of the N-th non-switch argument. Return -1
9008: +** if N is out of range.
9009: +*/
9010: +static int argindex(int n)
9011: +{
9012: + int i;
9013: + int dashdash = 0;
9014: + if( argv!=0 && *argv!=0 ){
9015: + for(i=1; argv[i]; i++){
9016: + if( dashdash || !ISOPT(argv[i]) ){
9017: + if( n==0 ) return i;
9018: + n--;
9019: + }
9020: + if( strcmp(argv[i],"--")==0 ) dashdash = 1;
9021: + }
9022: + }
9023: + return -1;
9024: +}
9025: +
9026: +static char emsg[] = "Command line syntax error: ";
9027: +
9028: +/*
9029: +** Process a flag command line argument.
9030: +*/
9031: +static int handleflags(int i, FILE *err)
9032: +{
9033: + int v;
9034: + int errcnt = 0;
9035: + int j;
9036: + for(j=0; op[j].label; j++){
9037: + if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
9038: + }
9039: + v = argv[i][0]=='-' ? 1 : 0;
9040: + if( op[j].label==0 ){
9041: + if( err ){
9042: + fprintf(err,"%sundefined option.\n",emsg);
9043: + errline(i,1,err);
9044: + }
9045: + errcnt++;
9046: + }else if( op[j].arg==0 ){
9047: + /* Ignore this option */
9048: + }else if( op[j].type==OPT_FLAG ){
9049: + *((int*)op[j].arg) = v;
9050: + }else if( op[j].type==OPT_FFLAG ){
9051: + (*(void(*)(int))(op[j].arg))(v);
9052: + }else if( op[j].type==OPT_FSTR ){
9053: + (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
9054: + }else{
9055: + if( err ){
9056: + fprintf(err,"%smissing argument on switch.\n",emsg);
9057: + errline(i,1,err);
9058: + }
9059: + errcnt++;
9060: + }
9061: + return errcnt;
9062: +}
9063: +
9064: +/*
9065: +** Process a command line switch which has an argument.
9066: +*/
9067: +static int handleswitch(int i, FILE *err)
9068: +{
9069: + int lv = 0;
9070: + double dv = 0.0;
9071: + char *sv = 0, *end;
9072: + char *cp;
9073: + int j;
9074: + int errcnt = 0;
9075: + cp = strchr(argv[i],'=');
9076: + assert( cp!=0 );
9077: + *cp = 0;
9078: + for(j=0; op[j].label; j++){
9079: + if( strcmp(argv[i],op[j].label)==0 ) break;
9080: + }
9081: + *cp = '=';
9082: + if( op[j].label==0 ){
9083: + if( err ){
9084: + fprintf(err,"%sundefined option.\n",emsg);
9085: + errline(i,0,err);
9086: + }
9087: + errcnt++;
9088: + }else{
9089: + cp++;
9090: + switch( op[j].type ){
9091: + case OPT_FLAG:
9092: + case OPT_FFLAG:
9093: + if( err ){
9094: + fprintf(err,"%soption requires an argument.\n",emsg);
9095: + errline(i,0,err);
9096: + }
9097: + errcnt++;
9098: + break;
9099: + case OPT_DBL:
9100: + case OPT_FDBL:
9101: + dv = strtod(cp,&end);
9102: + if( *end ){
9103: + if( err ){
9104: + fprintf(err,
9105: + "%sillegal character in floating-point argument.\n",emsg);
9106: + errline(i,(int)((char*)end-(char*)argv[i]),err);
9107: + }
9108: + errcnt++;
9109: + }
9110: + break;
9111: + case OPT_INT:
9112: + case OPT_FINT:
9113: + lv = strtol(cp,&end,0);
9114: + if( *end ){
9115: + if( err ){
9116: + fprintf(err,"%sillegal character in integer argument.\n",emsg);
9117: + errline(i,(int)((char*)end-(char*)argv[i]),err);
9118: + }
9119: + errcnt++;
9120: + }
9121: + break;
9122: + case OPT_STR:
9123: + case OPT_FSTR:
9124: + sv = cp;
9125: + break;
9126: + }
9127: + switch( op[j].type ){
9128: + case OPT_FLAG:
9129: + case OPT_FFLAG:
9130: + break;
9131: + case OPT_DBL:
9132: + *(double*)(op[j].arg) = dv;
9133: + break;
9134: + case OPT_FDBL:
9135: + (*(void(*)(double))(op[j].arg))(dv);
9136: + break;
9137: + case OPT_INT:
9138: + *(int*)(op[j].arg) = lv;
9139: + break;
9140: + case OPT_FINT:
9141: + (*(void(*)(int))(op[j].arg))((int)lv);
9142: + break;
9143: + case OPT_STR:
9144: + *(char**)(op[j].arg) = sv;
9145: + break;
9146: + case OPT_FSTR:
9147: + (*(void(*)(char *))(op[j].arg))(sv);
9148: + break;
9149: + }
9150: + }
9151: + return errcnt;
9152: +}
9153: +
9154: +int OptInit(char **a, struct s_options *o, FILE *err)
9155: +{
9156: + int errcnt = 0;
9157: + argv = a;
9158: + op = o;
9159: + errstream = err;
9160: + if( argv && *argv && op ){
9161: + int i;
9162: + for(i=1; argv[i]; i++){
9163: + if( argv[i][0]=='+' || argv[i][0]=='-' ){
9164: + errcnt += handleflags(i,err);
9165: + }else if( strchr(argv[i],'=') ){
9166: + errcnt += handleswitch(i,err);
9167: + }
9168: + }
9169: + }
9170: + if( errcnt>0 ){
9171: + fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
9172: + OptPrint();
9173: + exit(1);
9174: + }
9175: + return 0;
9176: +}
9177: +
9178: +int OptNArgs(){
9179: + int cnt = 0;
9180: + int dashdash = 0;
9181: + int i;
9182: + if( argv!=0 && argv[0]!=0 ){
9183: + for(i=1; argv[i]; i++){
9184: + if( dashdash || !ISOPT(argv[i]) ) cnt++;
9185: + if( strcmp(argv[i],"--")==0 ) dashdash = 1;
9186: + }
9187: + }
9188: + return cnt;
9189: +}
9190: +
9191: +char *OptArg(int n)
9192: +{
9193: + int i;
9194: + i = argindex(n);
9195: + return i>=0 ? argv[i] : 0;
9196: +}
9197: +
9198: +void OptErr(int n)
9199: +{
9200: + int i;
9201: + i = argindex(n);
9202: + if( i>=0 ) errline(i,0,errstream);
9203: +}
9204: +
9205: +void OptPrint(){
9206: + int i;
9207: + int max, len;
9208: + max = 0;
9209: + for(i=0; op[i].label; i++){
9210: + len = lemonStrlen(op[i].label) + 1;
9211: + switch( op[i].type ){
9212: + case OPT_FLAG:
9213: + case OPT_FFLAG:
9214: + break;
9215: + case OPT_INT:
9216: + case OPT_FINT:
9217: + len += 9; /* length of "<integer>" */
9218: + break;
9219: + case OPT_DBL:
9220: + case OPT_FDBL:
9221: + len += 6; /* length of "<real>" */
9222: + break;
9223: + case OPT_STR:
9224: + case OPT_FSTR:
9225: + len += 8; /* length of "<string>" */
9226: + break;
9227: + }
9228: + if( len>max ) max = len;
9229: + }
9230: + for(i=0; op[i].label; i++){
9231: + switch( op[i].type ){
9232: + case OPT_FLAG:
9233: + case OPT_FFLAG:
9234: + fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
9235: + break;
9236: + case OPT_INT:
9237: + case OPT_FINT:
9238: + fprintf(errstream," -%s<integer>%*s %s\n",op[i].label,
9239: + (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message);
9240: + break;
9241: + case OPT_DBL:
9242: + case OPT_FDBL:
9243: + fprintf(errstream," -%s<real>%*s %s\n",op[i].label,
9244: + (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message);
9245: + break;
9246: + case OPT_STR:
9247: + case OPT_FSTR:
9248: + fprintf(errstream," -%s<string>%*s %s\n",op[i].label,
9249: + (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message);
9250: + break;
9251: + }
9252: + }
9253: +}
9254: +/*********************** From the file "parse.c" ****************************/
9255: +/*
9256: +** Input file parser for the LEMON parser generator.
9257: +*/
9258: +
9259: +/* The state of the parser */
9260: +enum e_state {
9261: + INITIALIZE,
9262: + WAITING_FOR_DECL_OR_RULE,
9263: + WAITING_FOR_DECL_KEYWORD,
9264: + WAITING_FOR_DECL_ARG,
9265: + WAITING_FOR_PRECEDENCE_SYMBOL,
9266: + WAITING_FOR_ARROW,
9267: + IN_RHS,
9268: + LHS_ALIAS_1,
9269: + LHS_ALIAS_2,
9270: + LHS_ALIAS_3,
9271: + RHS_ALIAS_1,
9272: + RHS_ALIAS_2,
9273: + PRECEDENCE_MARK_1,
9274: + PRECEDENCE_MARK_2,
9275: + RESYNC_AFTER_RULE_ERROR,
9276: + RESYNC_AFTER_DECL_ERROR,
9277: + WAITING_FOR_DESTRUCTOR_SYMBOL,
9278: + WAITING_FOR_DATATYPE_SYMBOL,
9279: + WAITING_FOR_FALLBACK_ID,
9280: + WAITING_FOR_WILDCARD_ID,
9281: + WAITING_FOR_CLASS_ID,
9282: + WAITING_FOR_CLASS_TOKEN
9283: +};
9284: +struct pstate {
9285: + char *filename; /* Name of the input file */
9286: + int tokenlineno; /* Linenumber at which current token starts */
9287: + int errorcnt; /* Number of errors so far */
9288: + char *tokenstart; /* Text of current token */
9289: + struct lemon *gp; /* Global state vector */
9290: + enum e_state state; /* The state of the parser */
9291: + struct symbol *fallback; /* The fallback token */
9292: + struct symbol *tkclass; /* Token class symbol */
9293: + struct symbol *lhs; /* Left-hand side of current rule */
9294: + const char *lhsalias; /* Alias for the LHS */
9295: + int nrhs; /* Number of right-hand side symbols seen */
9296: + struct symbol *rhs[MAXRHS]; /* RHS symbols */
9297: + const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
9298: + struct rule *prevrule; /* Previous rule parsed */
9299: + const char *declkeyword; /* Keyword of a declaration */
9300: + char **declargslot; /* Where the declaration argument should be put */
9301: + int insertLineMacro; /* Add #line before declaration insert */
9302: + int *decllinenoslot; /* Where to write declaration line number */
9303: + enum e_assoc declassoc; /* Assign this association to decl arguments */
9304: + int preccounter; /* Assign this precedence to decl arguments */
9305: + struct rule *firstrule; /* Pointer to first rule in the grammar */
9306: + struct rule *lastrule; /* Pointer to the most recently parsed rule */
9307: +};
9308: +
9309: +/* Parse a single token */
9310: +static void parseonetoken(struct pstate *psp)
9311: +{
9312: + const char *x;
9313: + x = Strsafe(psp->tokenstart); /* Save the token permanently */
9314: +#if 0
9315: + printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
9316: + x,psp->state);
9317: +#endif
9318: + switch( psp->state ){
9319: + case INITIALIZE:
9320: + psp->prevrule = 0;
9321: + psp->preccounter = 0;
9322: + psp->firstrule = psp->lastrule = 0;
9323: + psp->gp->nrule = 0;
9324: + /* Fall thru to next case */
9325: + case WAITING_FOR_DECL_OR_RULE:
9326: + if( x[0]=='%' ){
9327: + psp->state = WAITING_FOR_DECL_KEYWORD;
9328: + }else if( ISLOWER(x[0]) ){
9329: + psp->lhs = Symbol_new(x);
9330: + psp->nrhs = 0;
9331: + psp->lhsalias = 0;
9332: + psp->state = WAITING_FOR_ARROW;
9333: + }else if( x[0]=='{' ){
9334: + if( psp->prevrule==0 ){
9335: + ErrorMsg(psp->filename,psp->tokenlineno,
9336: +"There is no prior rule upon which to attach the code \
9337: +fragment which begins on this line.");
9338: + psp->errorcnt++;
9339: + }else if( psp->prevrule->code!=0 ){
9340: + ErrorMsg(psp->filename,psp->tokenlineno,
9341: +"Code fragment beginning on this line is not the first \
9342: +to follow the previous rule.");
9343: + psp->errorcnt++;
9344: + }else{
9345: + psp->prevrule->line = psp->tokenlineno;
9346: + psp->prevrule->code = &x[1];
9347: + psp->prevrule->noCode = 0;
9348: + }
9349: + }else if( x[0]=='[' ){
9350: + psp->state = PRECEDENCE_MARK_1;
9351: + }else{
9352: + ErrorMsg(psp->filename,psp->tokenlineno,
9353: + "Token \"%s\" should be either \"%%\" or a nonterminal name.",
9354: + x);
9355: + psp->errorcnt++;
9356: + }
9357: + break;
9358: + case PRECEDENCE_MARK_1:
9359: + if( !ISUPPER(x[0]) ){
9360: + ErrorMsg(psp->filename,psp->tokenlineno,
9361: + "The precedence symbol must be a terminal.");
9362: + psp->errorcnt++;
9363: + }else if( psp->prevrule==0 ){
9364: + ErrorMsg(psp->filename,psp->tokenlineno,
9365: + "There is no prior rule to assign precedence \"[%s]\".",x);
9366: + psp->errorcnt++;
9367: + }else if( psp->prevrule->precsym!=0 ){
9368: + ErrorMsg(psp->filename,psp->tokenlineno,
9369: +"Precedence mark on this line is not the first \
9370: +to follow the previous rule.");
9371: + psp->errorcnt++;
9372: + }else{
9373: + psp->prevrule->precsym = Symbol_new(x);
9374: + }
9375: + psp->state = PRECEDENCE_MARK_2;
9376: + break;
9377: + case PRECEDENCE_MARK_2:
9378: + if( x[0]!=']' ){
9379: + ErrorMsg(psp->filename,psp->tokenlineno,
9380: + "Missing \"]\" on precedence mark.");
9381: + psp->errorcnt++;
9382: + }
9383: + psp->state = WAITING_FOR_DECL_OR_RULE;
9384: + break;
9385: + case WAITING_FOR_ARROW:
9386: + if( x[0]==':' && x[1]==':' && x[2]=='=' ){
9387: + psp->state = IN_RHS;
9388: + }else if( x[0]=='(' ){
9389: + psp->state = LHS_ALIAS_1;
9390: + }else{
9391: + ErrorMsg(psp->filename,psp->tokenlineno,
9392: + "Expected to see a \":\" following the LHS symbol \"%s\".",
9393: + psp->lhs->name);
9394: + psp->errorcnt++;
9395: + psp->state = RESYNC_AFTER_RULE_ERROR;
9396: + }
9397: + break;
9398: + case LHS_ALIAS_1:
9399: + if( ISALPHA(x[0]) ){
9400: + psp->lhsalias = x;
9401: + psp->state = LHS_ALIAS_2;
9402: + }else{
9403: + ErrorMsg(psp->filename,psp->tokenlineno,
9404: + "\"%s\" is not a valid alias for the LHS \"%s\"\n",
9405: + x,psp->lhs->name);
9406: + psp->errorcnt++;
9407: + psp->state = RESYNC_AFTER_RULE_ERROR;
9408: + }
9409: + break;
9410: + case LHS_ALIAS_2:
9411: + if( x[0]==')' ){
9412: + psp->state = LHS_ALIAS_3;
9413: + }else{
9414: + ErrorMsg(psp->filename,psp->tokenlineno,
9415: + "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
9416: + psp->errorcnt++;
9417: + psp->state = RESYNC_AFTER_RULE_ERROR;
9418: + }
9419: + break;
9420: + case LHS_ALIAS_3:
9421: + if( x[0]==':' && x[1]==':' && x[2]=='=' ){
9422: + psp->state = IN_RHS;
9423: + }else{
9424: + ErrorMsg(psp->filename,psp->tokenlineno,
9425: + "Missing \"->\" following: \"%s(%s)\".",
9426: + psp->lhs->name,psp->lhsalias);
9427: + psp->errorcnt++;
9428: + psp->state = RESYNC_AFTER_RULE_ERROR;
9429: + }
9430: + break;
9431: + case IN_RHS:
9432: + if( x[0]=='.' ){
9433: + struct rule *rp;
9434: + rp = (struct rule *)calloc( sizeof(struct rule) +
9435: + sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
9436: + if( rp==0 ){
9437: + ErrorMsg(psp->filename,psp->tokenlineno,
9438: + "Can't allocate enough memory for this rule.");
9439: + psp->errorcnt++;
9440: + psp->prevrule = 0;
9441: + }else{
9442: + int i;
9443: + rp->ruleline = psp->tokenlineno;
9444: + rp->rhs = (struct symbol**)&rp[1];
9445: + rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]);
9446: + for(i=0; i<psp->nrhs; i++){
9447: + rp->rhs[i] = psp->rhs[i];
9448: + rp->rhsalias[i] = psp->alias[i];
9449: + }
9450: + rp->lhs = psp->lhs;
9451: + rp->lhsalias = psp->lhsalias;
9452: + rp->nrhs = psp->nrhs;
9453: + rp->code = 0;
9454: + rp->noCode = 1;
9455: + rp->precsym = 0;
9456: + rp->index = psp->gp->nrule++;
9457: + rp->nextlhs = rp->lhs->rule;
9458: + rp->lhs->rule = rp;
9459: + rp->next = 0;
9460: + if( psp->firstrule==0 ){
9461: + psp->firstrule = psp->lastrule = rp;
9462: + }else{
9463: + psp->lastrule->next = rp;
9464: + psp->lastrule = rp;
9465: + }
9466: + psp->prevrule = rp;
9467: + }
9468: + psp->state = WAITING_FOR_DECL_OR_RULE;
9469: + }else if( ISALPHA(x[0]) ){
9470: + if( psp->nrhs>=MAXRHS ){
9471: + ErrorMsg(psp->filename,psp->tokenlineno,
9472: + "Too many symbols on RHS of rule beginning at \"%s\".",
9473: + x);
9474: + psp->errorcnt++;
9475: + psp->state = RESYNC_AFTER_RULE_ERROR;
9476: + }else{
9477: + psp->rhs[psp->nrhs] = Symbol_new(x);
9478: + psp->alias[psp->nrhs] = 0;
9479: + psp->nrhs++;
9480: + }
9481: + }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
9482: + struct symbol *msp = psp->rhs[psp->nrhs-1];
9483: + if( msp->type!=MULTITERMINAL ){
9484: + struct symbol *origsp = msp;
9485: + msp = (struct symbol *) calloc(1,sizeof(*msp));
9486: + memset(msp, 0, sizeof(*msp));
9487: + msp->type = MULTITERMINAL;
9488: + msp->nsubsym = 1;
9489: + msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*));
9490: + msp->subsym[0] = origsp;
9491: + msp->name = origsp->name;
9492: + psp->rhs[psp->nrhs-1] = msp;
9493: + }
9494: + msp->nsubsym++;
9495: + msp->subsym = (struct symbol **) realloc(msp->subsym,
9496: + sizeof(struct symbol*)*msp->nsubsym);
9497: + msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
9498: + if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){
9499: + ErrorMsg(psp->filename,psp->tokenlineno,
9500: + "Cannot form a compound containing a non-terminal");
9501: + psp->errorcnt++;
9502: + }
9503: + }else if( x[0]=='(' && psp->nrhs>0 ){
9504: + psp->state = RHS_ALIAS_1;
9505: + }else{
9506: + ErrorMsg(psp->filename,psp->tokenlineno,
9507: + "Illegal character on RHS of rule: \"%s\".",x);
9508: + psp->errorcnt++;
9509: + psp->state = RESYNC_AFTER_RULE_ERROR;
9510: + }
9511: + break;
9512: + case RHS_ALIAS_1:
9513: + if( ISALPHA(x[0]) ){
9514: + psp->alias[psp->nrhs-1] = x;
9515: + psp->state = RHS_ALIAS_2;
9516: + }else{
9517: + ErrorMsg(psp->filename,psp->tokenlineno,
9518: + "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
9519: + x,psp->rhs[psp->nrhs-1]->name);
9520: + psp->errorcnt++;
9521: + psp->state = RESYNC_AFTER_RULE_ERROR;
9522: + }
9523: + break;
9524: + case RHS_ALIAS_2:
9525: + if( x[0]==')' ){
9526: + psp->state = IN_RHS;
9527: + }else{
9528: + ErrorMsg(psp->filename,psp->tokenlineno,
9529: + "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
9530: + psp->errorcnt++;
9531: + psp->state = RESYNC_AFTER_RULE_ERROR;
9532: + }
9533: + break;
9534: + case WAITING_FOR_DECL_KEYWORD:
9535: + if( ISALPHA(x[0]) ){
9536: + psp->declkeyword = x;
9537: + psp->declargslot = 0;
9538: + psp->decllinenoslot = 0;
9539: + psp->insertLineMacro = 1;
9540: + psp->state = WAITING_FOR_DECL_ARG;
9541: + if( strcmp(x,"name")==0 ){
9542: + psp->declargslot = &(psp->gp->name);
9543: + psp->insertLineMacro = 0;
9544: + }else if( strcmp(x,"include")==0 ){
9545: + psp->declargslot = &(psp->gp->include);
9546: + }else if( strcmp(x,"code")==0 ){
9547: + psp->declargslot = &(psp->gp->extracode);
9548: + }else if( strcmp(x,"token_destructor")==0 ){
9549: + psp->declargslot = &psp->gp->tokendest;
9550: + }else if( strcmp(x,"default_destructor")==0 ){
9551: + psp->declargslot = &psp->gp->vardest;
9552: + }else if( strcmp(x,"token_prefix")==0 ){
9553: + psp->declargslot = &psp->gp->tokenprefix;
9554: + psp->insertLineMacro = 0;
9555: + }else if( strcmp(x,"syntax_error")==0 ){
9556: + psp->declargslot = &(psp->gp->error);
9557: + }else if( strcmp(x,"parse_accept")==0 ){
9558: + psp->declargslot = &(psp->gp->accept);
9559: + }else if( strcmp(x,"parse_failure")==0 ){
9560: + psp->declargslot = &(psp->gp->failure);
9561: + }else if( strcmp(x,"stack_overflow")==0 ){
9562: + psp->declargslot = &(psp->gp->overflow);
9563: + }else if( strcmp(x,"extra_argument")==0 ){
9564: + psp->declargslot = &(psp->gp->arg);
9565: + psp->insertLineMacro = 0;
9566: + }else if( strcmp(x,"token_type")==0 ){
9567: + psp->declargslot = &(psp->gp->tokentype);
9568: + psp->insertLineMacro = 0;
9569: + }else if( strcmp(x,"default_type")==0 ){
9570: + psp->declargslot = &(psp->gp->vartype);
9571: + psp->insertLineMacro = 0;
9572: + }else if( strcmp(x,"stack_size")==0 ){
9573: + psp->declargslot = &(psp->gp->stacksize);
9574: + psp->insertLineMacro = 0;
9575: + }else if( strcmp(x,"start_symbol")==0 ){
9576: + psp->declargslot = &(psp->gp->start);
9577: + psp->insertLineMacro = 0;
9578: + }else if( strcmp(x,"left")==0 ){
9579: + psp->preccounter++;
9580: + psp->declassoc = LEFT;
9581: + psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
9582: + }else if( strcmp(x,"right")==0 ){
9583: + psp->preccounter++;
9584: + psp->declassoc = RIGHT;
9585: + psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
9586: + }else if( strcmp(x,"nonassoc")==0 ){
9587: + psp->preccounter++;
9588: + psp->declassoc = NONE;
9589: + psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
9590: + }else if( strcmp(x,"destructor")==0 ){
9591: + psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
9592: + }else if( strcmp(x,"type")==0 ){
9593: + psp->state = WAITING_FOR_DATATYPE_SYMBOL;
9594: + }else if( strcmp(x,"fallback")==0 ){
9595: + psp->fallback = 0;
9596: + psp->state = WAITING_FOR_FALLBACK_ID;
9597: + }else if( strcmp(x,"wildcard")==0 ){
9598: + psp->state = WAITING_FOR_WILDCARD_ID;
9599: + }else if( strcmp(x,"token_class")==0 ){
9600: + psp->state = WAITING_FOR_CLASS_ID;
9601: + }else{
9602: + ErrorMsg(psp->filename,psp->tokenlineno,
9603: + "Unknown declaration keyword: \"%%%s\".",x);
9604: + psp->errorcnt++;
9605: + psp->state = RESYNC_AFTER_DECL_ERROR;
9606: + }
9607: + }else{
9608: + ErrorMsg(psp->filename,psp->tokenlineno,
9609: + "Illegal declaration keyword: \"%s\".",x);
9610: + psp->errorcnt++;
9611: + psp->state = RESYNC_AFTER_DECL_ERROR;
9612: + }
9613: + break;
9614: + case WAITING_FOR_DESTRUCTOR_SYMBOL:
9615: + if( !ISALPHA(x[0]) ){
9616: + ErrorMsg(psp->filename,psp->tokenlineno,
9617: + "Symbol name missing after %%destructor keyword");
9618: + psp->errorcnt++;
9619: + psp->state = RESYNC_AFTER_DECL_ERROR;
9620: + }else{
9621: + struct symbol *sp = Symbol_new(x);
9622: + psp->declargslot = &sp->destructor;
9623: + psp->decllinenoslot = &sp->destLineno;
9624: + psp->insertLineMacro = 1;
9625: + psp->state = WAITING_FOR_DECL_ARG;
9626: + }
9627: + break;
9628: + case WAITING_FOR_DATATYPE_SYMBOL:
9629: + if( !ISALPHA(x[0]) ){
9630: + ErrorMsg(psp->filename,psp->tokenlineno,
9631: + "Symbol name missing after %%type keyword");
9632: + psp->errorcnt++;
9633: + psp->state = RESYNC_AFTER_DECL_ERROR;
9634: + }else{
9635: + struct symbol *sp = Symbol_find(x);
9636: + if((sp) && (sp->datatype)){
9637: + ErrorMsg(psp->filename,psp->tokenlineno,
9638: + "Symbol %%type \"%s\" already defined", x);
9639: + psp->errorcnt++;
9640: + psp->state = RESYNC_AFTER_DECL_ERROR;
9641: + }else{
9642: + if (!sp){
9643: + sp = Symbol_new(x);
9644: + }
9645: + psp->declargslot = &sp->datatype;
9646: + psp->insertLineMacro = 0;
9647: + psp->state = WAITING_FOR_DECL_ARG;
9648: + }
9649: + }
9650: + break;
9651: + case WAITING_FOR_PRECEDENCE_SYMBOL:
9652: + if( x[0]=='.' ){
9653: + psp->state = WAITING_FOR_DECL_OR_RULE;
9654: + }else if( ISUPPER(x[0]) ){
9655: + struct symbol *sp;
9656: + sp = Symbol_new(x);
9657: + if( sp->prec>=0 ){
9658: + ErrorMsg(psp->filename,psp->tokenlineno,
9659: + "Symbol \"%s\" has already be given a precedence.",x);
9660: + psp->errorcnt++;
9661: + }else{
9662: + sp->prec = psp->preccounter;
9663: + sp->assoc = psp->declassoc;
9664: + }
9665: + }else{
9666: + ErrorMsg(psp->filename,psp->tokenlineno,
9667: + "Can't assign a precedence to \"%s\".",x);
9668: + psp->errorcnt++;
9669: + }
9670: + break;
9671: + case WAITING_FOR_DECL_ARG:
9672: + if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){
9673: + const char *zOld, *zNew;
9674: + char *zBuf, *z;
9675: + int nOld, n, nLine = 0, nNew, nBack;
9676: + int addLineMacro;
9677: + char zLine[50];
9678: + zNew = x;
9679: + if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
9680: + nNew = lemonStrlen(zNew);
9681: + if( *psp->declargslot ){
9682: + zOld = *psp->declargslot;
9683: + }else{
9684: + zOld = "";
9685: + }
9686: + nOld = lemonStrlen(zOld);
9687: + n = nOld + nNew + 20;
9688: + addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
9689: + (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
9690: + if( addLineMacro ){
9691: + for(z=psp->filename, nBack=0; *z; z++){
9692: + if( *z=='\\' ) nBack++;
9693: + }
9694: + lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
9695: + nLine = lemonStrlen(zLine);
9696: + n += nLine + lemonStrlen(psp->filename) + nBack;
9697: + }
9698: + *psp->declargslot = (char *) realloc(*psp->declargslot, n);
9699: + zBuf = *psp->declargslot + nOld;
9700: + if( addLineMacro ){
9701: + if( nOld && zBuf[-1]!='\n' ){
9702: + *(zBuf++) = '\n';
9703: + }
9704: + memcpy(zBuf, zLine, nLine);
9705: + zBuf += nLine;
9706: + *(zBuf++) = '"';
9707: + for(z=psp->filename; *z; z++){
9708: + if( *z=='\\' ){
9709: + *(zBuf++) = '\\';
9710: + }
9711: + *(zBuf++) = *z;
9712: + }
9713: + *(zBuf++) = '"';
9714: + *(zBuf++) = '\n';
9715: + }
9716: + if( psp->decllinenoslot && psp->decllinenoslot[0]==0 ){
9717: + psp->decllinenoslot[0] = psp->tokenlineno;
9718: + }
9719: + memcpy(zBuf, zNew, nNew);
9720: + zBuf += nNew;
9721: + *zBuf = 0;
9722: + psp->state = WAITING_FOR_DECL_OR_RULE;
9723: + }else{
9724: + ErrorMsg(psp->filename,psp->tokenlineno,
9725: + "Illegal argument to %%%s: %s",psp->declkeyword,x);
9726: + psp->errorcnt++;
9727: + psp->state = RESYNC_AFTER_DECL_ERROR;
9728: + }
9729: + break;
9730: + case WAITING_FOR_FALLBACK_ID:
9731: + if( x[0]=='.' ){
9732: + psp->state = WAITING_FOR_DECL_OR_RULE;
9733: + }else if( !ISUPPER(x[0]) ){
9734: + ErrorMsg(psp->filename, psp->tokenlineno,
9735: + "%%fallback argument \"%s\" should be a token", x);
9736: + psp->errorcnt++;
9737: + }else{
9738: + struct symbol *sp = Symbol_new(x);
9739: + if( psp->fallback==0 ){
9740: + psp->fallback = sp;
9741: + }else if( sp->fallback ){
9742: + ErrorMsg(psp->filename, psp->tokenlineno,
9743: + "More than one fallback assigned to token %s", x);
9744: + psp->errorcnt++;
9745: + }else{
9746: + sp->fallback = psp->fallback;
9747: + psp->gp->has_fallback = 1;
9748: + }
9749: + }
9750: + break;
9751: + case WAITING_FOR_WILDCARD_ID:
9752: + if( x[0]=='.' ){
9753: + psp->state = WAITING_FOR_DECL_OR_RULE;
9754: + }else if( !ISUPPER(x[0]) ){
9755: + ErrorMsg(psp->filename, psp->tokenlineno,
9756: + "%%wildcard argument \"%s\" should be a token", x);
9757: + psp->errorcnt++;
9758: + }else{
9759: + struct symbol *sp = Symbol_new(x);
9760: + if( psp->gp->wildcard==0 ){
9761: + psp->gp->wildcard = sp;
9762: + }else{
9763: + ErrorMsg(psp->filename, psp->tokenlineno,
9764: + "Extra wildcard to token: %s", x);
9765: + psp->errorcnt++;
9766: + }
9767: + }
9768: + break;
9769: + case WAITING_FOR_CLASS_ID:
9770: + if( !ISLOWER(x[0]) ){
9771: + ErrorMsg(psp->filename, psp->tokenlineno,
9772: + "%%token_class must be followed by an identifier: ", x);
9773: + psp->errorcnt++;
9774: + psp->state = RESYNC_AFTER_DECL_ERROR;
9775: + }else if( Symbol_find(x) ){
9776: + ErrorMsg(psp->filename, psp->tokenlineno,
9777: + "Symbol \"%s\" already used", x);
9778: + psp->errorcnt++;
9779: + psp->state = RESYNC_AFTER_DECL_ERROR;
9780: + }else{
9781: + psp->tkclass = Symbol_new(x);
9782: + psp->tkclass->type = MULTITERMINAL;
9783: + psp->state = WAITING_FOR_CLASS_TOKEN;
9784: + }
9785: + break;
9786: + case WAITING_FOR_CLASS_TOKEN:
9787: + if( x[0]=='.' ){
9788: + psp->state = WAITING_FOR_DECL_OR_RULE;
9789: + }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){
9790: + struct symbol *msp = psp->tkclass;
9791: + msp->nsubsym++;
9792: + msp->subsym = (struct symbol **) realloc(msp->subsym,
9793: + sizeof(struct symbol*)*msp->nsubsym);
9794: + if( !ISUPPER(x[0]) ) x++;
9795: + msp->subsym[msp->nsubsym-1] = Symbol_new(x);
9796: + }else{
9797: + ErrorMsg(psp->filename, psp->tokenlineno,
9798: + "%%token_class argument \"%s\" should be a token", x);
9799: + psp->errorcnt++;
9800: + psp->state = RESYNC_AFTER_DECL_ERROR;
9801: + }
9802: + break;
9803: + case RESYNC_AFTER_RULE_ERROR:
9804: +/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
9805: +** break; */
9806: + case RESYNC_AFTER_DECL_ERROR:
9807: + if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
9808: + if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
9809: + break;
9810: + }
9811: +}
9812: +
9813: +/* Run the preprocessor over the input file text. The global variables
9814: +** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
9815: +** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and
9816: +** comments them out. Text in between is also commented out as appropriate.
9817: +*/
9818: +static void preprocess_input(char *z){
9819: + int i, j, k, n;
9820: + int exclude = 0;
9821: + int start = 0;
9822: + int lineno = 1;
9823: + int start_lineno = 1;
9824: + for(i=0; z[i]; i++){
9825: + if( z[i]=='\n' ) lineno++;
9826: + if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue;
9827: + if( strncmp(&z[i],"%endif",6)==0 && ISSPACE(z[i+6]) ){
9828: + if( exclude ){
9829: + exclude--;
9830: + if( exclude==0 ){
9831: + for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
9832: + }
9833: + }
9834: + for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
9835: + }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6]))
9836: + || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){
9837: + if( exclude ){
9838: + exclude++;
9839: + }else{
9840: + for(j=i+7; ISSPACE(z[j]); j++){}
9841: + for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){}
9842: + exclude = 1;
9843: + for(k=0; k<nDefine; k++){
9844: + if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
9845: + exclude = 0;
9846: + break;
9847: + }
9848: + }
9849: + if( z[i+3]=='n' ) exclude = !exclude;
9850: + if( exclude ){
9851: + start = i;
9852: + start_lineno = lineno;
9853: + }
9854: + }
9855: + for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
9856: + }
9857: + }
9858: + if( exclude ){
9859: + fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno);
9860: + exit(1);
9861: + }
9862: +}
9863: +
9864: +/* In spite of its name, this function is really a scanner. It read
9865: +** in the entire input file (all at once) then tokenizes it. Each
9866: +** token is passed to the function "parseonetoken" which builds all
9867: +** the appropriate data structures in the global state vector "gp".
9868: +*/
9869: +void Parse(struct lemon *gp)
9870: +{
9871: + struct pstate ps;
9872: + FILE *fp;
9873: + char *filebuf;
9874: + unsigned int filesize;
9875: + int lineno;
9876: + int c;
9877: + char *cp, *nextcp;
9878: + int startline = 0;
9879: +
9880: + memset(&ps, '\0', sizeof(ps));
9881: + ps.gp = gp;
9882: + ps.filename = gp->filename;
9883: + ps.errorcnt = 0;
9884: + ps.state = INITIALIZE;
9885: +
9886: + /* Begin by reading the input file */
9887: + fp = fopen(ps.filename,"rb");
9888: + if( fp==0 ){
9889: + ErrorMsg(ps.filename,0,"Can't open this file for reading.");
9890: + gp->errorcnt++;
9891: + return;
9892: + }
9893: + fseek(fp,0,2);
9894: + filesize = ftell(fp);
9895: + rewind(fp);
9896: + filebuf = (char *)malloc( filesize+1 );
9897: + if( filesize>100000000 || filebuf==0 ){
9898: + ErrorMsg(ps.filename,0,"Input file too large.");
9899: + gp->errorcnt++;
9900: + fclose(fp);
9901: + return;
9902: + }
9903: + if( fread(filebuf,1,filesize,fp)!=filesize ){
9904: + ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
9905: + filesize);
9906: + free(filebuf);
9907: + gp->errorcnt++;
9908: + fclose(fp);
9909: + return;
9910: + }
9911: + fclose(fp);
9912: + filebuf[filesize] = 0;
9913: +
9914: + /* Make an initial pass through the file to handle %ifdef and %ifndef */
9915: + preprocess_input(filebuf);
9916: +
9917: + /* Now scan the text of the input file */
9918: + lineno = 1;
9919: + for(cp=filebuf; (c= *cp)!=0; ){
9920: + if( c=='\n' ) lineno++; /* Keep track of the line number */
9921: + if( ISSPACE(c) ){ cp++; continue; } /* Skip all white space */
9922: + if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */
9923: + cp+=2;
9924: + while( (c= *cp)!=0 && c!='\n' ) cp++;
9925: + continue;
9926: + }
9927: + if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
9928: + cp+=2;
9929: + while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
9930: + if( c=='\n' ) lineno++;
9931: + cp++;
9932: + }
9933: + if( c ) cp++;
9934: + continue;
9935: + }
9936: + ps.tokenstart = cp; /* Mark the beginning of the token */
9937: + ps.tokenlineno = lineno; /* Linenumber on which token begins */
9938: + if( c=='\"' ){ /* String literals */
9939: + cp++;
9940: + while( (c= *cp)!=0 && c!='\"' ){
9941: + if( c=='\n' ) lineno++;
9942: + cp++;
9943: + }
9944: + if( c==0 ){
9945: + ErrorMsg(ps.filename,startline,
9946: +"String starting on this line is not terminated before the end of the file.");
9947: + ps.errorcnt++;
9948: + nextcp = cp;
9949: + }else{
9950: + nextcp = cp+1;
9951: + }
9952: + }else if( c=='{' ){ /* A block of C code */
9953: + int level;
9954: + cp++;
9955: + for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
9956: + if( c=='\n' ) lineno++;
9957: + else if( c=='{' ) level++;
9958: + else if( c=='}' ) level--;
9959: + else if( c=='/' && cp[1]=='*' ){ /* Skip comments */
9960: + int prevc;
9961: + cp = &cp[2];
9962: + prevc = 0;
9963: + while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
9964: + if( c=='\n' ) lineno++;
9965: + prevc = c;
9966: + cp++;
9967: + }
9968: + }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
9969: + cp = &cp[2];
9970: + while( (c= *cp)!=0 && c!='\n' ) cp++;
9971: + if( c ) lineno++;
9972: + }else if( c=='\'' || c=='\"' ){ /* String a character literals */
9973: + int startchar, prevc;
9974: + startchar = c;
9975: + prevc = 0;
9976: + for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
9977: + if( c=='\n' ) lineno++;
9978: + if( prevc=='\\' ) prevc = 0;
9979: + else prevc = c;
9980: + }
9981: + }
9982: + }
9983: + if( c==0 ){
9984: + ErrorMsg(ps.filename,ps.tokenlineno,
9985: +"C code starting on this line is not terminated before the end of the file.");
9986: + ps.errorcnt++;
9987: + nextcp = cp;
9988: + }else{
9989: + nextcp = cp+1;
9990: + }
9991: + }else if( ISALNUM(c) ){ /* Identifiers */
9992: + while( (c= *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++;
9993: + nextcp = cp;
9994: + }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
9995: + cp += 3;
9996: + nextcp = cp;
9997: + }else if( (c=='/' || c=='|') && ISALPHA(cp[1]) ){
9998: + cp += 2;
9999: + while( (c = *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++;
10000: + nextcp = cp;
10001: + }else{ /* All other (one character) operators */
10002: + cp++;
10003: + nextcp = cp;
10004: + }
10005: + c = *cp;
10006: + *cp = 0; /* Null terminate the token */
10007: + parseonetoken(&ps); /* Parse the token */
10008: + *cp = (char)c; /* Restore the buffer */
10009: + cp = nextcp;
10010: + }
10011: + free(filebuf); /* Release the buffer after parsing */
10012: + gp->rule = ps.firstrule;
10013: + gp->errorcnt = ps.errorcnt;
10014: +}
10015: +/*************************** From the file "plink.c" *********************/
10016: +/*
10017: +** Routines processing configuration follow-set propagation links
10018: +** in the LEMON parser generator.
10019: +*/
10020: +static struct plink *plink_freelist = 0;
10021: +
10022: +/* Allocate a new plink */
10023: +struct plink *Plink_new(){
10024: + struct plink *newlink;
10025: +
10026: + if( plink_freelist==0 ){
10027: + int i;
10028: + int amt = 100;
10029: + plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
10030: + if( plink_freelist==0 ){
10031: + fprintf(stderr,
10032: + "Unable to allocate memory for a new follow-set propagation link.\n");
10033: + exit(1);
10034: + }
10035: + for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
10036: + plink_freelist[amt-1].next = 0;
10037: + }
10038: + newlink = plink_freelist;
10039: + plink_freelist = plink_freelist->next;
10040: + return newlink;
10041: +}
10042: +
10043: +/* Add a plink to a plink list */
10044: +void Plink_add(struct plink **plpp, struct config *cfp)
10045: +{
10046: + struct plink *newlink;
10047: + newlink = Plink_new();
10048: + newlink->next = *plpp;
10049: + *plpp = newlink;
10050: + newlink->cfp = cfp;
10051: +}
10052: +
10053: +/* Transfer every plink on the list "from" to the list "to" */
10054: +void Plink_copy(struct plink **to, struct plink *from)
10055: +{
10056: + struct plink *nextpl;
10057: + while( from ){
10058: + nextpl = from->next;
10059: + from->next = *to;
10060: + *to = from;
10061: + from = nextpl;
10062: + }
10063: +}
10064: +
10065: +/* Delete every plink on the list */
10066: +void Plink_delete(struct plink *plp)
10067: +{
10068: + struct plink *nextpl;
10069: +
10070: + while( plp ){
10071: + nextpl = plp->next;
10072: + plp->next = plink_freelist;
10073: + plink_freelist = plp;
10074: + plp = nextpl;
10075: + }
10076: +}
10077: +/*********************** From the file "report.c" **************************/
10078: +/*
10079: +** Procedures for generating reports and tables in the LEMON parser generator.
10080: +*/
10081: +
10082: +/* Generate a filename with the given suffix. Space to hold the
10083: +** name comes from malloc() and must be freed by the calling
10084: +** function.
10085: +*/
10086: +PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
10087: +{
10088: + char *name;
10089: + char *cp;
10090: +
10091: + name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 );
10092: + if( name==0 ){
10093: + fprintf(stderr,"Can't allocate space for a filename.\n");
10094: + exit(1);
10095: + }
10096: + lemon_strcpy(name,lemp->filename);
10097: + cp = strrchr(name,'.');
10098: + if( cp ) *cp = 0;
10099: + lemon_strcat(name,suffix);
10100: + return name;
10101: +}
10102: +
10103: +/* Open a file with a name based on the name of the input file,
10104: +** but with a different (specified) suffix, and return a pointer
10105: +** to the stream */
10106: +PRIVATE FILE *file_open(
10107: + struct lemon *lemp,
10108: + const char *suffix,
10109: + const char *mode
10110: +){
10111: + FILE *fp;
10112: +
10113: + if( lemp->outname ) free(lemp->outname);
10114: + lemp->outname = file_makename(lemp, suffix);
10115: + fp = fopen(lemp->outname,mode);
10116: + if( fp==0 && *mode=='w' ){
10117: + fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
10118: + lemp->errorcnt++;
10119: + return 0;
10120: + }
10121: + return fp;
10122: +}
10123: +
10124: +/* Duplicate the input file without comments and without actions
10125: +** on rules */
10126: +void Reprint(struct lemon *lemp)
10127: +{
10128: + struct rule *rp;
10129: + struct symbol *sp;
10130: + int i, j, maxlen, len, ncolumns, skip;
10131: + printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
10132: + maxlen = 10;
10133: + for(i=0; i<lemp->nsymbol; i++){
10134: + sp = lemp->symbols[i];
10135: + len = lemonStrlen(sp->name);
10136: + if( len>maxlen ) maxlen = len;
10137: + }
10138: + ncolumns = 76/(maxlen+5);
10139: + if( ncolumns<1 ) ncolumns = 1;
10140: + skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
10141: + for(i=0; i<skip; i++){
10142: + printf("//");
10143: + for(j=i; j<lemp->nsymbol; j+=skip){
10144: + sp = lemp->symbols[j];
10145: + assert( sp->index==j );
10146: + printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
10147: + }
10148: + printf("\n");
10149: + }
10150: + for(rp=lemp->rule; rp; rp=rp->next){
10151: + printf("%s",rp->lhs->name);
10152: + /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
10153: + printf(" ::=");
10154: + for(i=0; i<rp->nrhs; i++){
10155: + sp = rp->rhs[i];
10156: + if( sp->type==MULTITERMINAL ){
10157: + printf(" %s", sp->subsym[0]->name);
10158: + for(j=1; j<sp->nsubsym; j++){
10159: + printf("|%s", sp->subsym[j]->name);
10160: + }
10161: + }else{
10162: + printf(" %s", sp->name);
10163: + }
10164: + /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
10165: + }
10166: + printf(".");
10167: + if( rp->precsym ) printf(" [%s]",rp->precsym->name);
10168: + /* if( rp->code ) printf("\n %s",rp->code); */
10169: + printf("\n");
10170: + }
10171: +}
10172: +
10173: +/* Print a single rule.
10174: +*/
10175: +void RulePrint(FILE *fp, struct rule *rp, int iCursor){
10176: + struct symbol *sp;
10177: + int i, j;
10178: + fprintf(fp,"%s ::=",rp->lhs->name);
10179: + for(i=0; i<=rp->nrhs; i++){
10180: + if( i==iCursor ) fprintf(fp," *");
10181: + if( i==rp->nrhs ) break;
10182: + sp = rp->rhs[i];
10183: + if( sp->type==MULTITERMINAL ){
10184: + fprintf(fp," %s", sp->subsym[0]->name);
10185: + for(j=1; j<sp->nsubsym; j++){
10186: + fprintf(fp,"|%s",sp->subsym[j]->name);
10187: + }
10188: + }else{
10189: + fprintf(fp," %s", sp->name);
10190: + }
10191: + }
10192: +}
10193: +
10194: +/* Print the rule for a configuration.
10195: +*/
10196: +void ConfigPrint(FILE *fp, struct config *cfp){
10197: + RulePrint(fp, cfp->rp, cfp->dot);
10198: +}
10199: +
10200: +/* #define TEST */
10201: +#if 0
10202: +/* Print a set */
10203: +PRIVATE void SetPrint(out,set,lemp)
10204: +FILE *out;
10205: +char *set;
10206: +struct lemon *lemp;
10207: +{
10208: + int i;
10209: + char *spacer;
10210: + spacer = "";
10211: + fprintf(out,"%12s[","");
10212: + for(i=0; i<lemp->nterminal; i++){
10213: + if( SetFind(set,i) ){
10214: + fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
10215: + spacer = " ";
10216: + }
10217: + }
10218: + fprintf(out,"]\n");
10219: +}
10220: +
10221: +/* Print a plink chain */
10222: +PRIVATE void PlinkPrint(out,plp,tag)
10223: +FILE *out;
10224: +struct plink *plp;
10225: +char *tag;
10226: +{
10227: + while( plp ){
10228: + fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum);
10229: + ConfigPrint(out,plp->cfp);
10230: + fprintf(out,"\n");
10231: + plp = plp->next;
10232: + }
10233: +}
10234: +#endif
10235: +
10236: +/* Print an action to the given file descriptor. Return FALSE if
10237: +** nothing was actually printed.
10238: +*/
10239: +int PrintAction(
10240: + struct action *ap, /* The action to print */
10241: + FILE *fp, /* Print the action here */
10242: + int indent /* Indent by this amount */
10243: +){
10244: + int result = 1;
10245: + switch( ap->type ){
10246: + case SHIFT: {
10247: + struct state *stp = ap->x.stp;
10248: + fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum);
10249: + break;
10250: + }
10251: + case REDUCE: {
10252: + struct rule *rp = ap->x.rp;
10253: + fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->iRule);
10254: + RulePrint(fp, rp, -1);
10255: + break;
10256: + }
10257: + case SHIFTREDUCE: {
10258: + struct rule *rp = ap->x.rp;
10259: + fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->iRule);
10260: + RulePrint(fp, rp, -1);
10261: + break;
10262: + }
10263: + case ACCEPT:
10264: + fprintf(fp,"%*s accept",indent,ap->sp->name);
10265: + break;
10266: + case ERROR:
10267: + fprintf(fp,"%*s error",indent,ap->sp->name);
10268: + break;
10269: + case SRCONFLICT:
10270: + case RRCONFLICT:
10271: + fprintf(fp,"%*s reduce %-7d ** Parsing conflict **",
10272: + indent,ap->sp->name,ap->x.rp->iRule);
10273: + break;
10274: + case SSCONFLICT:
10275: + fprintf(fp,"%*s shift %-7d ** Parsing conflict **",
10276: + indent,ap->sp->name,ap->x.stp->statenum);
10277: + break;
10278: + case SH_RESOLVED:
10279: + if( showPrecedenceConflict ){
10280: + fprintf(fp,"%*s shift %-7d -- dropped by precedence",
10281: + indent,ap->sp->name,ap->x.stp->statenum);
10282: + }else{
10283: + result = 0;
10284: + }
10285: + break;
10286: + case RD_RESOLVED:
10287: + if( showPrecedenceConflict ){
10288: + fprintf(fp,"%*s reduce %-7d -- dropped by precedence",
10289: + indent,ap->sp->name,ap->x.rp->iRule);
10290: + }else{
10291: + result = 0;
10292: + }
10293: + break;
10294: + case NOT_USED:
10295: + result = 0;
10296: + break;
10297: + }
10298: + if( result && ap->spOpt ){
10299: + fprintf(fp," /* because %s==%s */", ap->sp->name, ap->spOpt->name);
10300: + }
10301: + return result;
10302: +}
10303: +
10304: +/* Generate the "*.out" log file */
10305: +void ReportOutput(struct lemon *lemp)
10306: +{
10307: + int i;
10308: + struct state *stp;
10309: + struct config *cfp;
10310: + struct action *ap;
10311: + FILE *fp;
10312: +
10313: + fp = file_open(lemp,".out","wb");
10314: + if( fp==0 ) return;
10315: + for(i=0; i<lemp->nxstate; i++){
10316: + stp = lemp->sorted[i];
10317: + fprintf(fp,"State %d:\n",stp->statenum);
10318: + if( lemp->basisflag ) cfp=stp->bp;
10319: + else cfp=stp->cfp;
10320: + while( cfp ){
10321: + char buf[20];
10322: + if( cfp->dot==cfp->rp->nrhs ){
10323: + lemon_sprintf(buf,"(%d)",cfp->rp->iRule);
10324: + fprintf(fp," %5s ",buf);
10325: + }else{
10326: + fprintf(fp," ");
10327: + }
10328: + ConfigPrint(fp,cfp);
10329: + fprintf(fp,"\n");
10330: +#if 0
10331: + SetPrint(fp,cfp->fws,lemp);
10332: + PlinkPrint(fp,cfp->fplp,"To ");
10333: + PlinkPrint(fp,cfp->bplp,"From");
10334: +#endif
10335: + if( lemp->basisflag ) cfp=cfp->bp;
10336: + else cfp=cfp->next;
10337: + }
10338: + fprintf(fp,"\n");
10339: + for(ap=stp->ap; ap; ap=ap->next){
10340: + if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
10341: + }
10342: + fprintf(fp,"\n");
10343: + }
10344: + fprintf(fp, "----------------------------------------------------\n");
10345: + fprintf(fp, "Symbols:\n");
10346: + for(i=0; i<lemp->nsymbol; i++){
10347: + int j;
10348: + struct symbol *sp;
10349: +
10350: + sp = lemp->symbols[i];
10351: + fprintf(fp, " %3d: %s", i, sp->name);
10352: + if( sp->type==NONTERMINAL ){
10353: + fprintf(fp, ":");
10354: + if( sp->lambda ){
10355: + fprintf(fp, " <lambda>");
10356: + }
10357: + for(j=0; j<lemp->nterminal; j++){
10358: + if( sp->firstset && SetFind(sp->firstset, j) ){
10359: + fprintf(fp, " %s", lemp->symbols[j]->name);
10360: + }
10361: + }
10362: + }
10363: + fprintf(fp, "\n");
10364: + }
10365: + fclose(fp);
10366: + return;
10367: +}
10368: +
10369: +/* Search for the file "name" which is in the same directory as
10370: +** the exacutable */
10371: +PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
10372: +{
10373: + const char *pathlist;
10374: + char *pathbufptr;
10375: + char *pathbuf;
10376: + char *path,*cp;
10377: + char c;
10378: +
10379: +#ifdef __WIN32__
10380: + cp = strrchr(argv0,'\\');
10381: +#else
10382: + cp = strrchr(argv0,'/');
10383: +#endif
10384: + if( cp ){
10385: + c = *cp;
10386: + *cp = 0;
10387: + path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
10388: + if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
10389: + *cp = c;
10390: + }else{
10391: + pathlist = getenv("PATH");
10392: + if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
10393: + pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
10394: + path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
10395: + if( (pathbuf != 0) && (path!=0) ){
10396: + pathbufptr = pathbuf;
10397: + lemon_strcpy(pathbuf, pathlist);
10398: + while( *pathbuf ){
10399: + cp = strchr(pathbuf,':');
10400: + if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)];
10401: + c = *cp;
10402: + *cp = 0;
10403: + lemon_sprintf(path,"%s/%s",pathbuf,name);
10404: + *cp = c;
10405: + if( c==0 ) pathbuf[0] = 0;
10406: + else pathbuf = &cp[1];
10407: + if( access(path,modemask)==0 ) break;
10408: + }
10409: + free(pathbufptr);
10410: + }
10411: + }
10412: + return path;
10413: +}
10414: +
10415: +/* Given an action, compute the integer value for that action
10416: +** which is to be put in the action table of the generated machine.
10417: +** Return negative if no action should be generated.
10418: +*/
10419: +PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
10420: +{
10421: + int act;
10422: + switch( ap->type ){
10423: + case SHIFT: act = ap->x.stp->statenum; break;
10424: + case SHIFTREDUCE: act = ap->x.rp->iRule + lemp->nstate; break;
10425: + case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break;
10426: + case ERROR: act = lemp->nstate + lemp->nrule*2; break;
10427: + case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break;
10428: + default: act = -1; break;
10429: + }
10430: + return act;
10431: +}
10432: +
10433: +#define LINESIZE 1000
10434: +/* The next cluster of routines are for reading the template file
10435: +** and writing the results to the generated parser */
10436: +/* The first function transfers data from "in" to "out" until
10437: +** a line is seen which begins with "%%". The line number is
10438: +** tracked.
10439: +**
10440: +** if name!=0, then any word that begin with "Parse" is changed to
10441: +** begin with *name instead.
10442: +*/
10443: +PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
10444: +{
10445: + int i, iStart;
10446: + char line[LINESIZE];
10447: + while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
10448: + (*lineno)++;
10449: + iStart = 0;
10450: + if( name ){
10451: + for(i=0; line[i]; i++){
10452: + if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
10453: + && (i==0 || !ISALPHA(line[i-1]))
10454: + ){
10455: + if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
10456: + fprintf(out,"%s",name);
10457: + i += 4;
10458: + iStart = i+1;
10459: + }
10460: + }
10461: + }
10462: + fprintf(out,"%s",&line[iStart]);
10463: + }
10464: +}
10465: +
10466: +/* The next function finds the template file and opens it, returning
10467: +** a pointer to the opened file. */
10468: +PRIVATE FILE *tplt_open(struct lemon *lemp)
10469: +{
10470: + static char templatename[] = "lempar.c";
10471: + char buf[1000];
10472: + FILE *in;
10473: + char *tpltname;
10474: + char *cp;
10475: +
10476: + /* first, see if user specified a template filename on the command line. */
10477: + if (user_templatename != 0) {
10478: + if( access(user_templatename,004)==-1 ){
10479: + fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
10480: + user_templatename);
10481: + lemp->errorcnt++;
10482: + return 0;
10483: + }
10484: + in = fopen(user_templatename,"rb");
10485: + if( in==0 ){
10486: + fprintf(stderr,"Can't open the template file \"%s\".\n",
10487: + user_templatename);
10488: + lemp->errorcnt++;
10489: + return 0;
10490: + }
10491: + return in;
10492: + }
10493: +
10494: + cp = strrchr(lemp->filename,'.');
10495: + if( cp ){
10496: + lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
10497: + }else{
10498: + lemon_sprintf(buf,"%s.lt",lemp->filename);
10499: + }
10500: + if( access(buf,004)==0 ){
10501: + tpltname = buf;
10502: + }else if( access(templatename,004)==0 ){
10503: + tpltname = templatename;
10504: + }else{
10505: + tpltname = pathsearch(lemp->argv0,templatename,0);
10506: + }
10507: + if( tpltname==0 ){
10508: + fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
10509: + templatename);
10510: + lemp->errorcnt++;
10511: + return 0;
10512: + }
10513: + in = fopen(tpltname,"rb");
10514: + if( in==0 ){
10515: + fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
10516: + lemp->errorcnt++;
10517: + return 0;
10518: + }
10519: + return in;
10520: +}
10521: +
10522: +/* Print a #line directive line to the output file. */
10523: +PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename)
10524: +{
10525: + fprintf(out,"#line %d \"",lineno);
10526: + while( *filename ){
10527: + if( *filename == '\\' ) putc('\\',out);
10528: + putc(*filename,out);
10529: + filename++;
10530: + }
10531: + fprintf(out,"\"\n");
10532: +}
10533: +
10534: +/* Print a string to the file and keep the linenumber up to date */
10535: +PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno)
10536: +{
10537: + if( str==0 ) return;
10538: + while( *str ){
10539: + putc(*str,out);
10540: + if( *str=='\n' ) (*lineno)++;
10541: + str++;
10542: + }
10543: + if( str[-1]!='\n' ){
10544: + putc('\n',out);
10545: + (*lineno)++;
10546: + }
10547: + if (!lemp->nolinenosflag) {
10548: + (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
10549: + }
10550: + return;
10551: +}
10552: +
10553: +/*
10554: +** The following routine emits code for the destructor for the
10555: +** symbol sp
10556: +*/
10557: +void emit_destructor_code(
10558: + FILE *out,
10559: + struct symbol *sp,
10560: + struct lemon *lemp,
10561: + int *lineno
10562: +){
10563: + char *cp = 0;
10564: +
10565: + if( sp->type==TERMINAL ){
10566: + cp = lemp->tokendest;
10567: + if( cp==0 ) return;
10568: + fprintf(out,"{\n"); (*lineno)++;
10569: + }else if( sp->destructor ){
10570: + cp = sp->destructor;
10571: + fprintf(out,"{\n"); (*lineno)++;
10572: + if( !lemp->nolinenosflag ){
10573: + (*lineno)++;
10574: + tplt_linedir(out,sp->destLineno,lemp->filename);
10575: + }
10576: + }else if( lemp->vardest ){
10577: + cp = lemp->vardest;
10578: + if( cp==0 ) return;
10579: + fprintf(out,"{\n"); (*lineno)++;
10580: + }else{
10581: + assert( 0 ); /* Cannot happen */
10582: + }
10583: + for(; *cp; cp++){
10584: + if( *cp=='$' && cp[1]=='$' ){
10585: + fprintf(out,"(yypminor->yy%d)",sp->dtnum);
10586: + cp++;
10587: + continue;
10588: + }
10589: + if( *cp=='\n' ) (*lineno)++;
10590: + fputc(*cp,out);
10591: + }
10592: + fprintf(out,"\n"); (*lineno)++;
10593: + if (!lemp->nolinenosflag) {
10594: + (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
10595: + }
10596: + fprintf(out,"}\n"); (*lineno)++;
10597: + return;
10598: +}
10599: +
10600: +/*
10601: +** Return TRUE (non-zero) if the given symbol has a destructor.
10602: +*/
10603: +int has_destructor(struct symbol *sp, struct lemon *lemp)
10604: +{
10605: + int ret;
10606: + if( sp->type==TERMINAL ){
10607: + ret = lemp->tokendest!=0;
10608: + }else{
10609: + ret = lemp->vardest!=0 || sp->destructor!=0;
10610: + }
10611: + return ret;
10612: +}
10613: +
10614: +/*
10615: +** Append text to a dynamically allocated string. If zText is 0 then
10616: +** reset the string to be empty again. Always return the complete text
10617: +** of the string (which is overwritten with each call).
10618: +**
10619: +** n bytes of zText are stored. If n==0 then all of zText up to the first
10620: +** \000 terminator is stored. zText can contain up to two instances of
10621: +** %d. The values of p1 and p2 are written into the first and second
10622: +** %d.
10623: +**
10624: +** If n==-1, then the previous character is overwritten.
10625: +*/
10626: +PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
10627: + static char empty[1] = { 0 };
10628: + static char *z = 0;
10629: + static int alloced = 0;
10630: + static int used = 0;
10631: + int c;
10632: + char zInt[40];
10633: + if( zText==0 ){
10634: + if( used==0 && z!=0 ) z[0] = 0;
10635: + used = 0;
10636: + return z;
10637: + }
10638: + if( n<=0 ){
10639: + if( n<0 ){
10640: + used += n;
10641: + assert( used>=0 );
10642: + }
10643: + n = lemonStrlen(zText);
10644: + }
10645: + if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
10646: + alloced = n + sizeof(zInt)*2 + used + 200;
10647: + z = (char *) realloc(z, alloced);
10648: + }
10649: + if( z==0 ) return empty;
10650: + while( n-- > 0 ){
10651: + c = *(zText++);
10652: + if( c=='%' && n>0 && zText[0]=='d' ){
10653: + lemon_sprintf(zInt, "%d", p1);
10654: + p1 = p2;
10655: + lemon_strcpy(&z[used], zInt);
10656: + used += lemonStrlen(&z[used]);
10657: + zText++;
10658: + n--;
10659: + }else{
10660: + z[used++] = (char)c;
10661: + }
10662: + }
10663: + z[used] = 0;
10664: + return z;
10665: +}
10666: +
10667: +/*
10668: +** Write and transform the rp->code string so that symbols are expanded.
10669: +** Populate the rp->codePrefix and rp->codeSuffix strings, as appropriate.
10670: +**
10671: +** Return 1 if the expanded code requires that "yylhsminor" local variable
10672: +** to be defined.
10673: +*/
10674: +PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
10675: + char *cp, *xp;
10676: + int i;
10677: + int rc = 0; /* True if yylhsminor is used */
10678: + int dontUseRhs0 = 0; /* If true, use of left-most RHS label is illegal */
10679: + const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */
10680: + char lhsused = 0; /* True if the LHS element has been used */
10681: + char lhsdirect; /* True if LHS writes directly into stack */
10682: + char used[MAXRHS]; /* True for each RHS element which is used */
10683: + char zLhs[50]; /* Convert the LHS symbol into this string */
10684: + char zOvwrt[900]; /* Comment that to allow LHS to overwrite RHS */
10685: +
10686: + for(i=0; i<rp->nrhs; i++) used[i] = 0;
10687: + lhsused = 0;
10688: +
10689: + if( rp->code==0 ){
10690: + static char newlinestr[2] = { '\n', '\0' };
10691: + rp->code = newlinestr;
10692: + rp->line = rp->ruleline;
10693: + rp->noCode = 1;
10694: + }else{
10695: + rp->noCode = 0;
10696: + }
10697: +
10698: +
10699: + if( rp->nrhs==0 ){
10700: + /* If there are no RHS symbols, then writing directly to the LHS is ok */
10701: + lhsdirect = 1;
10702: + }else if( rp->rhsalias[0]==0 ){
10703: + /* The left-most RHS symbol has no value. LHS direct is ok. But
10704: + ** we have to call the distructor on the RHS symbol first. */
10705: + lhsdirect = 1;
10706: + if( has_destructor(rp->rhs[0],lemp) ){
10707: + append_str(0,0,0,0);
10708: + append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
10709: + rp->rhs[0]->index,1-rp->nrhs);
10710: + rp->codePrefix = Strsafe(append_str(0,0,0,0));
10711: + rp->noCode = 0;
10712: + }
10713: + }else if( rp->lhsalias==0 ){
10714: + /* There is no LHS value symbol. */
10715: + lhsdirect = 1;
10716: + }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){
10717: + /* The LHS symbol and the left-most RHS symbol are the same, so
10718: + ** direct writing is allowed */
10719: + lhsdirect = 1;
10720: + lhsused = 1;
10721: + used[0] = 1;
10722: + if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){
10723: + ErrorMsg(lemp->filename,rp->ruleline,
10724: + "%s(%s) and %s(%s) share the same label but have "
10725: + "different datatypes.",
10726: + rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]);
10727: + lemp->errorcnt++;
10728: + }
10729: + }else{
10730: + lemon_sprintf(zOvwrt, "/*%s-overwrites-%s*/",
10731: + rp->lhsalias, rp->rhsalias[0]);
10732: + zSkip = strstr(rp->code, zOvwrt);
10733: + if( zSkip!=0 ){
10734: + /* The code contains a special comment that indicates that it is safe
10735: + ** for the LHS label to overwrite left-most RHS label. */
10736: + lhsdirect = 1;
10737: + }else{
10738: + lhsdirect = 0;
10739: + }
10740: + }
10741: + if( lhsdirect ){
10742: + sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
10743: + }else{
10744: + rc = 1;
10745: + sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
10746: + }
10747: +
10748: + append_str(0,0,0,0);
10749: +
10750: + /* This const cast is wrong but harmless, if we're careful. */
10751: + for(cp=(char *)rp->code; *cp; cp++){
10752: + if( cp==zSkip ){
10753: + append_str(zOvwrt,0,0,0);
10754: + cp += lemonStrlen(zOvwrt)-1;
10755: + dontUseRhs0 = 1;
10756: + continue;
10757: + }
10758: + if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){
10759: + char saved;
10760: + for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++);
10761: + saved = *xp;
10762: + *xp = 0;
10763: + if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
10764: + append_str(zLhs,0,0,0);
10765: + cp = xp;
10766: + lhsused = 1;
10767: + }else{
10768: + for(i=0; i<rp->nrhs; i++){
10769: + if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
10770: + if( i==0 && dontUseRhs0 ){
10771: + ErrorMsg(lemp->filename,rp->ruleline,
10772: + "Label %s used after '%s'.",
10773: + rp->rhsalias[0], zOvwrt);
10774: + lemp->errorcnt++;
10775: + }else if( cp!=rp->code && cp[-1]=='@' ){
10776: + /* If the argument is of the form @X then substituted
10777: + ** the token number of X, not the value of X */
10778: + append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
10779: + }else{
10780: + struct symbol *sp = rp->rhs[i];
10781: + int dtnum;
10782: + if( sp->type==MULTITERMINAL ){
10783: + dtnum = sp->subsym[0]->dtnum;
10784: + }else{
10785: + dtnum = sp->dtnum;
10786: + }
10787: + append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum);
10788: + }
10789: + cp = xp;
10790: + used[i] = 1;
10791: + break;
10792: + }
10793: + }
10794: + }
10795: + *xp = saved;
10796: + }
10797: + append_str(cp, 1, 0, 0);
10798: + } /* End loop */
10799: +
10800: + /* Main code generation completed */
10801: + cp = append_str(0,0,0,0);
10802: + if( cp && cp[0] ) rp->code = Strsafe(cp);
10803: + append_str(0,0,0,0);
10804: +
10805: + /* Check to make sure the LHS has been used */
10806: + if( rp->lhsalias && !lhsused ){
10807: + ErrorMsg(lemp->filename,rp->ruleline,
10808: + "Label \"%s\" for \"%s(%s)\" is never used.",
10809: + rp->lhsalias,rp->lhs->name,rp->lhsalias);
10810: + lemp->errorcnt++;
10811: + }
10812: +
10813: + /* Generate destructor code for RHS minor values which are not referenced.
10814: + ** Generate error messages for unused labels and duplicate labels.
10815: + */
10816: + for(i=0; i<rp->nrhs; i++){
10817: + if( rp->rhsalias[i] ){
10818: + if( i>0 ){
10819: + int j;
10820: + if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
10821: + ErrorMsg(lemp->filename,rp->ruleline,
10822: + "%s(%s) has the same label as the LHS but is not the left-most "
10823: + "symbol on the RHS.",
10824: + rp->rhs[i]->name, rp->rhsalias);
10825: + lemp->errorcnt++;
10826: + }
10827: + for(j=0; j<i; j++){
10828: + if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){
10829: + ErrorMsg(lemp->filename,rp->ruleline,
10830: + "Label %s used for multiple symbols on the RHS of a rule.",
10831: + rp->rhsalias[i]);
10832: + lemp->errorcnt++;
10833: + break;
10834: + }
10835: + }
10836: + }
10837: + if( !used[i] ){
10838: + ErrorMsg(lemp->filename,rp->ruleline,
10839: + "Label %s for \"%s(%s)\" is never used.",
10840: + rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
10841: + lemp->errorcnt++;
10842: + }
10843: + }else if( i>0 && has_destructor(rp->rhs[i],lemp) ){
10844: + append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
10845: + rp->rhs[i]->index,i-rp->nrhs+1);
10846: + }
10847: + }
10848: +
10849: + /* If unable to write LHS values directly into the stack, write the
10850: + ** saved LHS value now. */
10851: + if( lhsdirect==0 ){
10852: + append_str(" yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum);
10853: + append_str(zLhs, 0, 0, 0);
10854: + append_str(";\n", 0, 0, 0);
10855: + }
10856: +
10857: + /* Suffix code generation complete */
10858: + cp = append_str(0,0,0,0);
10859: + if( cp && cp[0] ){
10860: + rp->codeSuffix = Strsafe(cp);
10861: + rp->noCode = 0;
10862: + }
10863: +
10864: + return rc;
10865: +}
10866: +
10867: +/*
10868: +** Generate code which executes when the rule "rp" is reduced. Write
10869: +** the code to "out". Make sure lineno stays up-to-date.
10870: +*/
10871: +PRIVATE void emit_code(
10872: + FILE *out,
10873: + struct rule *rp,
10874: + struct lemon *lemp,
10875: + int *lineno
10876: +){
10877: + const char *cp;
10878: +
10879: + /* Setup code prior to the #line directive */
10880: + if( rp->codePrefix && rp->codePrefix[0] ){
10881: + fprintf(out, "{%s", rp->codePrefix);
10882: + for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
10883: + }
10884: +
10885: + /* Generate code to do the reduce action */
10886: + if( rp->code ){
10887: + if( !lemp->nolinenosflag ){
10888: + (*lineno)++;
10889: + tplt_linedir(out,rp->line,lemp->filename);
10890: + }
10891: + fprintf(out,"{%s",rp->code);
10892: + for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
10893: + fprintf(out,"}\n"); (*lineno)++;
10894: + if( !lemp->nolinenosflag ){
10895: + (*lineno)++;
10896: + tplt_linedir(out,*lineno,lemp->outname);
10897: + }
10898: + }
10899: +
10900: + /* Generate breakdown code that occurs after the #line directive */
10901: + if( rp->codeSuffix && rp->codeSuffix[0] ){
10902: + fprintf(out, "%s", rp->codeSuffix);
10903: + for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
10904: + }
10905: +
10906: + if( rp->codePrefix ){
10907: + fprintf(out, "}\n"); (*lineno)++;
10908: + }
10909: +
10910: + return;
10911: +}
10912: +
10913: +/*
10914: +** Print the definition of the union used for the parser's data stack.
10915: +** This union contains fields for every possible data type for tokens
10916: +** and nonterminals. In the process of computing and printing this
10917: +** union, also set the ".dtnum" field of every terminal and nonterminal
10918: +** symbol.
10919: +*/
10920: +void print_stack_union(
10921: + FILE *out, /* The output stream */
10922: + struct lemon *lemp, /* The main info structure for this parser */
10923: + int *plineno, /* Pointer to the line number */
10924: + int mhflag /* True if generating makeheaders output */
10925: +){
10926: + int lineno = *plineno; /* The line number of the output */
10927: + char **types; /* A hash table of datatypes */
10928: + int arraysize; /* Size of the "types" array */
10929: + int maxdtlength; /* Maximum length of any ".datatype" field. */
10930: + char *stddt; /* Standardized name for a datatype */
10931: + int i,j; /* Loop counters */
10932: + unsigned hash; /* For hashing the name of a type */
10933: + const char *name; /* Name of the parser */
10934: +
10935: + /* Allocate and initialize types[] and allocate stddt[] */
10936: + arraysize = lemp->nsymbol * 2;
10937: + types = (char**)calloc( arraysize, sizeof(char*) );
10938: + if( types==0 ){
10939: + fprintf(stderr,"Out of memory.\n");
10940: + exit(1);
10941: + }
10942: + for(i=0; i<arraysize; i++) types[i] = 0;
10943: + maxdtlength = 0;
10944: + if( lemp->vartype ){
10945: + maxdtlength = lemonStrlen(lemp->vartype);
10946: + }
10947: + for(i=0; i<lemp->nsymbol; i++){
10948: + int len;
10949: + struct symbol *sp = lemp->symbols[i];
10950: + if( sp->datatype==0 ) continue;
10951: + len = lemonStrlen(sp->datatype);
10952: + if( len>maxdtlength ) maxdtlength = len;
10953: + }
10954: + stddt = (char*)malloc( maxdtlength*2 + 1 );
10955: + if( stddt==0 ){
10956: + fprintf(stderr,"Out of memory.\n");
10957: + exit(1);
10958: + }
10959: +
10960: + /* Build a hash table of datatypes. The ".dtnum" field of each symbol
10961: + ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
10962: + ** used for terminal symbols. If there is no %default_type defined then
10963: + ** 0 is also used as the .dtnum value for nonterminals which do not specify
10964: + ** a datatype using the %type directive.
10965: + */
10966: + for(i=0; i<lemp->nsymbol; i++){
10967: + struct symbol *sp = lemp->symbols[i];
10968: + char *cp;
10969: + if( sp==lemp->errsym ){
10970: + sp->dtnum = arraysize+1;
10971: + continue;
10972: + }
10973: + if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
10974: + sp->dtnum = 0;
10975: + continue;
10976: + }
10977: + cp = sp->datatype;
10978: + if( cp==0 ) cp = lemp->vartype;
10979: + j = 0;
10980: + while( ISSPACE(*cp) ) cp++;
10981: + while( *cp ) stddt[j++] = *cp++;
10982: + while( j>0 && ISSPACE(stddt[j-1]) ) j--;
10983: + stddt[j] = 0;
10984: + if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){
10985: + sp->dtnum = 0;
10986: + continue;
10987: + }
10988: + hash = 0;
10989: + for(j=0; stddt[j]; j++){
10990: + hash = hash*53 + stddt[j];
10991: + }
10992: + hash = (hash & 0x7fffffff)%arraysize;
10993: + while( types[hash] ){
10994: + if( strcmp(types[hash],stddt)==0 ){
10995: + sp->dtnum = hash + 1;
10996: + break;
10997: + }
10998: + hash++;
10999: + if( hash>=(unsigned)arraysize ) hash = 0;
11000: + }
11001: + if( types[hash]==0 ){
11002: + sp->dtnum = hash + 1;
11003: + types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
11004: + if( types[hash]==0 ){
11005: + fprintf(stderr,"Out of memory.\n");
11006: + exit(1);
11007: + }
11008: + lemon_strcpy(types[hash],stddt);
11009: + }
11010: + }
11011: +
11012: + /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
11013: + name = lemp->name ? lemp->name : "Parse";
11014: + lineno = *plineno;
11015: + if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
11016: + fprintf(out,"#define %sTOKENTYPE %s\n",name,
11017: + lemp->tokentype?lemp->tokentype:"void*"); lineno++;
11018: + if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
11019: + fprintf(out,"typedef union {\n"); lineno++;
11020: + fprintf(out," int yyinit;\n"); lineno++;
11021: + fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
11022: + for(i=0; i<arraysize; i++){
11023: + if( types[i]==0 ) continue;
11024: + fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
11025: + free(types[i]);
11026: + }
11027: + if( lemp->errsym->useCnt ){
11028: + fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
11029: + }
11030: + free(stddt);
11031: + free(types);
11032: + fprintf(out,"} YYMINORTYPE;\n"); lineno++;
11033: + *plineno = lineno;
11034: +}
11035: +
11036: +/*
11037: +** Return the name of a C datatype able to represent values between
11038: +** lwr and upr, inclusive. If pnByte!=NULL then also write the sizeof
11039: +** for that type (1, 2, or 4) into *pnByte.
11040: +*/
11041: +static const char *minimum_size_type(int lwr, int upr, int *pnByte){
11042: + const char *zType = "int";
11043: + int nByte = 4;
11044: + if( lwr>=0 ){
11045: + if( upr<=255 ){
11046: + zType = "unsigned char";
11047: + nByte = 1;
11048: + }else if( upr<65535 ){
11049: + zType = "unsigned short int";
11050: + nByte = 2;
11051: + }else{
11052: + zType = "unsigned int";
11053: + nByte = 4;
11054: + }
11055: + }else if( lwr>=-127 && upr<=127 ){
11056: + zType = "signed char";
11057: + nByte = 1;
11058: + }else if( lwr>=-32767 && upr<32767 ){
11059: + zType = "short";
11060: + nByte = 2;
11061: + }
11062: + if( pnByte ) *pnByte = nByte;
11063: + return zType;
11064: +}
11065: +
11066: +/*
11067: +** Each state contains a set of token transaction and a set of
11068: +** nonterminal transactions. Each of these sets makes an instance
11069: +** of the following structure. An array of these structures is used
11070: +** to order the creation of entries in the yy_action[] table.
11071: +*/
11072: +struct axset {
11073: + struct state *stp; /* A pointer to a state */
11074: + int isTkn; /* True to use tokens. False for non-terminals */
11075: + int nAction; /* Number of actions */
11076: + int iOrder; /* Original order of action sets */
11077: +};
11078: +
11079: +/*
11080: +** Compare to axset structures for sorting purposes
11081: +*/
11082: +static int axset_compare(const void *a, const void *b){
11083: + struct axset *p1 = (struct axset*)a;
11084: + struct axset *p2 = (struct axset*)b;
11085: + int c;
11086: + c = p2->nAction - p1->nAction;
11087: + if( c==0 ){
11088: + c = p1->iOrder - p2->iOrder;
11089: + }
11090: + assert( c!=0 || p1==p2 );
11091: + return c;
11092: +}
11093: +
11094: +/*
11095: +** Write text on "out" that describes the rule "rp".
11096: +*/
11097: +static void writeRuleText(FILE *out, struct rule *rp){
11098: + int j;
11099: + fprintf(out,"%s ::=", rp->lhs->name);
11100: + for(j=0; j<rp->nrhs; j++){
11101: + struct symbol *sp = rp->rhs[j];
11102: + if( sp->type!=MULTITERMINAL ){
11103: + fprintf(out," %s", sp->name);
11104: + }else{
11105: + int k;
11106: + fprintf(out," %s", sp->subsym[0]->name);
11107: + for(k=1; k<sp->nsubsym; k++){
11108: + fprintf(out,"|%s",sp->subsym[k]->name);
11109: + }
11110: + }
11111: + }
11112: +}
11113: +
11114: +
11115: +/* Generate C source code for the parser */
11116: +void ReportTable(
11117: + struct lemon *lemp,
11118: + int mhflag /* Output in makeheaders format if true */
11119: +){
11120: + FILE *out, *in;
11121: + char line[LINESIZE];
11122: + int lineno;
11123: + struct state *stp;
11124: + struct action *ap;
11125: + struct rule *rp;
11126: + struct acttab *pActtab;
11127: + int i, j, n, sz;
11128: + int szActionType; /* sizeof(YYACTIONTYPE) */
11129: + int szCodeType; /* sizeof(YYCODETYPE) */
11130: + const char *name;
11131: + int mnTknOfst, mxTknOfst;
11132: + int mnNtOfst, mxNtOfst;
11133: + struct axset *ax;
11134: +
11135: + in = tplt_open(lemp);
11136: + if( in==0 ) return;
11137: + out = file_open(lemp,".c","wb");
11138: + if( out==0 ){
11139: + fclose(in);
11140: + return;
11141: + }
11142: + lineno = 1;
11143: + tplt_xfer(lemp->name,in,out,&lineno);
11144: +
11145: + /* Generate the include code, if any */
11146: + tplt_print(out,lemp,lemp->include,&lineno);
11147: + if( mhflag ){
11148: + char *incName = file_makename(lemp, ".h");
11149: + fprintf(out,"#include \"%s\"\n", incName); lineno++;
11150: + free(incName);
11151: + }
11152: + tplt_xfer(lemp->name,in,out,&lineno);
11153: +
11154: + /* Generate #defines for all tokens */
11155: + if( mhflag ){
11156: + const char *prefix;
11157: + fprintf(out,"#if INTERFACE\n"); lineno++;
11158: + if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
11159: + else prefix = "";
11160: + for(i=1; i<lemp->nterminal; i++){
11161: + fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
11162: + lineno++;
11163: + }
11164: + fprintf(out,"#endif\n"); lineno++;
11165: + }
11166: + tplt_xfer(lemp->name,in,out,&lineno);
11167: +
11168: + /* Generate the defines */
11169: + fprintf(out,"#define YYCODETYPE %s\n",
11170: + minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++;
11171: + fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
11172: + fprintf(out,"#define YYACTIONTYPE %s\n",
11173: + minimum_size_type(0,lemp->nstate+lemp->nrule*2+5,&szActionType)); lineno++;
11174: + if( lemp->wildcard ){
11175: + fprintf(out,"#define YYWILDCARD %d\n",
11176: + lemp->wildcard->index); lineno++;
11177: + }
11178: + print_stack_union(out,lemp,&lineno,mhflag);
11179: + fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++;
11180: + if( lemp->stacksize ){
11181: + fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
11182: + }else{
11183: + fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
11184: + }
11185: + fprintf(out, "#endif\n"); lineno++;
11186: + if( mhflag ){
11187: + fprintf(out,"#if INTERFACE\n"); lineno++;
11188: + }
11189: + name = lemp->name ? lemp->name : "Parse";
11190: + if( lemp->arg && lemp->arg[0] ){
11191: + i = lemonStrlen(lemp->arg);
11192: + while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--;
11193: + while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
11194: + fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
11195: + fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
11196: + fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
11197: + name,lemp->arg,&lemp->arg[i]); lineno++;
11198: + fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
11199: + name,&lemp->arg[i],&lemp->arg[i]); lineno++;
11200: + }else{
11201: + fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
11202: + fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
11203: + fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
11204: + fprintf(out,"#define %sARG_STORE\n",name); lineno++;
11205: + }
11206: + if( mhflag ){
11207: + fprintf(out,"#endif\n"); lineno++;
11208: + }
11209: + if( lemp->errsym->useCnt ){
11210: + fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
11211: + fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
11212: + }
11213: + if( lemp->has_fallback ){
11214: + fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
11215: + }
11216: +
11217: + /* Compute the action table, but do not output it yet. The action
11218: + ** table must be computed before generating the YYNSTATE macro because
11219: + ** we need to know how many states can be eliminated.
11220: + */
11221: + ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
11222: + if( ax==0 ){
11223: + fprintf(stderr,"malloc failed\n");
11224: + exit(1);
11225: + }
11226: + for(i=0; i<lemp->nxstate; i++){
11227: + stp = lemp->sorted[i];
11228: + ax[i*2].stp = stp;
11229: + ax[i*2].isTkn = 1;
11230: + ax[i*2].nAction = stp->nTknAct;
11231: + ax[i*2+1].stp = stp;
11232: + ax[i*2+1].isTkn = 0;
11233: + ax[i*2+1].nAction = stp->nNtAct;
11234: + }
11235: + mxTknOfst = mnTknOfst = 0;
11236: + mxNtOfst = mnNtOfst = 0;
11237: + /* In an effort to minimize the action table size, use the heuristic
11238: + ** of placing the largest action sets first */
11239: + for(i=0; i<lemp->nxstate*2; i++) ax[i].iOrder = i;
11240: + qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare);
11241: + pActtab = acttab_alloc();
11242: + for(i=0; i<lemp->nxstate*2 && ax[i].nAction>0; i++){
11243: + stp = ax[i].stp;
11244: + if( ax[i].isTkn ){
11245: + for(ap=stp->ap; ap; ap=ap->next){
11246: + int action;
11247: + if( ap->sp->index>=lemp->nterminal ) continue;
11248: + action = compute_action(lemp, ap);
11249: + if( action<0 ) continue;
11250: + acttab_action(pActtab, ap->sp->index, action);
11251: + }
11252: + stp->iTknOfst = acttab_insert(pActtab);
11253: + if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
11254: + if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
11255: + }else{
11256: + for(ap=stp->ap; ap; ap=ap->next){
11257: + int action;
11258: + if( ap->sp->index<lemp->nterminal ) continue;
11259: + if( ap->sp->index==lemp->nsymbol ) continue;
11260: + action = compute_action(lemp, ap);
11261: + if( action<0 ) continue;
11262: + acttab_action(pActtab, ap->sp->index, action);
11263: + }
11264: + stp->iNtOfst = acttab_insert(pActtab);
11265: + if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
11266: + if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
11267: + }
11268: +#if 0 /* Uncomment for a trace of how the yy_action[] table fills out */
11269: + { int jj, nn;
11270: + for(jj=nn=0; jj<pActtab->nAction; jj++){
11271: + if( pActtab->aAction[jj].action<0 ) nn++;
11272: + }
11273: + printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n",
11274: + i, stp->statenum, ax[i].isTkn ? "Token" : "Var ",
11275: + ax[i].nAction, pActtab->nAction, nn);
11276: + }
11277: +#endif
11278: + }
11279: + free(ax);
11280: +
11281: + /* Mark rules that are actually used for reduce actions after all
11282: + ** optimizations have been applied
11283: + */
11284: + for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE;
11285: + for(i=0; i<lemp->nxstate; i++){
11286: + for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
11287: + if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){
11288: + ap->x.rp->doesReduce = i;
11289: + }
11290: + }
11291: + }
11292: +
11293: + /* Finish rendering the constants now that the action table has
11294: + ** been computed */
11295: + fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
11296: + fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
11297: + fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++;
11298: + fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++;
11299: + i = lemp->nstate + lemp->nrule;
11300: + fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++;
11301: + fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++;
11302: + i = lemp->nstate + lemp->nrule*2;
11303: + fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
11304: + fprintf(out,"#define YY_ERROR_ACTION %d\n", i); lineno++;
11305: + fprintf(out,"#define YY_ACCEPT_ACTION %d\n", i+1); lineno++;
11306: + fprintf(out,"#define YY_NO_ACTION %d\n", i+2); lineno++;
11307: + tplt_xfer(lemp->name,in,out,&lineno);
11308: +
11309: + /* Now output the action table and its associates:
11310: + **
11311: + ** yy_action[] A single table containing all actions.
11312: + ** yy_lookahead[] A table containing the lookahead for each entry in
11313: + ** yy_action. Used to detect hash collisions.
11314: + ** yy_shift_ofst[] For each state, the offset into yy_action for
11315: + ** shifting terminals.
11316: + ** yy_reduce_ofst[] For each state, the offset into yy_action for
11317: + ** shifting non-terminals after a reduce.
11318: + ** yy_default[] Default action for each state.
11319: + */
11320: +
11321: + /* Output the yy_action table */
11322: + lemp->nactiontab = n = acttab_size(pActtab);
11323: + lemp->tablesize += n*szActionType;
11324: + fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
11325: + fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
11326: + for(i=j=0; i<n; i++){
11327: + int action = acttab_yyaction(pActtab, i);
11328: + if( action<0 ) action = lemp->nstate + lemp->nrule + 2;
11329: + if( j==0 ) fprintf(out," /* %5d */ ", i);
11330: + fprintf(out, " %4d,", action);
11331: + if( j==9 || i==n-1 ){
11332: + fprintf(out, "\n"); lineno++;
11333: + j = 0;
11334: + }else{
11335: + j++;
11336: + }
11337: + }
11338: + fprintf(out, "};\n"); lineno++;
11339: +
11340: + /* Output the yy_lookahead table */
11341: + lemp->tablesize += n*szCodeType;
11342: + fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
11343: + for(i=j=0; i<n; i++){
11344: + int la = acttab_yylookahead(pActtab, i);
11345: + if( la<0 ) la = lemp->nsymbol;
11346: + if( j==0 ) fprintf(out," /* %5d */ ", i);
11347: + fprintf(out, " %4d,", la);
11348: + if( j==9 || i==n-1 ){
11349: + fprintf(out, "\n"); lineno++;
11350: + j = 0;
11351: + }else{
11352: + j++;
11353: + }
11354: + }
11355: + fprintf(out, "};\n"); lineno++;
11356: +
11357: + /* Output the yy_shift_ofst[] table */
11358: + n = lemp->nxstate;
11359: + while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
11360: + fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++;
11361: + fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
11362: + fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
11363: + fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
11364: + fprintf(out, "static const %s yy_shift_ofst[] = {\n",
11365: + minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz));
11366: + lineno++;
11367: + lemp->tablesize += n*sz;
11368: + for(i=j=0; i<n; i++){
11369: + int ofst;
11370: + stp = lemp->sorted[i];
11371: + ofst = stp->iTknOfst;
11372: + if( ofst==NO_OFFSET ) ofst = lemp->nactiontab;
11373: + if( j==0 ) fprintf(out," /* %5d */ ", i);
11374: + fprintf(out, " %4d,", ofst);
11375: + if( j==9 || i==n-1 ){
11376: + fprintf(out, "\n"); lineno++;
11377: + j = 0;
11378: + }else{
11379: + j++;
11380: + }
11381: + }
11382: + fprintf(out, "};\n"); lineno++;
11383: +
11384: + /* Output the yy_reduce_ofst[] table */
11385: + fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
11386: + n = lemp->nxstate;
11387: + while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
11388: + fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
11389: + fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++;
11390: + fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++;
11391: + fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
11392: + minimum_size_type(mnNtOfst-1, mxNtOfst, &sz)); lineno++;
11393: + lemp->tablesize += n*sz;
11394: + for(i=j=0; i<n; i++){
11395: + int ofst;
11396: + stp = lemp->sorted[i];
11397: + ofst = stp->iNtOfst;
11398: + if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
11399: + if( j==0 ) fprintf(out," /* %5d */ ", i);
11400: + fprintf(out, " %4d,", ofst);
11401: + if( j==9 || i==n-1 ){
11402: + fprintf(out, "\n"); lineno++;
11403: + j = 0;
11404: + }else{
11405: + j++;
11406: + }
11407: + }
11408: + fprintf(out, "};\n"); lineno++;
11409: +
11410: + /* Output the default action table */
11411: + fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
11412: + n = lemp->nxstate;
11413: + lemp->tablesize += n*szActionType;
11414: + for(i=j=0; i<n; i++){
11415: + stp = lemp->sorted[i];
11416: + if( j==0 ) fprintf(out," /* %5d */ ", i);
11417: + fprintf(out, " %4d,", stp->iDfltReduce+lemp->nstate+lemp->nrule);
11418: + if( j==9 || i==n-1 ){
11419: + fprintf(out, "\n"); lineno++;
11420: + j = 0;
11421: + }else{
11422: + j++;
11423: + }
11424: + }
11425: + fprintf(out, "};\n"); lineno++;
11426: + tplt_xfer(lemp->name,in,out,&lineno);
11427: +
11428: + /* Generate the table of fallback tokens.
11429: + */
11430: + if( lemp->has_fallback ){
11431: + int mx = lemp->nterminal - 1;
11432: + while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
11433: + lemp->tablesize += (mx+1)*szCodeType;
11434: + for(i=0; i<=mx; i++){
11435: + struct symbol *p = lemp->symbols[i];
11436: + if( p->fallback==0 ){
11437: + fprintf(out, " 0, /* %10s => nothing */\n", p->name);
11438: + }else{
11439: + fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
11440: + p->name, p->fallback->name);
11441: + }
11442: + lineno++;
11443: + }
11444: + }
11445: + tplt_xfer(lemp->name, in, out, &lineno);
11446: +
11447: + /* Generate a table containing the symbolic name of every symbol
11448: + */
11449: + for(i=0; i<lemp->nsymbol; i++){
11450: + lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
11451: + fprintf(out," %-15s",line);
11452: + if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
11453: + }
11454: + if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
11455: + tplt_xfer(lemp->name,in,out,&lineno);
11456: +
11457: + /* Generate a table containing a text string that describes every
11458: + ** rule in the rule set of the grammar. This information is used
11459: + ** when tracing REDUCE actions.
11460: + */
11461: + for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
11462: + assert( rp->iRule==i );
11463: + fprintf(out," /* %3d */ \"", i);
11464: + writeRuleText(out, rp);
11465: + fprintf(out,"\",\n"); lineno++;
11466: + }
11467: + tplt_xfer(lemp->name,in,out,&lineno);
11468: +
11469: + /* Generate code which executes every time a symbol is popped from
11470: + ** the stack while processing errors or while destroying the parser.
11471: + ** (In other words, generate the %destructor actions)
11472: + */
11473: + if( lemp->tokendest ){
11474: + int once = 1;
11475: + for(i=0; i<lemp->nsymbol; i++){
11476: + struct symbol *sp = lemp->symbols[i];
11477: + if( sp==0 || sp->type!=TERMINAL ) continue;
11478: + if( once ){
11479: + fprintf(out, " /* TERMINAL Destructor */\n"); lineno++;
11480: + once = 0;
11481: + }
11482: + fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
11483: + }
11484: + for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
11485: + if( i<lemp->nsymbol ){
11486: + emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
11487: + fprintf(out," break;\n"); lineno++;
11488: + }
11489: + }
11490: + if( lemp->vardest ){
11491: + struct symbol *dflt_sp = 0;
11492: + int once = 1;
11493: + for(i=0; i<lemp->nsymbol; i++){
11494: + struct symbol *sp = lemp->symbols[i];
11495: + if( sp==0 || sp->type==TERMINAL ||
11496: + sp->index<=0 || sp->destructor!=0 ) continue;
11497: + if( once ){
11498: + fprintf(out, " /* Default NON-TERMINAL Destructor */\n"); lineno++;
11499: + once = 0;
11500: + }
11501: + fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
11502: + dflt_sp = sp;
11503: + }
11504: + if( dflt_sp!=0 ){
11505: + emit_destructor_code(out,dflt_sp,lemp,&lineno);
11506: + }
11507: + fprintf(out," break;\n"); lineno++;
11508: + }
11509: + for(i=0; i<lemp->nsymbol; i++){
11510: + struct symbol *sp = lemp->symbols[i];
11511: + if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
11512: + if( sp->destLineno<0 ) continue; /* Already emitted */
11513: + fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
11514: +
11515: + /* Combine duplicate destructors into a single case */
11516: + for(j=i+1; j<lemp->nsymbol; j++){
11517: + struct symbol *sp2 = lemp->symbols[j];
11518: + if( sp2 && sp2->type!=TERMINAL && sp2->destructor
11519: + && sp2->dtnum==sp->dtnum
11520: + && strcmp(sp->destructor,sp2->destructor)==0 ){
11521: + fprintf(out," case %d: /* %s */\n",
11522: + sp2->index, sp2->name); lineno++;
11523: + sp2->destLineno = -1; /* Avoid emitting this destructor again */
11524: + }
11525: + }
11526: +
11527: + emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
11528: + fprintf(out," break;\n"); lineno++;
11529: + }
11530: + tplt_xfer(lemp->name,in,out,&lineno);
11531: +
11532: + /* Generate code which executes whenever the parser stack overflows */
11533: + tplt_print(out,lemp,lemp->overflow,&lineno);
11534: + tplt_xfer(lemp->name,in,out,&lineno);
11535: +
11536: + /* Generate the table of rule information
11537: + **
11538: + ** Note: This code depends on the fact that rules are number
11539: + ** sequentually beginning with 0.
11540: + */
11541: + for(rp=lemp->rule; rp; rp=rp->next){
11542: + fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
11543: + }
11544: + tplt_xfer(lemp->name,in,out,&lineno);
11545: +
11546: + /* Generate code which execution during each REDUCE action */
11547: + i = 0;
11548: + for(rp=lemp->rule; rp; rp=rp->next){
11549: + i += translate_code(lemp, rp);
11550: + }
11551: + if( i ){
11552: + fprintf(out," YYMINORTYPE yylhsminor;\n"); lineno++;
11553: + }
11554: + /* First output rules other than the default: rule */
11555: + for(rp=lemp->rule; rp; rp=rp->next){
11556: + struct rule *rp2; /* Other rules with the same action */
11557: + if( rp->codeEmitted ) continue;
11558: + if( rp->noCode ){
11559: + /* No C code actions, so this will be part of the "default:" rule */
11560: + continue;
11561: + }
11562: + fprintf(out," case %d: /* ", rp->iRule);
11563: + writeRuleText(out, rp);
11564: + fprintf(out, " */\n"); lineno++;
11565: + for(rp2=rp->next; rp2; rp2=rp2->next){
11566: + if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix
11567: + && rp2->codeSuffix==rp->codeSuffix ){
11568: + fprintf(out," case %d: /* ", rp2->iRule);
11569: + writeRuleText(out, rp2);
11570: + fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
11571: + rp2->codeEmitted = 1;
11572: + }
11573: + }
11574: + emit_code(out,rp,lemp,&lineno);
11575: + fprintf(out," break;\n"); lineno++;
11576: + rp->codeEmitted = 1;
11577: + }
11578: + /* Finally, output the default: rule. We choose as the default: all
11579: + ** empty actions. */
11580: + fprintf(out," default:\n"); lineno++;
11581: + for(rp=lemp->rule; rp; rp=rp->next){
11582: + if( rp->codeEmitted ) continue;
11583: + assert( rp->noCode );
11584: + fprintf(out," /* (%d) ", rp->iRule);
11585: + writeRuleText(out, rp);
11586: + if( rp->doesReduce ){
11587: + fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
11588: + }else{
11589: + fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n",
11590: + rp->iRule); lineno++;
11591: + }
11592: + }
11593: + fprintf(out," break;\n"); lineno++;
11594: + tplt_xfer(lemp->name,in,out,&lineno);
11595: +
11596: + /* Generate code which executes if a parse fails */
11597: + tplt_print(out,lemp,lemp->failure,&lineno);
11598: + tplt_xfer(lemp->name,in,out,&lineno);
11599: +
11600: + /* Generate code which executes when a syntax error occurs */
11601: + tplt_print(out,lemp,lemp->error,&lineno);
11602: + tplt_xfer(lemp->name,in,out,&lineno);
11603: +
11604: + /* Generate code which executes when the parser accepts its input */
11605: + tplt_print(out,lemp,lemp->accept,&lineno);
11606: + tplt_xfer(lemp->name,in,out,&lineno);
11607: +
11608: + /* Append any addition code the user desires */
11609: + tplt_print(out,lemp,lemp->extracode,&lineno);
11610: +
11611: + fclose(in);
11612: + fclose(out);
11613: + return;
11614: +}
11615: +
11616: +/* Generate a header file for the parser */
11617: +void ReportHeader(struct lemon *lemp)
11618: +{
11619: + FILE *out, *in;
11620: + const char *prefix;
11621: + char line[LINESIZE];
11622: + char pattern[LINESIZE];
11623: + int i;
11624: +
11625: + if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
11626: + else prefix = "";
11627: + in = file_open(lemp,".h","rb");
11628: + if( in ){
11629: + int nextChar;
11630: + for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
11631: + lemon_sprintf(pattern,"#define %s%-30s %3d\n",
11632: + prefix,lemp->symbols[i]->name,i);
11633: + if( strcmp(line,pattern) ) break;
11634: + }
11635: + nextChar = fgetc(in);
11636: + fclose(in);
11637: + if( i==lemp->nterminal && nextChar==EOF ){
11638: + /* No change in the file. Don't rewrite it. */
11639: + return;
11640: + }
11641: + }
11642: + out = file_open(lemp,".h","wb");
11643: + if( out ){
11644: + for(i=1; i<lemp->nterminal; i++){
11645: + fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i);
11646: + }
11647: + fclose(out);
11648: + }
11649: + return;
11650: +}
11651: +
11652: +/* Reduce the size of the action tables, if possible, by making use
11653: +** of defaults.
11654: +**
11655: +** In this version, we take the most frequent REDUCE action and make
11656: +** it the default. Except, there is no default if the wildcard token
11657: +** is a possible look-ahead.
11658: +*/
11659: +void CompressTables(struct lemon *lemp)
11660: +{
11661: + struct state *stp;
11662: + struct action *ap, *ap2, *nextap;
11663: + struct rule *rp, *rp2, *rbest;
11664: + int nbest, n;
11665: + int i;
11666: + int usesWildcard;
11667: +
11668: + for(i=0; i<lemp->nstate; i++){
11669: + stp = lemp->sorted[i];
11670: + nbest = 0;
11671: + rbest = 0;
11672: + usesWildcard = 0;
11673: +
11674: + for(ap=stp->ap; ap; ap=ap->next){
11675: + if( ap->type==SHIFT && ap->sp==lemp->wildcard ){
11676: + usesWildcard = 1;
11677: + }
11678: + if( ap->type!=REDUCE ) continue;
11679: + rp = ap->x.rp;
11680: + if( rp->lhsStart ) continue;
11681: + if( rp==rbest ) continue;
11682: + n = 1;
11683: + for(ap2=ap->next; ap2; ap2=ap2->next){
11684: + if( ap2->type!=REDUCE ) continue;
11685: + rp2 = ap2->x.rp;
11686: + if( rp2==rbest ) continue;
11687: + if( rp2==rp ) n++;
11688: + }
11689: + if( n>nbest ){
11690: + nbest = n;
11691: + rbest = rp;
11692: + }
11693: + }
11694: +
11695: + /* Do not make a default if the number of rules to default
11696: + ** is not at least 1 or if the wildcard token is a possible
11697: + ** lookahead.
11698: + */
11699: + if( nbest<1 || usesWildcard ) continue;
11700: +
11701: +
11702: + /* Combine matching REDUCE actions into a single default */
11703: + for(ap=stp->ap; ap; ap=ap->next){
11704: + if( ap->type==REDUCE && ap->x.rp==rbest ) break;
11705: + }
11706: + assert( ap );
11707: + ap->sp = Symbol_new("{default}");
11708: + for(ap=ap->next; ap; ap=ap->next){
11709: + if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
11710: + }
11711: + stp->ap = Action_sort(stp->ap);
11712: +
11713: + for(ap=stp->ap; ap; ap=ap->next){
11714: + if( ap->type==SHIFT ) break;
11715: + if( ap->type==REDUCE && ap->x.rp!=rbest ) break;
11716: + }
11717: + if( ap==0 ){
11718: + stp->autoReduce = 1;
11719: + stp->pDfltReduce = rbest;
11720: + }
11721: + }
11722: +
11723: + /* Make a second pass over all states and actions. Convert
11724: + ** every action that is a SHIFT to an autoReduce state into
11725: + ** a SHIFTREDUCE action.
11726: + */
11727: + for(i=0; i<lemp->nstate; i++){
11728: + stp = lemp->sorted[i];
11729: + for(ap=stp->ap; ap; ap=ap->next){
11730: + struct state *pNextState;
11731: + if( ap->type!=SHIFT ) continue;
11732: + pNextState = ap->x.stp;
11733: + if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){
11734: + ap->type = SHIFTREDUCE;
11735: + ap->x.rp = pNextState->pDfltReduce;
11736: + }
11737: + }
11738: + }
11739: +
11740: + /* If a SHIFTREDUCE action specifies a rule that has a single RHS term
11741: + ** (meaning that the SHIFTREDUCE will land back in the state where it
11742: + ** started) and if there is no C-code associated with the reduce action,
11743: + ** then we can go ahead and convert the action to be the same as the
11744: + ** action for the RHS of the rule.
11745: + */
11746: + for(i=0; i<lemp->nstate; i++){
11747: + stp = lemp->sorted[i];
11748: + for(ap=stp->ap; ap; ap=nextap){
11749: + nextap = ap->next;
11750: + if( ap->type!=SHIFTREDUCE ) continue;
11751: + rp = ap->x.rp;
11752: + if( rp->noCode==0 ) continue;
11753: + if( rp->nrhs!=1 ) continue;
11754: +#if 1
11755: + /* Only apply this optimization to non-terminals. It would be OK to
11756: + ** apply it to terminal symbols too, but that makes the parser tables
11757: + ** larger. */
11758: + if( ap->sp->index<lemp->nterminal ) continue;
11759: +#endif
11760: + /* If we reach this point, it means the optimization can be applied */
11761: + nextap = ap;
11762: + for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){}
11763: + assert( ap2!=0 );
11764: + ap->spOpt = ap2->sp;
11765: + ap->type = ap2->type;
11766: + ap->x = ap2->x;
11767: + }
11768: + }
11769: +}
11770: +
11771: +
11772: +/*
11773: +** Compare two states for sorting purposes. The smaller state is the
11774: +** one with the most non-terminal actions. If they have the same number
11775: +** of non-terminal actions, then the smaller is the one with the most
11776: +** token actions.
11777: +*/
11778: +static int stateResortCompare(const void *a, const void *b){
11779: + const struct state *pA = *(const struct state**)a;
11780: + const struct state *pB = *(const struct state**)b;
11781: + int n;
11782: +
11783: + n = pB->nNtAct - pA->nNtAct;
11784: + if( n==0 ){
11785: + n = pB->nTknAct - pA->nTknAct;
11786: + if( n==0 ){
11787: + n = pB->statenum - pA->statenum;
11788: + }
11789: + }
11790: + assert( n!=0 );
11791: + return n;
11792: +}
11793: +
11794: +
11795: +/*
11796: +** Renumber and resort states so that states with fewer choices
11797: +** occur at the end. Except, keep state 0 as the first state.
11798: +*/
11799: +void ResortStates(struct lemon *lemp)
11800: +{
11801: + int i;
11802: + struct state *stp;
11803: + struct action *ap;
11804: +
11805: + for(i=0; i<lemp->nstate; i++){
11806: + stp = lemp->sorted[i];
11807: + stp->nTknAct = stp->nNtAct = 0;
11808: + stp->iDfltReduce = lemp->nrule; /* Init dflt action to "syntax error" */
11809: + stp->iTknOfst = NO_OFFSET;
11810: + stp->iNtOfst = NO_OFFSET;
11811: + for(ap=stp->ap; ap; ap=ap->next){
11812: + int iAction = compute_action(lemp,ap);
11813: + if( iAction>=0 ){
11814: + if( ap->sp->index<lemp->nterminal ){
11815: + stp->nTknAct++;
11816: + }else if( ap->sp->index<lemp->nsymbol ){
11817: + stp->nNtAct++;
11818: + }else{
11819: + assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp );
11820: + stp->iDfltReduce = iAction - lemp->nstate - lemp->nrule;
11821: + }
11822: + }
11823: + }
11824: + }
11825: + qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]),
11826: + stateResortCompare);
11827: + for(i=0; i<lemp->nstate; i++){
11828: + lemp->sorted[i]->statenum = i;
11829: + }
11830: + lemp->nxstate = lemp->nstate;
11831: + while( lemp->nxstate>1 && lemp->sorted[lemp->nxstate-1]->autoReduce ){
11832: + lemp->nxstate--;
11833: + }
11834: +}
11835: +
11836: +
11837: +/***************** From the file "set.c" ************************************/
11838: +/*
11839: +** Set manipulation routines for the LEMON parser generator.
11840: +*/
11841: +
11842: +static int size = 0;
11843: +
11844: +/* Set the set size */
11845: +void SetSize(int n)
11846: +{
11847: + size = n+1;
11848: +}
11849: +
11850: +/* Allocate a new set */
11851: +char *SetNew(){
11852: + char *s;
11853: + s = (char*)calloc( size, 1);
11854: + if( s==0 ){
11855: + extern void memory_error();
11856: + memory_error();
11857: + }
11858: + return s;
11859: +}
11860: +
11861: +/* Deallocate a set */
11862: +void SetFree(char *s)
11863: +{
11864: + free(s);
11865: +}
11866: +
11867: +/* Add a new element to the set. Return TRUE if the element was added
11868: +** and FALSE if it was already there. */
11869: +int SetAdd(char *s, int e)
11870: +{
11871: + int rv;
11872: + assert( e>=0 && e<size );
11873: + rv = s[e];
11874: + s[e] = 1;
11875: + return !rv;
11876: +}
11877: +
11878: +/* Add every element of s2 to s1. Return TRUE if s1 changes. */
11879: +int SetUnion(char *s1, char *s2)
11880: +{
11881: + int i, progress;
11882: + progress = 0;
11883: + for(i=0; i<size; i++){
11884: + if( s2[i]==0 ) continue;
11885: + if( s1[i]==0 ){
11886: + progress = 1;
11887: + s1[i] = 1;
11888: + }
11889: + }
11890: + return progress;
11891: +}
11892: +/********************** From the file "table.c" ****************************/
11893: +/*
11894: +** All code in this file has been automatically generated
11895: +** from a specification in the file
11896: +** "table.q"
11897: +** by the associative array code building program "aagen".
11898: +** Do not edit this file! Instead, edit the specification
11899: +** file, then rerun aagen.
11900: +*/
11901: +/*
11902: +** Code for processing tables in the LEMON parser generator.
11903: +*/
11904: +
11905: +PRIVATE unsigned strhash(const char *x)
11906: +{
11907: + unsigned h = 0;
11908: + while( *x ) h = h*13 + *(x++);
11909: + return h;
11910: +}
11911: +
11912: +/* Works like strdup, sort of. Save a string in malloced memory, but
11913: +** keep strings in a table so that the same string is not in more
11914: +** than one place.
11915: +*/
11916: +const char *Strsafe(const char *y)
11917: +{
11918: + const char *z;
11919: + char *cpy;
11920: +
11921: + if( y==0 ) return 0;
11922: + z = Strsafe_find(y);
11923: + if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
11924: + lemon_strcpy(cpy,y);
11925: + z = cpy;
11926: + Strsafe_insert(z);
11927: + }
11928: + MemoryCheck(z);
11929: + return z;
11930: +}
11931: +
11932: +/* There is one instance of the following structure for each
11933: +** associative array of type "x1".
11934: +*/
11935: +struct s_x1 {
11936: + int size; /* The number of available slots. */
11937: + /* Must be a power of 2 greater than or */
11938: + /* equal to 1 */
11939: + int count; /* Number of currently slots filled */
11940: + struct s_x1node *tbl; /* The data stored here */
11941: + struct s_x1node **ht; /* Hash table for lookups */
11942: +};
11943: +
11944: +/* There is one instance of this structure for every data element
11945: +** in an associative array of type "x1".
11946: +*/
11947: +typedef struct s_x1node {
11948: + const char *data; /* The data */
11949: + struct s_x1node *next; /* Next entry with the same hash */
11950: + struct s_x1node **from; /* Previous link */
11951: +} x1node;
11952: +
11953: +/* There is only one instance of the array, which is the following */
11954: +static struct s_x1 *x1a;
11955: +
11956: +/* Allocate a new associative array */
11957: +void Strsafe_init(){
11958: + if( x1a ) return;
11959: + x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
11960: + if( x1a ){
11961: + x1a->size = 1024;
11962: + x1a->count = 0;
11963: + x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*));
11964: + if( x1a->tbl==0 ){
11965: + free(x1a);
11966: + x1a = 0;
11967: + }else{
11968: + int i;
11969: + x1a->ht = (x1node**)&(x1a->tbl[1024]);
11970: + for(i=0; i<1024; i++) x1a->ht[i] = 0;
11971: + }
11972: + }
11973: +}
11974: +/* Insert a new record into the array. Return TRUE if successful.
11975: +** Prior data with the same key is NOT overwritten */
11976: +int Strsafe_insert(const char *data)
11977: +{
11978: + x1node *np;
11979: + unsigned h;
11980: + unsigned ph;
11981: +
11982: + if( x1a==0 ) return 0;
11983: + ph = strhash(data);
11984: + h = ph & (x1a->size-1);
11985: + np = x1a->ht[h];
11986: + while( np ){
11987: + if( strcmp(np->data,data)==0 ){
11988: + /* An existing entry with the same key is found. */
11989: + /* Fail because overwrite is not allows. */
11990: + return 0;
11991: + }
11992: + np = np->next;
11993: + }
11994: + if( x1a->count>=x1a->size ){
11995: + /* Need to make the hash table bigger */
11996: + int i,arrSize;
11997: + struct s_x1 array;
11998: + array.size = arrSize = x1a->size*2;
11999: + array.count = x1a->count;
12000: + array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*));
12001: + if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
12002: + array.ht = (x1node**)&(array.tbl[arrSize]);
12003: + for(i=0; i<arrSize; i++) array.ht[i] = 0;
12004: + for(i=0; i<x1a->count; i++){
12005: + x1node *oldnp, *newnp;
12006: + oldnp = &(x1a->tbl[i]);
12007: + h = strhash(oldnp->data) & (arrSize-1);
12008: + newnp = &(array.tbl[i]);
12009: + if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
12010: + newnp->next = array.ht[h];
12011: + newnp->data = oldnp->data;
12012: + newnp->from = &(array.ht[h]);
12013: + array.ht[h] = newnp;
12014: + }
12015: + free(x1a->tbl);
12016: + *x1a = array;
12017: + }
12018: + /* Insert the new data */
12019: + h = ph & (x1a->size-1);
12020: + np = &(x1a->tbl[x1a->count++]);
12021: + np->data = data;
12022: + if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
12023: + np->next = x1a->ht[h];
12024: + x1a->ht[h] = np;
12025: + np->from = &(x1a->ht[h]);
12026: + return 1;
12027: +}
12028: +
12029: +/* Return a pointer to data assigned to the given key. Return NULL
12030: +** if no such key. */
12031: +const char *Strsafe_find(const char *key)
12032: +{
12033: + unsigned h;
12034: + x1node *np;
12035: +
12036: + if( x1a==0 ) return 0;
12037: + h = strhash(key) & (x1a->size-1);
12038: + np = x1a->ht[h];
12039: + while( np ){
12040: + if( strcmp(np->data,key)==0 ) break;
12041: + np = np->next;
12042: + }
12043: + return np ? np->data : 0;
12044: +}
12045: +
12046: +/* Return a pointer to the (terminal or nonterminal) symbol "x".
12047: +** Create a new symbol if this is the first time "x" has been seen.
12048: +*/
12049: +struct symbol *Symbol_new(const char *x)
12050: +{
12051: + struct symbol *sp;
12052: +
12053: + sp = Symbol_find(x);
12054: + if( sp==0 ){
12055: + sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
12056: + MemoryCheck(sp);
12057: + sp->name = Strsafe(x);
12058: + sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL;
12059: + sp->rule = 0;
12060: + sp->fallback = 0;
12061: + sp->prec = -1;
12062: + sp->assoc = UNK;
12063: + sp->firstset = 0;
12064: + sp->lambda = LEMON_FALSE;
12065: + sp->destructor = 0;
12066: + sp->destLineno = 0;
12067: + sp->datatype = 0;
12068: + sp->useCnt = 0;
12069: + Symbol_insert(sp,sp->name);
12070: + }
12071: + sp->useCnt++;
12072: + return sp;
12073: +}
12074: +
12075: +/* Compare two symbols for sorting purposes. Return negative,
12076: +** zero, or positive if a is less then, equal to, or greater
12077: +** than b.
12078: +**
12079: +** Symbols that begin with upper case letters (terminals or tokens)
12080: +** must sort before symbols that begin with lower case letters
12081: +** (non-terminals). And MULTITERMINAL symbols (created using the
12082: +** %token_class directive) must sort at the very end. Other than
12083: +** that, the order does not matter.
12084: +**
12085: +** We find experimentally that leaving the symbols in their original
12086: +** order (the order they appeared in the grammar file) gives the
12087: +** smallest parser tables in SQLite.
12088: +*/
12089: +int Symbolcmpp(const void *_a, const void *_b)
12090: +{
12091: + const struct symbol *a = *(const struct symbol **) _a;
12092: + const struct symbol *b = *(const struct symbol **) _b;
12093: + int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1;
12094: + int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1;
12095: + return i1==i2 ? a->index - b->index : i1 - i2;
12096: +}
12097: +
12098: +/* There is one instance of the following structure for each
12099: +** associative array of type "x2".
12100: +*/
12101: +struct s_x2 {
12102: + int size; /* The number of available slots. */
12103: + /* Must be a power of 2 greater than or */
12104: + /* equal to 1 */
12105: + int count; /* Number of currently slots filled */
12106: + struct s_x2node *tbl; /* The data stored here */
12107: + struct s_x2node **ht; /* Hash table for lookups */
12108: +};
12109: +
12110: +/* There is one instance of this structure for every data element
12111: +** in an associative array of type "x2".
12112: +*/
12113: +typedef struct s_x2node {
12114: + struct symbol *data; /* The data */
12115: + const char *key; /* The key */
12116: + struct s_x2node *next; /* Next entry with the same hash */
12117: + struct s_x2node **from; /* Previous link */
12118: +} x2node;
12119: +
12120: +/* There is only one instance of the array, which is the following */
12121: +static struct s_x2 *x2a;
12122: +
12123: +/* Allocate a new associative array */
12124: +void Symbol_init(){
12125: + if( x2a ) return;
12126: + x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
12127: + if( x2a ){
12128: + x2a->size = 128;
12129: + x2a->count = 0;
12130: + x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*));
12131: + if( x2a->tbl==0 ){
12132: + free(x2a);
12133: + x2a = 0;
12134: + }else{
12135: + int i;
12136: + x2a->ht = (x2node**)&(x2a->tbl[128]);
12137: + for(i=0; i<128; i++) x2a->ht[i] = 0;
12138: + }
12139: + }
12140: +}
12141: +/* Insert a new record into the array. Return TRUE if successful.
12142: +** Prior data with the same key is NOT overwritten */
12143: +int Symbol_insert(struct symbol *data, const char *key)
12144: +{
12145: + x2node *np;
12146: + unsigned h;
12147: + unsigned ph;
12148: +
12149: + if( x2a==0 ) return 0;
12150: + ph = strhash(key);
12151: + h = ph & (x2a->size-1);
12152: + np = x2a->ht[h];
12153: + while( np ){
12154: + if( strcmp(np->key,key)==0 ){
12155: + /* An existing entry with the same key is found. */
12156: + /* Fail because overwrite is not allows. */
12157: + return 0;
12158: + }
12159: + np = np->next;
12160: + }
12161: + if( x2a->count>=x2a->size ){
12162: + /* Need to make the hash table bigger */
12163: + int i,arrSize;
12164: + struct s_x2 array;
12165: + array.size = arrSize = x2a->size*2;
12166: + array.count = x2a->count;
12167: + array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*));
12168: + if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
12169: + array.ht = (x2node**)&(array.tbl[arrSize]);
12170: + for(i=0; i<arrSize; i++) array.ht[i] = 0;
12171: + for(i=0; i<x2a->count; i++){
12172: + x2node *oldnp, *newnp;
12173: + oldnp = &(x2a->tbl[i]);
12174: + h = strhash(oldnp->key) & (arrSize-1);
12175: + newnp = &(array.tbl[i]);
12176: + if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
12177: + newnp->next = array.ht[h];
12178: + newnp->key = oldnp->key;
12179: + newnp->data = oldnp->data;
12180: + newnp->from = &(array.ht[h]);
12181: + array.ht[h] = newnp;
12182: + }
12183: + free(x2a->tbl);
12184: + *x2a = array;
12185: + }
12186: + /* Insert the new data */
12187: + h = ph & (x2a->size-1);
12188: + np = &(x2a->tbl[x2a->count++]);
12189: + np->key = key;
12190: + np->data = data;
12191: + if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
12192: + np->next = x2a->ht[h];
12193: + x2a->ht[h] = np;
12194: + np->from = &(x2a->ht[h]);
12195: + return 1;
12196: +}
12197: +
12198: +/* Return a pointer to data assigned to the given key. Return NULL
12199: +** if no such key. */
12200: +struct symbol *Symbol_find(const char *key)
12201: +{
12202: + unsigned h;
12203: + x2node *np;
12204: +
12205: + if( x2a==0 ) return 0;
12206: + h = strhash(key) & (x2a->size-1);
12207: + np = x2a->ht[h];
12208: + while( np ){
12209: + if( strcmp(np->key,key)==0 ) break;
12210: + np = np->next;
12211: + }
12212: + return np ? np->data : 0;
12213: +}
12214: +
12215: +/* Return the n-th data. Return NULL if n is out of range. */
12216: +struct symbol *Symbol_Nth(int n)
12217: +{
12218: + struct symbol *data;
12219: + if( x2a && n>0 && n<=x2a->count ){
12220: + data = x2a->tbl[n-1].data;
12221: + }else{
12222: + data = 0;
12223: + }
12224: + return data;
12225: +}
12226: +
12227: +/* Return the size of the array */
12228: +int Symbol_count()
12229: +{
12230: + return x2a ? x2a->count : 0;
12231: +}
12232: +
12233: +/* Return an array of pointers to all data in the table.
12234: +** The array is obtained from malloc. Return NULL if memory allocation
12235: +** problems, or if the array is empty. */
12236: +struct symbol **Symbol_arrayof()
12237: +{
12238: + struct symbol **array;
12239: + int i,arrSize;
12240: + if( x2a==0 ) return 0;
12241: + arrSize = x2a->count;
12242: + array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *));
12243: + if( array ){
12244: + for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
12245: + }
12246: + return array;
12247: +}
12248: +
12249: +/* Compare two configurations */
12250: +int Configcmp(const char *_a,const char *_b)
12251: +{
12252: + const struct config *a = (struct config *) _a;
12253: + const struct config *b = (struct config *) _b;
12254: + int x;
12255: + x = a->rp->index - b->rp->index;
12256: + if( x==0 ) x = a->dot - b->dot;
12257: + return x;
12258: +}
12259: +
12260: +/* Compare two states */
12261: +PRIVATE int statecmp(struct config *a, struct config *b)
12262: +{
12263: + int rc;
12264: + for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
12265: + rc = a->rp->index - b->rp->index;
12266: + if( rc==0 ) rc = a->dot - b->dot;
12267: + }
12268: + if( rc==0 ){
12269: + if( a ) rc = 1;
12270: + if( b ) rc = -1;
12271: + }
12272: + return rc;
12273: +}
12274: +
12275: +/* Hash a state */
12276: +PRIVATE unsigned statehash(struct config *a)
12277: +{
12278: + unsigned h=0;
12279: + while( a ){
12280: + h = h*571 + a->rp->index*37 + a->dot;
12281: + a = a->bp;
12282: + }
12283: + return h;
12284: +}
12285: +
12286: +/* Allocate a new state structure */
12287: +struct state *State_new()
12288: +{
12289: + struct state *newstate;
12290: + newstate = (struct state *)calloc(1, sizeof(struct state) );
12291: + MemoryCheck(newstate);
12292: + return newstate;
12293: +}
12294: +
12295: +/* There is one instance of the following structure for each
12296: +** associative array of type "x3".
12297: +*/
12298: +struct s_x3 {
12299: + int size; /* The number of available slots. */
12300: + /* Must be a power of 2 greater than or */
12301: + /* equal to 1 */
12302: + int count; /* Number of currently slots filled */
12303: + struct s_x3node *tbl; /* The data stored here */
12304: + struct s_x3node **ht; /* Hash table for lookups */
12305: +};
12306: +
12307: +/* There is one instance of this structure for every data element
12308: +** in an associative array of type "x3".
12309: +*/
12310: +typedef struct s_x3node {
12311: + struct state *data; /* The data */
12312: + struct config *key; /* The key */
12313: + struct s_x3node *next; /* Next entry with the same hash */
12314: + struct s_x3node **from; /* Previous link */
12315: +} x3node;
12316: +
12317: +/* There is only one instance of the array, which is the following */
12318: +static struct s_x3 *x3a;
12319: +
12320: +/* Allocate a new associative array */
12321: +void State_init(){
12322: + if( x3a ) return;
12323: + x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
12324: + if( x3a ){
12325: + x3a->size = 128;
12326: + x3a->count = 0;
12327: + x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*));
12328: + if( x3a->tbl==0 ){
12329: + free(x3a);
12330: + x3a = 0;
12331: + }else{
12332: + int i;
12333: + x3a->ht = (x3node**)&(x3a->tbl[128]);
12334: + for(i=0; i<128; i++) x3a->ht[i] = 0;
12335: + }
12336: + }
12337: +}
12338: +/* Insert a new record into the array. Return TRUE if successful.
12339: +** Prior data with the same key is NOT overwritten */
12340: +int State_insert(struct state *data, struct config *key)
12341: +{
12342: + x3node *np;
12343: + unsigned h;
12344: + unsigned ph;
12345: +
12346: + if( x3a==0 ) return 0;
12347: + ph = statehash(key);
12348: + h = ph & (x3a->size-1);
12349: + np = x3a->ht[h];
12350: + while( np ){
12351: + if( statecmp(np->key,key)==0 ){
12352: + /* An existing entry with the same key is found. */
12353: + /* Fail because overwrite is not allows. */
12354: + return 0;
12355: + }
12356: + np = np->next;
12357: + }
12358: + if( x3a->count>=x3a->size ){
12359: + /* Need to make the hash table bigger */
12360: + int i,arrSize;
12361: + struct s_x3 array;
12362: + array.size = arrSize = x3a->size*2;
12363: + array.count = x3a->count;
12364: + array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*));
12365: + if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
12366: + array.ht = (x3node**)&(array.tbl[arrSize]);
12367: + for(i=0; i<arrSize; i++) array.ht[i] = 0;
12368: + for(i=0; i<x3a->count; i++){
12369: + x3node *oldnp, *newnp;
12370: + oldnp = &(x3a->tbl[i]);
12371: + h = statehash(oldnp->key) & (arrSize-1);
12372: + newnp = &(array.tbl[i]);
12373: + if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
12374: + newnp->next = array.ht[h];
12375: + newnp->key = oldnp->key;
12376: + newnp->data = oldnp->data;
12377: + newnp->from = &(array.ht[h]);
12378: + array.ht[h] = newnp;
12379: + }
12380: + free(x3a->tbl);
12381: + *x3a = array;
12382: + }
12383: + /* Insert the new data */
12384: + h = ph & (x3a->size-1);
12385: + np = &(x3a->tbl[x3a->count++]);
12386: + np->key = key;
12387: + np->data = data;
12388: + if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
12389: + np->next = x3a->ht[h];
12390: + x3a->ht[h] = np;
12391: + np->from = &(x3a->ht[h]);
12392: + return 1;
12393: +}
12394: +
12395: +/* Return a pointer to data assigned to the given key. Return NULL
12396: +** if no such key. */
12397: +struct state *State_find(struct config *key)
12398: +{
12399: + unsigned h;
12400: + x3node *np;
12401: +
12402: + if( x3a==0 ) return 0;
12403: + h = statehash(key) & (x3a->size-1);
12404: + np = x3a->ht[h];
12405: + while( np ){
12406: + if( statecmp(np->key,key)==0 ) break;
12407: + np = np->next;
12408: + }
12409: + return np ? np->data : 0;
12410: +}
12411: +
12412: +/* Return an array of pointers to all data in the table.
12413: +** The array is obtained from malloc. Return NULL if memory allocation
12414: +** problems, or if the array is empty. */
12415: +struct state **State_arrayof()
12416: +{
12417: + struct state **array;
12418: + int i,arrSize;
12419: + if( x3a==0 ) return 0;
12420: + arrSize = x3a->count;
12421: + array = (struct state **)calloc(arrSize, sizeof(struct state *));
12422: + if( array ){
12423: + for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
12424: + }
12425: + return array;
12426: +}
12427: +
12428: +/* Hash a configuration */
12429: +PRIVATE unsigned confighash(struct config *a)
12430: +{
12431: + unsigned h=0;
12432: + h = h*571 + a->rp->index*37 + a->dot;
12433: + return h;
12434: +}
12435: +
12436: +/* There is one instance of the following structure for each
12437: +** associative array of type "x4".
12438: +*/
12439: +struct s_x4 {
12440: + int size; /* The number of available slots. */
12441: + /* Must be a power of 2 greater than or */
12442: + /* equal to 1 */
12443: + int count; /* Number of currently slots filled */
12444: + struct s_x4node *tbl; /* The data stored here */
12445: + struct s_x4node **ht; /* Hash table for lookups */
12446: +};
12447: +
12448: +/* There is one instance of this structure for every data element
12449: +** in an associative array of type "x4".
12450: +*/
12451: +typedef struct s_x4node {
12452: + struct config *data; /* The data */
12453: + struct s_x4node *next; /* Next entry with the same hash */
12454: + struct s_x4node **from; /* Previous link */
12455: +} x4node;
12456: +
12457: +/* There is only one instance of the array, which is the following */
12458: +static struct s_x4 *x4a;
12459: +
12460: +/* Allocate a new associative array */
12461: +void Configtable_init(){
12462: + if( x4a ) return;
12463: + x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
12464: + if( x4a ){
12465: + x4a->size = 64;
12466: + x4a->count = 0;
12467: + x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*));
12468: + if( x4a->tbl==0 ){
12469: + free(x4a);
12470: + x4a = 0;
12471: + }else{
12472: + int i;
12473: + x4a->ht = (x4node**)&(x4a->tbl[64]);
12474: + for(i=0; i<64; i++) x4a->ht[i] = 0;
12475: + }
12476: + }
12477: +}
12478: +/* Insert a new record into the array. Return TRUE if successful.
12479: +** Prior data with the same key is NOT overwritten */
12480: +int Configtable_insert(struct config *data)
12481: +{
12482: + x4node *np;
12483: + unsigned h;
12484: + unsigned ph;
12485: +
12486: + if( x4a==0 ) return 0;
12487: + ph = confighash(data);
12488: + h = ph & (x4a->size-1);
12489: + np = x4a->ht[h];
12490: + while( np ){
12491: + if( Configcmp((const char *) np->data,(const char *) data)==0 ){
12492: + /* An existing entry with the same key is found. */
12493: + /* Fail because overwrite is not allows. */
12494: + return 0;
12495: + }
12496: + np = np->next;
12497: + }
12498: + if( x4a->count>=x4a->size ){
12499: + /* Need to make the hash table bigger */
12500: + int i,arrSize;
12501: + struct s_x4 array;
12502: + array.size = arrSize = x4a->size*2;
12503: + array.count = x4a->count;
12504: + array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*));
12505: + if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
12506: + array.ht = (x4node**)&(array.tbl[arrSize]);
12507: + for(i=0; i<arrSize; i++) array.ht[i] = 0;
12508: + for(i=0; i<x4a->count; i++){
12509: + x4node *oldnp, *newnp;
12510: + oldnp = &(x4a->tbl[i]);
12511: + h = confighash(oldnp->data) & (arrSize-1);
12512: + newnp = &(array.tbl[i]);
12513: + if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
12514: + newnp->next = array.ht[h];
12515: + newnp->data = oldnp->data;
12516: + newnp->from = &(array.ht[h]);
12517: + array.ht[h] = newnp;
12518: + }
12519: + free(x4a->tbl);
12520: + *x4a = array;
12521: + }
12522: + /* Insert the new data */
12523: + h = ph & (x4a->size-1);
12524: + np = &(x4a->tbl[x4a->count++]);
12525: + np->data = data;
12526: + if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
12527: + np->next = x4a->ht[h];
12528: + x4a->ht[h] = np;
12529: + np->from = &(x4a->ht[h]);
12530: + return 1;
12531: +}
12532: +
12533: +/* Return a pointer to data assigned to the given key. Return NULL
12534: +** if no such key. */
12535: +struct config *Configtable_find(struct config *key)
12536: +{
12537: + int h;
12538: + x4node *np;
12539: +
12540: + if( x4a==0 ) return 0;
12541: + h = confighash(key) & (x4a->size-1);
12542: + np = x4a->ht[h];
12543: + while( np ){
12544: + if( Configcmp((const char *) np->data,(const char *) key)==0 ) break;
12545: + np = np->next;
12546: + }
12547: + return np ? np->data : 0;
12548: +}
12549: +
12550: +/* Remove all data from the table. Pass each data to the function "f"
12551: +** as it is removed. ("f" may be null to avoid this step.) */
12552: +void Configtable_clear(int(*f)(struct config *))
12553: +{
12554: + int i;
12555: + if( x4a==0 || x4a->count==0 ) return;
12556: + if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
12557: + for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
12558: + x4a->count = 0;
12559: + return;
12560: +}