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

📄 parse.y

📁 一个去掉程序中#ifdef #if 等预处理条件为假的程序
💻 Y
字号:
/* * parse.y - #if parser for the selective C preprocessor, scpp. * * Copyright (c) 1985 by * Tektronix, Incorporated Beaverton, Oregon 97077 * All rights reserved. * * Permission is hereby granted for personal, non-commercial * reproduction and use of this program, provided that this * notice and all copyright notices are included in any copy. */%term	MUL		/* *		*/%term	DIV		/* /		*/%term	MOD		/* %		*/%term	PLUS		/* +		*/%term	MINUS		/* -		*/%term	LS		/* <<		*/%term	RS		/* >>		*/%term	AND		/* &		*/%term	OR		/* |		*/%term	ER		/* ^		*/%term	LT		/* <		*/%term	LE		/* <=		*/%term	GT		/* >		*/%term	GE		/* >=		*/%term	EQ		/* ==		*/%term	NE		/* !=		*/%term	ANDAND		/* &&		*/%term	OROR		/* ||		*/%term	CM		/* , (comma)	*/%term	QUEST		/* ?		*/%term	COLON		/* :		*/%term	NOT		/* !		*/%term	COMPL		/* ~		*/%term	LP		/* (		*/%term	RP		/* )		*/%term	INT		/* an integer	*/%term	FLOAT		/* a float	*/%term	IDENT		/* a identifier	*/%term	QUOTE		/* ' (apostrophe) */%term	DQUOTE		/* "		*/%term	BACKS		/* \ (backslash) */%term	OPENC		/* open comment sequence */%term	CLOSEC		/* close comment sequence */%term	WHITE		/* whitespace	*/%term	NL		/* newline	*/%term	QNL		/* escaped (quoted) newline	*/%term	COMMENT		/* a comment	*/%term	OTHER		/* anything else */%term	STRING		/* a double-quote enclosed string constant	*/%term	CHARS		/* a single-quote enclosed char constant	*/%term	POUNDLINE	/*			 * The initial '#' of a preprocessor directive			 * (as opposed to a normal '#', which is of type OTHER).			 */%term	DEFMAC		/* an uninterpreted 'defined(x)' invocation	*/%left	CM%right	QUEST COLON%left	OROR%left	ANDAND%left	OR%left	ER%left	AND%left	EQ NE%left	LT LE GE GT%left	LS RS%left	PLUS MINUS%left	MUL DIV MOD%right	NOT COMPL%left	LP%union {	int intval;		/* yacc stack entries	*/	struct anode *lexval;	/* everything in this file	*/}%type <lexval>	exp e term%type <lexval> MUL DIV MOD PLUS MINUS LS RS AND OR ER LT LE GT GE EQ NE		ANDAND OROR CM QUEST COLON NOT COMPL LP RP INT FLOAT IDENT		QUOTE DQUOTE BACKS OPENC CLOSEC WHITE NL QNL COMMENT OTHER		STRING CHARS POUNDLINE DEFMAC%{# include "scpp.h"/* * struct anode - the structure used to pass strings. *  Allocated by mknode(); *  Deallocated by freenode(). * The string described will be in pend[] and is NOT NULL-TERMINATED. */struct anode {	int an_val;	/*			 * lexical (token) value of this string.			 * A value of 0 == this node is free.			 */	int an_ifval;	/* integer result of this expression */};# define NODESIZ 100	/* max number of nodes in a #if expresssion	*/struct anode nodepool[NODESIZ];struct anode *mknode();# define NIL ((struct anode *) 0)%}%start exp%%exp:	e		{			/*			 * If the expression can be evaluated, set the result			 */			if ($1->an_val == INT) {				*curif |= $1->an_ifval != 0 ?				  IF_TRUE : IF_FALSE;			}			freenode($1);		}	;e:	  e MUL e		{			$1->an_ifval = $1->an_ifval * $3->an_ifval;		binop:			$$ = $1;			if ($1->an_val == INT && $3->an_val == INT) {				$$->an_val == INT;			} else {				$$->an_val = OTHER;			}			freenode($2);			freenode($3);		}	| e DIV e		{		  if ($3->an_ifval == 0 && $3->an_val == INT) {			$3->an_val = OTHER;			warnf("division by zero in #if");		  } else {			$1->an_ifval = $1->an_ifval / $3->an_ifval;		  }		  goto binop;		}	| e MOD e		{		  if ($3->an_ifval == 0 && $3->an_val == INT) {			$3->an_val = OTHER;			warnf("mod by zero in #if");		  } else {			$1->an_ifval = $1->an_ifval % $3->an_ifval;		  }		  goto binop;		}	| e PLUS e		{$1->an_ifval = $1->an_ifval + $3->an_ifval; goto binop;}	| e MINUS e		{$1->an_ifval = $1->an_ifval - $3->an_ifval; goto binop;}	| e LS e		{$1->an_ifval = $1->an_ifval << $3->an_ifval; goto binop;}	| e RS e		{$1->an_ifval = $1->an_ifval >> $3->an_ifval; goto binop;}	| e LT e		{$1->an_ifval = $1->an_ifval < $3->an_ifval; goto binop;}	| e GT e		{$1->an_ifval = $1->an_ifval > $3->an_ifval; goto binop;}	| e LE e		{$1->an_ifval = $1->an_ifval <= $3->an_ifval; goto binop;}	| e GE e		{$1->an_ifval = $1->an_ifval >= $3->an_ifval; goto binop;}	| e EQ e		{$1->an_ifval = $1->an_ifval == $3->an_ifval; goto binop;}	| e NE e		{$1->an_ifval = $1->an_ifval != $3->an_ifval; goto binop;}	| e AND e		{$1->an_ifval = $1->an_ifval & $3->an_ifval; goto binop;}	| e ER e		{$1->an_ifval = $1->an_ifval ^ $3->an_ifval; goto binop;}	| e OR e		{$1->an_ifval = $1->an_ifval | $3->an_ifval; goto binop;}	| e ANDAND e		{			/*			 * since this is a logical AND, its value			 *  is known if either subexpression is false.			 */			$$ = $1;			if ($1->an_val == INT && $3->an_val == INT) {				/* both subexpressions are known */				$$->an_ifval = $1->an_ifval && $3->an_ifval;			} else {				if (($1->an_val == INT && !$1->an_ifval) ||				    ($3->an_val == INT && !$3->an_ifval)) {					$$->an_val = INT;					$$->an_ifval = FALSE;				} else {					$$->an_val = OTHER;				}			}			freenode($2); freenode($3);		}	| e OROR e		{			/*			 * since this is a logical OR, its value			 *  is known if either subexpression is true.			 */			$$ = $1;			if ($1->an_val == INT && $3->an_val == INT) {				/* both subexpressions are known */				$$->an_ifval = $1->an_ifval || $3->an_ifval;			} else {				if (($1->an_val == INT && $1->an_ifval) ||				    ($3->an_val == INT && $3->an_ifval)) {					$$->an_val = INT;					$$->an_ifval = TRUE;				} else {					$$->an_val = OTHER;				}			}			freenode($2); freenode($3);		}	| e QUEST e COLON e		{			/*			 * since this is an IF-ELSE, its value is known			 * in some cases even if one subexpression is unknown.			 */			$$ = $1;			if ($1->an_val == INT) {				if ($1->an_ifval) {					$$->an_val = $3->an_val;					$$->an_ifval = $3->an_ifval;				} else {					$$->an_val = $5->an_val;					$$->an_ifval = $5->an_ifval;				}			} else {				$$->an_val = OTHER;			}			freenode($2); freenode($3); freenode($4);			freenode($5);		}	| e CM e		{			/*			 * since this is a comma operator, the value of			 * the first expression is irrelevant.			 */			$$ = $3;			freenode($1);			freenode($2);		}	| term		{$$ = $1;}	;term:	  MINUS term		{			$2->an_ifval = -($2->an_ifval);		unop:			$$ = $2;			freenode($1);		}	| NOT term		{$2->an_ifval = !($2->an_ifval); goto unop;}	| COMPL term		{$2->an_ifval = ~($2->an_ifval); goto unop;}	| LP e RP		{			$$ = $2;			freenode($1); freenode($3);		}	| INT		{$$= $1;}	| IDENT		{/* an uninterpreted macro */ $$ = $1;}	| DEFMAC		{/* an uninterpreted 'defined(x)' invocation */ $$ = $1;}	;%%yyerror(s)char *s;{	struct anode *anp;	/* free all nodes */	for (anp = &nodepool[0]; anp < &nodepool[NODESIZ]; anp++) {		anp->an_val = 0;	}	warnf("syntax error in #if");}/* * yylex() - the lexical analyzer for #if statements. *  yylex() reads from the stream of interpreted macros, skipping *  insignificant tokens, then sets yylval appropriately and returns *  the token number of the token. */intyylex(){	int tok;	/*	 * Skip whitespace, quoted newlines, and interpreted preprocessor	 * directives;	 * End-of-file or an unquoted newline marks the end of the parse;	 * calculate the value of integers and character constants.	 */	if (!(yylval.lexval = mknode())) {		return(0);	}	while ((tok = gintok()) == WHITE || tok == COMMENT || tok == QNL)		;	if (tok == 0 || tok == NL) {		freenode(yylval.lexval);		yylval.lexval = NIL;		return(0);	}	yylval.lexval->an_val = tok;	if (tok == INT) {		yylval.lexval->an_ifval = inttok(curtext, nxtout);	} else if (tok == CHARS) {		yylval.lexval->an_val = INT;		yylval.lexval->an_ifval = chartok(curtext, nxtout);	}	return(yylval.lexval->an_val);}/* * inttok - convert integer token. *  Given the bounds of a token of type INT, return the value of that integer. */intinttok(s, e)char *s, *e;{	char *str;	/* points to a (dynamically alloc'ed) copy of the tok */	char *cp;	int base;	/* the radix of this integer			*/	int value;	/* the value to return				*/	int digit;	/* the value of the current digit		*/	/*	 * get a copy of the token (to remove ATTN bytes and null-terminate	 *  the string), and find out what the number base is.	 */	str = savtok(s, e);	cp = str;	if (*cp != '0') {		base = 10;	} else {		if (*cp && (*++cp == 'x' || *cp == 'X')) {			++cp;			base = 16;		} else {			base = 8;		}	}	/*	 * convert the string	 */	value = 0;	for (;*cp; ++cp) {		if (*cp >= '0' && *cp <= '7') {			digit = (int)(*cp - '0');		} else if (*cp >= '8' && *cp <= '9' && base >= 10) {			digit = (int)(*cp - '0');		} else if (*cp >= 'a' && *cp <= 'f' && base == 16) {			digit = (int)(*cp - 'a') + 10;		} else if (*cp >= 'A' && *cp <= 'F' && base == 16) {			digit = (int)(*cp - 'A') + 10;		} else {			break;		}		value = value * base + digit;	}	free(str);	return(value);}/* * chartok() - convert a character constant token. *  given the bounds of a character constant, return the integer value *   of that character constant. */ intchartok(s, e)char *s, *e;{	char *str;	/* (dynamically alloc'ed) copy of the token	*/	char *cp;	int value;	/* value to return				*/	int cnt;	str = savtok(s, e);	cp = str + 1;	if (*cp != '\\') {		value = (int) *cp;	} else if (*++cp == 'n') {		value = (int) '\n';	} else if (*cp == 't') {		value = (int) '\t';	} else if (*cp == 'b') {		value = (int) '\b';/*--read the book to find out the other chars supported--*/	} else if (*cp >= '0' && *cp <= '7') {		for (value = 0, cnt = 3; cnt >= 1 && *cp >= '0' && *cp <= '7';		  --cnt, ++cp) {			value = value * 8 + (int)(*cp - '0');		}	} else {		value = (int) *cp;	}	free(str);	return(value);}struct anode *mknode(){	struct anode *anp;	for (anp = &nodepool[0];	  anp < &nodepool[NODESIZ] && anp->an_val != 0; anp++)		;	if (anp >= &nodepool[NODESIZ]) {		warnf("#if expression too complex");		return(NIL);	}	anp->an_val = OTHER;	return(anp);}freenode(n)struct anode *n;{	n->an_val = 0;}

⌨️ 快捷键说明

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