File indexing completed on 2025-02-23 04:46:17
0001 /* ------------------------------------------------------------------------ 0002 @NAME : parse_auxiliary.c 0003 @INPUT : 0004 @OUTPUT : 0005 @RETURNS : 0006 @DESCRIPTION: Anything needed by the parser that's too hairy to go in the 0007 grammar itself. Currently, just stuff needed for generating 0008 syntax errors. (See error.c for how they're actually 0009 printed.) 0010 @GLOBALS : 0011 @CALLS : 0012 @CALLERS : 0013 @CREATED : 1996/08/07, Greg Ward 0014 @MODIFIED : 0015 @VERSION : $Id: parse_auxiliary.c,v 1.20 1999/11/29 01:13:10 greg Rel $ 0016 @COPYRIGHT : Copyright (c) 1996-99 by Gregory P. Ward. All rights reserved. 0017 0018 This file is part of the btparse library. This library is 0019 free software; you can redistribute it and/or modify it under 0020 the terms of the GNU General Public License as 0021 published by the Free Software Foundation; either version 2 0022 of the License, or (at your option) any later version. 0023 -------------------------------------------------------------------------- */ 0024 0025 /*#include "bt_config.h"*/ 0026 #include "stdpccts.h" 0027 #include "error.h" 0028 #include "lex_auxiliary.h" 0029 #include "parse_auxiliary.h" 0030 /*#include "my_dmalloc.h"*/ 0031 0032 extern const char * InputFilename; /* from input.c */ 0033 0034 GEN_PRIVATE_ERRFUNC (syntax_error, (const char * fmt, ...), 0035 BTERR_SYNTAX, InputFilename, zzline, NULL, -1, fmt) 0036 0037 0038 /* this is stolen from PCCTS' err.h */ 0039 static SetWordType bitmask[] = 0040 { 0041 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0042 0x00000010, 0x00000020, 0x00000040, 0x00000080 0043 }; 0044 0045 static struct 0046 { 0047 int token; 0048 const char *new_name; 0049 } new_tokens[] = 0050 { 0051 { AT, "\"@\"" }, 0052 { NAME, "name (entry type, key, field, or macro name)" }, 0053 { LBRACE, "left brace (\"{\")" }, 0054 { RBRACE, "right brace (\"}\")" }, 0055 { ENTRY_OPEN, "start of entry (\"{\" or \"(\")" }, 0056 { ENTRY_CLOSE,"end of entry (\"}\" or \")\")" }, 0057 { EQUALS, "\"=\"" }, 0058 { HASH, "\"#\"" }, 0059 { COMMA, "\",\"" }, 0060 { NUMBER, "number" }, 0061 { STRING, "quoted string ({...} or \"...\")" } 0062 }; 0063 0064 0065 #ifdef CLEVER_TOKEN_STUFF 0066 char **token_names; 0067 #endif 0068 0069 0070 void 0071 fix_token_names (void) 0072 { 0073 int i; 0074 int num_replace; 0075 0076 #ifdef CLEVER_TOKEN_STUFF /* clever, but it doesn't work... */ 0077 /* arg! this doesn't work because I don't know how to find out the 0078 * number of tokens 0079 */ 0080 0081 int num_tok; 0082 0083 num_tok = (sizeof(zztokens) / sizeof(*zztokens)); 0084 sizeof (zztokens); 0085 sizeof (*zztokens); 0086 token_names = (char **) malloc (sizeof (char *) * num_tok); 0087 0088 for (i = 0; i < num_tok; i++) 0089 { 0090 token_names[i] = zztokens[i]; 0091 } 0092 #endif 0093 0094 num_replace = (sizeof(new_tokens) / sizeof(*new_tokens)); 0095 for (i = 0; i < num_replace; i++) 0096 { 0097 const char *new = new_tokens[i].new_name; 0098 const char **old = zztokens + new_tokens[i].token; 0099 0100 *old = new; 0101 } 0102 } 0103 0104 0105 #ifdef USER_ZZSYN 0106 0107 static void 0108 append_token_set (char *msg, SetWordType *a) 0109 { 0110 SetWordType *p = a; 0111 SetWordType *endp = &(p[zzSET_SIZE]); 0112 unsigned e = 0; 0113 int tokens_printed = 0; 0114 0115 do 0116 { 0117 SetWordType t = *p; 0118 SetWordType *b = &(bitmask[0]); 0119 do 0120 { 0121 if (t & *b) 0122 { 0123 strcat (msg, zztokens[e]); 0124 tokens_printed++; 0125 if (tokens_printed < zzset_deg (a) - 1) 0126 strcat (msg, ", "); 0127 else if (tokens_printed == zzset_deg (a) - 1) 0128 strcat (msg, " or "); 0129 } 0130 e++; 0131 } while (++b < &(bitmask[sizeof(SetWordType)*8])); 0132 } while (++p < endp); 0133 } 0134 0135 0136 void 0137 zzsyn(const char * text, 0138 int tok, 0139 char * egroup, 0140 SetWordType * eset, 0141 int etok, 0142 int k, 0143 const char * bad_text) 0144 { 0145 static char msg [MAX_ERROR]; 0146 int len; 0147 0148 #ifndef ALLOW_WARNINGS 0149 text = NULL; /* avoid "unused parameter" warning */ 0150 #endif 0151 0152 /* Initial message: give location of error */ 0153 0154 msg[0] = (char) 0; /* make sure string is empty to start! */ 0155 if (tok == zzEOF_TOKEN) 0156 strcat (msg, "at end of input"); 0157 else 0158 sprintf (msg, "found \"%s\"", bad_text); 0159 0160 len = strlen (msg); 0161 0162 0163 /* Caller supplied neither a single token nor set of tokens expected... */ 0164 0165 if (!etok && !eset) 0166 { 0167 syntax_error (msg); 0168 return; 0169 } 0170 else 0171 { 0172 strcat (msg, ", "); 0173 len += 2; 0174 } 0175 0176 0177 /* I'm not quite sure what this is all about, or where k would be != 1... */ 0178 0179 if (k != 1) 0180 { 0181 sprintf (msg+len, "; \"%s\" not", bad_text); 0182 if (zzset_deg (eset) > 1) strcat (msg, " in"); 0183 len = strlen (msg); 0184 } 0185 0186 0187 /* This is the code that usually gets run */ 0188 0189 if (zzset_deg (eset) > 0) 0190 { 0191 if (zzset_deg (eset) == 1) 0192 strcat (msg, "expected "); 0193 else 0194 strcat (msg, "expected one of: "); 0195 0196 append_token_set (msg, eset); 0197 } 0198 else 0199 { 0200 sprintf (msg+len, "expected %s", zztokens[etok]); 0201 if (etok == ENTRY_CLOSE) 0202 { 0203 strcat (msg, " (skipping to next \"@\")"); 0204 initialize_lexer_state (); 0205 } 0206 } 0207 0208 len = strlen (msg); 0209 if (egroup && strlen (egroup) > 0) 0210 sprintf (msg+len, " in %s", egroup); 0211 0212 syntax_error (msg); 0213 0214 } 0215 #endif /* USER_ZZSYN */ 0216 0217 0218 void 0219 check_field_name (AST * field) 0220 { 0221 char * name; 0222 0223 if (! field || field->nodetype != BTAST_FIELD) 0224 return; 0225 0226 name = field->text; 0227 if (strchr ("0123456789", name[0])) 0228 syntax_error ("invalid field name \"%s\": cannot start with digit", 0229 name); 0230 } 0231 0232 0233 #ifdef STACK_DUMP_CODE 0234 0235 static void 0236 show_ast_stack_elem (int num) 0237 { 0238 extern const char *nodetype_names[]; /* nicked from bibtex_ast.c */ 0239 /* bt_nodetype nodetype; 0240 bt_metatype metatype; */ 0241 AST *elem; 0242 0243 elem = zzastStack[num]; 0244 printf ("zzastStack[%3d] = ", num); 0245 if (elem) 0246 { 0247 /* get_node_type (elem, &nodetype, &metatype); */ 0248 if (elem->nodetype <= BTAST_MACRO) 0249 { 0250 printf ("{ %s: \"%s\" (line %d, char %d) }\n", 0251 nodetype_names[elem->nodetype], 0252 elem->text, elem->line, elem->offset); 0253 } 0254 else 0255 { 0256 printf ("bogus node (uninitialized?)\n"); 0257 } 0258 } 0259 else 0260 { 0261 printf ("NULL\n"); 0262 } 0263 } 0264 0265 0266 static void 0267 show_ast_stack_top (char *label) 0268 { 0269 if (label) 0270 printf ("%s: ast stack top: ", label); 0271 else 0272 printf ("ast stack top: "); 0273 show_ast_stack_elem (zzast_sp); 0274 } 0275 0276 0277 static void 0278 dump_ast_stack (char *label) 0279 { 0280 int i; 0281 0282 if (label) 0283 printf ("%s: complete ast stack:\n", label); 0284 else 0285 printf ("complete ast stack:\n"); 0286 0287 for (i = zzast_sp; i < ZZAST_STACKSIZE; i++) 0288 { 0289 printf (" "); 0290 show_ast_stack_elem (i); 0291 } 0292 } 0293 0294 0295 static void 0296 show_attrib_stack_elem (int num) 0297 { 0298 Attrib elem; 0299 0300 elem = zzaStack[num]; 0301 printf ("zzaStack[%3d] = ", num); 0302 printf ("{ \"%s\" (token %d (%s), line %d, char %d) }\n", 0303 elem.text, elem.token, zztokens[elem.token], 0304 elem.line, elem.offset); 0305 } 0306 0307 0308 static void 0309 show_attrib_stack_top (char *label) 0310 { 0311 if (label) 0312 printf ("%s: attrib stack top: ", label); 0313 else 0314 printf ("attrib stack top: "); 0315 show_attrib_stack_elem (zzasp); 0316 } 0317 0318 0319 static void 0320 dump_attrib_stack (char *label) 0321 { 0322 int i; 0323 0324 if (label) 0325 printf ("%s: complete attrib stack:\n", label); 0326 else 0327 printf ("complete attrib stack:\n"); 0328 0329 for (i = zzasp; i < ZZA_STACKSIZE; i++) 0330 { 0331 printf (" "); 0332 show_attrib_stack_elem (i); 0333 } 0334 } 0335 0336 #endif /* STACK_DUMP_CODE */