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: +}