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

📄 reader.c

📁 生成C++词法/语法分析的GNU语法分析器
💻 C
📖 第 1 页 / 共 3 页
字号:
		fatal("invalid @-construct");	      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(){  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(){  register int t;  register bucket *lhs;  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;    	      t = lex();	      if (t != COLON)		fatal("ill-formed rule");	    }	  if (nrules == 0)	    {	      if (t == BAR)		fatal("grammar starts with vertical bar");	      if (!start_flag)		startval = lhs;	    }	  /* 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)	    fatals("rule given for %s, which is a token", lhs->tag);	  /* read the rhs of the rule.  */	  for (;;)	    {	      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 write 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++;	    }	  /* 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)	    {	      t = lex();	      crule->ruleprec = symval;	      t = lex();	    }	  if (t == GUARD)	    {	      if (! semantic_parser)		fatal("%guard present but %semantic_parser not specified");	      copy_guard(crule, rulelength);	      t = lex();	    }	  else if (t == LEFT_CURLY)	    {	      if (actionflag) fatal("two actions at end of one rule");	      copy_action(crule, rulelength);	      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))		fprintf(stderr, "%s:%d:  warning:  type clash ('%s' '%s') on default action\n",			infile,			lineno,			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)	    fprintf(stderr,		    "%s:%d:  warning: empty rule for typed nonterminal, and no action\n",		    infile,		    lineno);	  if (t == SEMICOLON)	    t = lex();	}      /* these things can appear as alternatives to 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();	}      else	fatal("invalid input");    }  set_parser_name(NULL); /* if undef, use default */  if (nsyms > MAXSHORT)    fatals("too many symbols (tokens plus nonterminals); maximum %d",	   MAXSHORT);  if (nrules == 0)    fatal("no input grammar");  if (typed == 0	/* JF put out same default YYSTYPE as YACC does */      && !value_components_used)    {    }  /* Report any undefined symbols and consider them nonterminals.  */  for (bp = firstsymbol; bp; bp = bp->next)    if (bp->class == SUNKNOWN)      {	fprintf(stderr, "symbol %s used, not defined as token, and no rules for it\n",			bp->tag);	failure = 1;	bp->class = SNTERM;	bp->value = nvars++;      }  ntokens = nsyms - nvars;}voidrecord_rule_line (){  /* Record each rule's source line number in rline table.  */  if (nrules >= rline_allocated)    {      rline_allocated = nrules * 2;      rline = (short *) xrealloc (rline,				 rline_allocated * sizeof (short));    }  rline[nrules] = lineno;}/* read in a %type declaration and record its information for get_type_name to access */intget_type(){  register int k;  register int t;  register char *name;  t = lex();  if (t != TYPENAME)    fatal("ill-formed %type declaration");  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	    fatals("type redeclaration for %s", symval->tag);	  break;	default:	  return (t);	}    }}/* assign symbol numbers, and write definition of token names into fdefines.Set up vectors tags and sprec of names and precedences of symbols.  */voidpacksymbols(){  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] = "$";  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 (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;	  bp->value = tokno++;	}      tags[bp->value] = bp->tag;      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 $illegal., 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;      if (translations)	{	  if (token_translations[bp->user_token_number] != 2)	    {	    	/* JF made this a call to fatals() */	      fatals( "tokens %s and %s both assigned number %d",			      tags[token_translations[bp->user_token_number]],			      bp->tag,			      bp->user_token_number);	    }	  token_translations[bp->user_token_number] = bp->value;	}    }  error_token_number = errtoken->value;    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;  output_about_token();}      /* convert the rules into the representation using rrhs, rlhs and ritems.  */voidpackgram(){  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 (stream)     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;}void set_parser_name(n)char *n;{ if(n) /* define */   {if(parser_defined) /* redef */      fatals("parser name already defined as \"%s\"and redefined to \"%s\"\n",parser_name,n);    else      parser_defined++;      parser_name=(char *)xmalloc(strlen(n)+1);      strcpy(parser_name,n);   } else /* use only */   {     if(!parser_defined) /* first use, default */      {parser_defined++;       fprintf(stderr,"%s:%d parser name defined to default :\"%s\"\n"         ,infile,lineno,parser_name);      }     else /* next use ok*/;   }}void read_a_name(buf,len)char *buf;int len;{int c,l; for(c = skip_white_space(),l=0;     (isalnum(c) || c == '_');     c=getc(finput),l++)       if(l<len) buf[l]=c; if(l>=len)   {buf[len-1]=0;    fprintf(stderr,"%s:%d name too long, truncated to :\"%s\"\n"         ,infile,lineno,buf);   } else  buf[l]=0;          ungetc(c, finput);}  ;  voidparse_name_declaration(){char name[65]; read_a_name(name,sizeof(name)); set_parser_name(name);}voidparse_define(){char name[65]; int c; int after_backslash; read_a_name(name,sizeof(name)); set_parser_name(NULL); fprintf(ftable,"#define YY_%s_%s ",parser_name,name); if (definesflag)   fprintf(fdefines,"#define YY_%s_%s ",parser_name,name); for(after_backslash=0,c=getc(finput);     (after_backslash || c!='\n');     c=getc(finput))  {after_backslash=(c=='\\');   if(c=='\n') lineno++;   if(c==EOF)    {fatal("unexpected EOF in %define");}   hputc(c);  }  hputc('\n');lineno++;}

⌨️ 快捷键说明

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