⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reader.c

📁 Bison语法分析器
💻 C
📖 第 1 页 / 共 3 页
字号:
		  n = read_signed_integer(finput);		  c = getc(finput);		}	      else		{		  warn(_("invalid @-construct"));		  n = 1;		}	      fprintf(faction, "yylsp[%d]", n - stack_offset);	      yylsp_needed = 1;	      continue;	    case EOF:	      fatal(_("unmatched `{'"));	    default:	      putc(c, faction);	    }          c = getc(finput);        }      /* above loop exits when c is '}' */      if (--count)        {	  putc(c, faction);	  c = getc(finput);	}    }  fprintf(faction, ";\n    break;}");}/* generate a dummy symbol, a nonterminal,whose name cannot conflict with the user's names. */bucket *gensym (void){  register bucket *sym;  sprintf (token_buffer, "@%d", ++gensym_count);  sym = getsym(token_buffer);  sym->class = SNTERM;  sym->value = nvars++;  return (sym);}/* Parse the input grammar into a one symbol_list structure.Each rule is represented by a sequence of symbols: the left hand sidefollowed by the contents of the right hand side, followed by a null pointerinstead of a symbol to terminate the rule.The next symbol is the lhs of the following rule.All guards and actions are copied out to the appropriate files,labelled by the rule number they apply to.  */voidreadgram (void){  register int t;  register bucket *lhs = NULL;  register symbol_list *p;  register symbol_list *p1;  register bucket *bp;  symbol_list *crule;	/* points to first symbol_list of current rule.  */			/* its symbol is the lhs of the rule.   */  symbol_list *crule1;  /* points to the symbol_list preceding crule.  */  p1 = NULL;  t = lex();  while (t != TWO_PERCENTS && t != ENDFILE)    {      if (t == IDENTIFIER || t == BAR)	{	  register int actionflag = 0;	  int rulelength = 0;  /* number of symbols in rhs of this rule so far  */	  int xactions = 0;	/* JF for error checking */	  bucket *first_rhs = 0;	  if (t == IDENTIFIER)	    {	      lhs = symval;	      if (!start_flag)		{		  startval = lhs;		  start_flag = 1;		}	      t = lex();	      if (t != COLON)		{		  warn(_("ill-formed rule: initial symbol not followed by colon"));		  unlex(t);		}	    }	  if (nrules == 0 && t == BAR)	    {	      warn(_("grammar starts with vertical bar"));	      lhs = symval;	/* BOGUS: use a random symval */	    }	  /* start a new rule and record its lhs.  */	  nrules++;	  nitems++;	  record_rule_line ();	  p = NEW(symbol_list);	  p->sym = lhs;	  crule1 = p1;	  if (p1)	    p1->next = p;	  else	    grammar = p;	  p1 = p;	  crule = p;	  /* mark the rule's lhs as a nonterminal if not already so.  */	  if (lhs->class == SUNKNOWN)	    {	      lhs->class = SNTERM;	      lhs->value = nvars;	      nvars++;	    }	  else if (lhs->class == STOKEN)	    warns(_("rule given for %s, which is a token"), lhs->tag);	  /* read the rhs of the rule.  */	  for (;;)	    {	      t = lex();	      if (t == PREC)		{		  t = lex();		  crule->ruleprec = symval;		  t = lex();		}	      if (! (t == IDENTIFIER || t == LEFT_CURLY)) break;	      /* If next token is an identifier, see if a colon follows it.		 If one does, exit this rule now.  */	      if (t == IDENTIFIER)		{		  register bucket *ssave;		  register int t1;		  ssave = symval;		  t1 = lex();		  unlex(t1);		  symval = ssave;		  if (t1 == COLON) break;		  if(!first_rhs)	/* JF */		    first_rhs = symval;		  /* Not followed by colon =>		     process as part of this rule's rhs.  */		}	      /* If we just passed an action, that action was in the middle		 of a rule, so make a dummy rule to reduce it to a		 non-terminal.  */	      if (actionflag)		{		  register bucket *sdummy;		  /* Since the action was written out with this rule's */		  /* number, we must give the new rule this number */		  /* by inserting the new rule before it.  */		  /* Make a dummy nonterminal, a gensym.  */		  sdummy = gensym();		  /* Make a new rule, whose body is empty,		     before the current one, so that the action		     just read can belong to it.  */		  nrules++;		  nitems++;		  record_rule_line ();		  p = NEW(symbol_list);		  if (crule1)		    crule1->next = p;		  else grammar = p;		  p->sym = sdummy;		  crule1 = NEW(symbol_list);		  p->next = crule1;		  crule1->next = crule;		  /* insert the dummy generated by that rule into this rule.  */		  nitems++;		  p = NEW(symbol_list);		  p->sym = sdummy;		  p1->next = p;		  p1 = p;		  actionflag = 0;		}	      if (t == IDENTIFIER)		{		  nitems++;		  p = NEW(symbol_list);		  p->sym = symval;		  p1->next = p;		  p1 = p;		}	      else /* handle an action.  */		{		  copy_action(crule, rulelength);		  actionflag = 1;		  xactions++;	/* JF */		}	      rulelength++;	    }	/* end of  read rhs of rule */	  /* Put an empty link in the list to mark the end of this rule  */	  p = NEW(symbol_list);	  p1->next = p;	  p1 = p;	  if (t == PREC)	    {	      warn(_("two @prec's in a row"));	      t = lex();	      crule->ruleprec = symval;	      t = lex();	    }	  if (t == GUARD)	    {	      if (! semantic_parser)		warn(_("%%guard present but %%semantic_parser not specified"));	      copy_guard(crule, rulelength);	      t = lex();	    }	  else if (t == LEFT_CURLY)	    {		/* This case never occurs -wjh */	      if (actionflag)  warn(_("two actions at end of one rule"));	      copy_action(crule, rulelength);	      actionflag = 1;	      xactions++;	/* -wjh */	      t = lex();	    }	  /* If $$ is being set in default way,	     warn if any type mismatch.  */	  else if (!xactions && first_rhs && lhs->type_name != first_rhs->type_name)	    {	      if (lhs->type_name == 0 || first_rhs->type_name == 0		  || strcmp(lhs->type_name,first_rhs->type_name))		warnss(_("type clash (`%s' `%s') on default action"),			lhs->type_name ? lhs->type_name : "",			first_rhs->type_name ? first_rhs->type_name : "");	    }	  /* Warn if there is no default for $$ but we need one.  */	  else if (!xactions && !first_rhs && lhs->type_name != 0)	    warn(_("empty rule for typed nonterminal, and no action"));	  if (t == SEMICOLON)	    t = lex();	}#if 0  /* these things can appear as alternatives to rules.  *//* NO, they cannot.	a) none of the documentation allows them	b) most of them scan forward until finding a next %		thus they may swallow lots of intervening rules*/      else if (t == TOKEN)	{	  parse_token_decl(STOKEN, SNTERM);	  t = lex();	}      else if (t == NTERM)	{	  parse_token_decl(SNTERM, STOKEN);	  t = lex();	}      else if (t == TYPE)	{	  t = get_type();	}      else if (t == UNION)	{	  parse_union_decl();	  t = lex();	}      else if (t == EXPECT)	{	  parse_expect_decl();	  t = lex();	}      else if (t == START)	{	  parse_start_decl();	  t = lex();	}#endif      else	{	  warns(_("invalid input: %s"), token_buffer);	  t = lex();	}    }  /* grammar has been read.  Do some checking */  if (nsyms > MAXSHORT)    fatals(_("too many symbols (tokens plus nonterminals); maximum %s"),	   int_to_string(MAXSHORT));  if (nrules == 0)    fatal(_("no rules in the input grammar"));  if (typed == 0	/* JF put out same default YYSTYPE as YACC does */      && !value_components_used)    {      /* We used to use `unsigned long' as YYSTYPE on MSDOS,	 but it seems better to be consistent.	 Most programs should declare their own type anyway.  */      fprintf(fattrs, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");      if (fdefines)	fprintf(fdefines, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");    }  /* Report any undefined symbols and consider them nonterminals.  */  for (bp = firstsymbol; bp; bp = bp->next)    if (bp->class == SUNKNOWN)      {	warns(_("symbol %s is used, but is not defined as a token and has no rules"),			bp->tag);	bp->class = SNTERM;	bp->value = nvars++;      }  ntokens = nsyms - nvars;}voidrecord_rule_line (void){  /* Record each rule's source line number in rline table.  */  if (nrules >= rline_allocated)    {      rline_allocated = nrules * 2;      rline = (short *) xrealloc ((char *) rline,				  rline_allocated * sizeof (short));    }  rline[nrules] = lineno;}#if 0/* read in a %type declaration and record its information for get_type_name to access *//* this is unused.  it is only called from the #if 0 part of readgram */static intget_type (void){  register int k;  register int t;  register char *name;  t = lex();  if (t != TYPENAME)    {      warn(_("ill-formed %type declaration"));      return t;    }  k = strlen(token_buffer);  name = NEW2(k + 1, char);  strcpy(name, token_buffer);  for (;;)    {      t = lex();      switch (t)	{	case SEMICOLON:	  return (lex());	case COMMA:	  break;	case IDENTIFIER:	  if (symval->type_name == NULL)	    symval->type_name = name;	  else if (strcmp(name, symval->type_name) != 0)	    warns(_("type redeclaration for %s"), symval->tag);	  break;	default:	  return (t);	}    }}#endif/* assign symbol numbers, and write definition of token names into fdefines.Set up vectors tags and sprec of names and precedences of symbols.  */voidpacksymbols (void){  register bucket *bp;  register int tokno = 1;  register int i;  register int last_user_token_number;  /* int lossage = 0; JF set but not used */  tags = NEW2(nsyms + 1, char *);  tags[0] = "$";  user_toknums = NEW2(nsyms + 1, int);  user_toknums[0] = 0;  sprec = NEW2(nsyms, short);  sassoc = NEW2(nsyms, short);  max_user_token_number = 256;  last_user_token_number = 256;  for (bp = firstsymbol; bp; bp = bp->next)    {      if (bp->class == SNTERM)	{	  bp->value += ntokens;	}      else if (bp->alias)	{		/* this symbol and its alias are a single token defn.		  allocate a tokno, and assign to both		  check agreement of ->prec and ->assoc fields			and make both the same		*/		if (bp->value == 0)			bp->value = bp->alias->value = tokno++;		if (bp->prec != bp->alias->prec) {			if (bp->prec != 0 && bp->alias->prec != 0					&& bp->user_token_number == SALIAS)				warnss(_("conflicting precedences for %s and %s"),					bp->tag, bp->alias->tag);			if (bp->prec != 0) bp->alias->prec = bp->prec;			else bp->prec = bp->alias->prec;		}		if (bp->assoc != bp->alias->assoc) {			if (bp->assoc != 0 && bp->alias->assoc != 0					&& bp->user_token_number == SALIAS)				warnss(_("conflicting assoc values for %s and %s"),					bp->tag, bp->alias->tag);			if (bp->assoc != 0) bp->alias->assoc = bp->assoc;			else bp->assoc = bp->alias->assoc;		}		if (bp->user_token_number == SALIAS)			continue;  /* do not do processing below for SALIASs */ 	}      else  /* bp->class == STOKEN */	{	  bp->value = tokno++;	}      if (bp->class == STOKEN)	{	  if (translations && !(bp->user_token_number))	    bp->user_token_number = ++last_user_token_number;	  if (bp->user_token_number > max_user_token_number)	    max_user_token_number = bp->user_token_number;	}      tags[bp->value] = bp->tag;      user_toknums[bp->value] = bp->user_token_number;      sprec[bp->value] = bp->prec;      sassoc[bp->value] = bp->assoc;    }  if (translations)    {      register int i;      token_translations = NEW2(max_user_token_number+1, short);      /* initialize all entries for literal tokens to 2,	 the internal token number for $undefined.,	 which represents all invalid inputs.  */      for (i = 0; i <= max_user_token_number; i++)        token_translations[i] = 2;      for (bp = firstsymbol; bp; bp = bp->next)        {          if (bp->value >= ntokens) continue;		  /* non-terminal */          if (bp->user_token_number == SALIAS) continue;          if (token_translations[bp->user_token_number] != 2)	    warnsss(_("tokens %s and %s both assigned number %s"),			      tags[token_translations[bp->user_token_number]],			      bp->tag,			      int_to_string(bp->user_token_number));          token_translations[bp->user_token_number] = bp->value;        }    }  error_token_number = errtoken->value;  if (! noparserflag)    output_token_defines(ftable);  if (startval->class == SUNKNOWN)    fatals(_("the start symbol %s is undefined"), startval->tag);  else if (startval->class == STOKEN)    fatals(_("the start symbol %s is a token"), startval->tag);  start_symbol = startval->value;  if (definesflag)    {      output_token_defines(fdefines);      if (!pure_parser)	{	  if (spec_name_prefix)	    fprintf(fdefines, "\nextern YYSTYPE %slval;\n", spec_name_prefix);	  else	    fprintf(fdefines, "\nextern YYSTYPE yylval;\n");	}      if (semantic_parser)	for (i = ntokens; i < nsyms; i++)	  {	    /* don't make these for dummy nonterminals made by gensym.  */	    if (*tags[i] != '@')	      fprintf(fdefines, "#define\tNT%s\t%d\n", tags[i], i);	  }#if 0      /* `fdefines' is now a temporary file, so we need to copy its         contents in `done', so we can't close it here.  */      fclose(fdefines);      fdefines = NULL;#endif    }}/* For named tokens, but not literal ones, define the name.   The value is the user token number.*/voidoutput_token_defines (FILE *file){  bucket *bp;  register char *cp, *symbol;  register char c;  for (bp = firstsymbol; bp; bp = bp->next)    {      symbol = bp->tag;				/* get symbol */      if (bp->value >= ntokens) continue;      if (bp->user_token_number == SALIAS) continue;      if ('\'' == *symbol) continue;	/* skip literal character */      if (bp == errtoken) continue; 	/* skip error token */      if ('\"' == *symbol)	{		/* use literal string only if given a symbol with an alias */		if (bp->alias)			symbol = bp->alias->tag;		else			continue;	}      /* Don't #define nonliteral tokens whose names contain periods.  */      cp = symbol;      while ((c = *cp++) && c != '.');      if (c != '\0')  continue;      fprintf(file, "#define\t%s\t%d\n", symbol,		((translations && ! rawtoknumflag)			? bp->user_token_number			: bp->value));      if (semantic_parser)        fprintf(file, "#define\tT%s\t%d\n", symbol, bp->value);    }  putc('\n', file);}/* convert the rules into the representation using rrhs, rlhs and ritems.  */voidpackgram (void){  register int itemno;  register int ruleno;  register symbol_list *p;/*  register bucket *bp; JF unused */  bucket *ruleprec;  ritem = NEW2(nitems + 1, short);  rlhs = NEW2(nrules, short) - 1;  rrhs = NEW2(nrules, short) - 1;  rprec = NEW2(nrules, short) - 1;  rprecsym = NEW2(nrules, short) - 1;  rassoc = NEW2(nrules, short) - 1;  itemno = 0;  ruleno = 1;  p = grammar;  while (p)    {      rlhs[ruleno] = p->sym->value;      rrhs[ruleno] = itemno;      ruleprec = p->ruleprec;      p = p->next;      while (p && p->sym)	{	  ritem[itemno++] = p->sym->value;	  /* A rule gets by default the precedence and associativity	     of the last token in it.  */          if (p->sym->class == STOKEN)	    {	      rprec[ruleno] = p->sym->prec;	      rassoc[ruleno] = p->sym->assoc;	    }	  if (p) p = p->next;	}      /* If this rule has a %prec,	 the specified symbol's precedence replaces the default.  */      if (ruleprec)	{          rprec[ruleno] = ruleprec->prec;          rassoc[ruleno] = ruleprec->assoc;	  rprecsym[ruleno] = ruleprec->value;	}      ritem[itemno++] = -ruleno;      ruleno++;      if (p) p = p->next;    }  ritem[itemno] = 0;}/* Read a signed integer from STREAM and return its value.  */intread_signed_integer (FILE *stream){  register int c = getc(stream);  register int sign = 1;  register int n;  if (c == '-')    {      c = getc(stream);      sign = -1;    }  n = 0;  while (isdigit(c))    {      n = 10*n + (c - '0');      c = getc(stream);    }  ungetc(c, stream);  return n * sign;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -