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

📄 proc.c

📁 又一个Pascal 到C的转换器
💻 C
字号:
/*--- proc.c -------------------------------------------------------------Procedure, type, variable, and label parsing routines for the Pascal to Ctranslator.3/25/87 Daniel Kegel (seismo!rochester!srs!dan)--------------------------------------------------------------------------*/#include <stdio.h>#include <string.h>#include "p2c.h"#include "ktypes.h"	/* keyword type definitions */#define SLEN 80	typedef char sstr[SLEN+1];	/* short string */#define PLEN 1024typedef char pstr[PLEN+1];	/* long string *//* pgroup is used in parseProcedure to store the procedure's parameters */struct pgroup {    sstr pclass;	/* VAR or empty */    sstr ptype;		/* what type all these guys are */    pstr params;	/* identifiers separated by commas and space */};booleanisSectionKeyword(k)register int k;{    return(k==T_CONST||k==T_TYPE||k==T_VAR||k==T_PROC||k==T_FUNC||k==T_BEGIN);}/*--- skipSpace ---------------------------------------------------------Accepts and throws away space and comment tokens.------------------------------------------------------------------------*/voidskipSpace(){    do	getTok();    while (cTok.kind == T_SPACE || cTok.kind == T_COMMENT);    if (cTok.kind == T_EOF) {	printf("\n/***# EOF ***/\n");	fflush(stdout);	exit(1);    }}/*--- parseSpace ---------------------------------------------------------Accepts and prints space and comment tokens.------------------------------------------------------------------------*/voidparseSpace(){    do {	getTok();	if (cTok.kind == T_SPACE || cTok.kind == T_COMMENT)	    fputs(cTok.str, stdout);    } while (cTok.kind == T_SPACE || cTok.kind == T_COMMENT);    if (cTok.kind == T_EOF) {	printf("\n/***# EOF ***/\n");	fflush(stdout);	exit(1);    }}voidexpected(s)char *s;{    printf("/***# Expected %s ***/", s);    fflush(stdout);}/*---- expectThing -------------------------------------------------------Makes sure current token is of desired type, else prints error message.------------------------------------------------------------------------*/voidexpectThing(s, k)char *s;{    if (cTok.kind != k)	expected(s);}/*---- getThing -------------------------------------------------------Gets next nonblank token, makes sure it is desired type, else prints error message.------------------------------------------------------------------------*/voidgetThing(s, k)char *s;int k;{    skipSpace();    expectThing(s, k);}/*---- parseVarDec ----------------------------------------------------Translates one (possibly multi-)variable declaration.Works for complex types, but can't be used to parse procedure parameters.On entry, cTok is first token in identifier list.On exit, cTok is the token after the type- probably T_SEMI.Semicolon is translated, too.----------------------------------------------------------------------*/struct ident {			/* Used to save variable declaration body */    char *str;			/* until type is known */    int  kind;};#define MAXIDENTS 132		/* allows about 32 variables */voidparseVarDec(){    void parseTypeDecl();		/* forward declaration */    sstr indir, index;    struct ident idents[MAXIDENTS];    int i, n;    /* Get identifiers, up to the colon that marks end of list */    n=0;    while (cTok.kind != T_COLON) {	if (n == MAXIDENTS-1)	    printf("/***# Variable declaration too long ***/");	if (n == MAXIDENTS) n--;	idents[n].str = MALLOC(char, strlen(cTok.str));	strcpy(idents[n].str, cTok.str);	idents[n++].kind = cTok.kind;	if (cTok.kind != T_ZIP && cTok.kind != T_COMMA 	&& cTok.kind != T_SPACE && cTok.kind != T_COMMENT)	    expected(" (variable declaration) comma or identifier");	getTok();		/* don't nuke spaces or comments */    }    /* Output any whitespace given before the type declaration */    for (i=0; i<n&&(idents[i].kind==T_SPACE||idents[i].kind==T_COMMENT); i++){	fputs(idents[i].str, stdout);	free(idents[i].str);    }    /* Translate type specification */    indir[0]=index[0]='\0';    parseTypeDecl(indir, index);    /* Output the identifiers, with appropriate modification for        ptr & array types */    putchar(' ');		/* separate RECORD from first element...? */    for (; i<n; i++) {	if (idents[i].kind == T_ZIP && indir[0]!='\0')	    fputs(indir, stdout);	fputs(idents[i].str, stdout);	if (idents[i].kind == T_ZIP && index[0]!='\0')	    fputs(index, stdout);	free(idents[i].str);    }    if (cTok.kind == T_SEMI)	putchar(';');}/*---- parseProcedure -------------------------------------------------------On entry, cTok is "PROCEDURE" or "FUNCTION".On exit, cTok is the token after the semicolon after the function header.Turns declarations like    foo(a:int; b:int)into    foo(a,b)    int a;    int b;Breaks up function declarations into     1. name    2. parameter declarations    3. type (or 'void', if procedure)Breaks up parameter declarations into an array of pgroups.----------------------------------------------------------------------------*/voidparseProcedure(){    boolean isProcedure;    boolean isForward;    sstr fnName;    sstr fnType;    struct pgroup *pgps=NULL;    int i, npgp=0;    register struct pgroup *p;    /* Remember whether is returns a value or not */    isProcedure = (cTok.kind == T_PROC);    /* Get function or procedure name, skipping space & comments */    getThing("function name", T_ZIP);    strcpy(fnName, cTok.str);    skipSpace();			/* eat the function name */    /* Get open paren (or semicolon of a parameterless procedure or fn) */    if (cTok.kind == T_LPAREN) {	do {	    register char *cp;	    /* Allocate and initialize another parameter group */	    if (npgp++ == 0) pgps=MALLOC(struct pgroup, 1);	    else pgps = REALLOC(pgps, struct pgroup, npgp);	    p = pgps + npgp-1;	    p->pclass[0] = p->ptype[0] = '\0';	    /* Get optional class keyword */	    skipSpace();		/* eat the paren or semicolon */	    if (cTok.kind == T_VAR) {		strcpy(p->pclass, cTok.str);		skipSpace();		/* eat the class keyword */	    }	    /* Get identifier list & type */	    cp = p->params;	    /* Get identifiers, up to the colon that marks end of list */	    while (cTok.kind != T_COLON) {		register char *cq=cTok.str;		if (cTok.kind != T_ZIP && cTok.kind != T_COMMA)		    expected(" (variable declaration) comma or identifier");		while (*cp++ = *cq++)		    ;		cp--;		skipSpace();	    }	    *cp = 0;	    /* Get type specifier, which may be many tokens.  Primitive. */	    skipSpace();	    p->ptype[0]=0;	    do {		strcat(p->ptype, cTok.str);		skipSpace();	    } while (cTok.kind != T_SEMI && cTok.kind != T_RPAREN);	} while (cTok.kind == T_SEMI);	expectThing(") at end of param list", T_RPAREN);	skipSpace();    }    /* Get return type */    if (isProcedure) {	strcpy(fnType, "void");    } else {	expectThing(":", T_COLON);	getThing("function type", T_ZIP);	strcpy(fnType, cTok.str);	skipSpace();    }    expectThing("semicolon", T_SEMI);    /* Get optional FORWARD keyword */    skipSpace();    if (isForward = (cTok.kind == T_FORWARD)) {	getThing(";", T_SEMI);	skipSpace();    }    /* Output the first part of the translated function declaration */    printf("%s %s(", fnType, fnName);    for (i=0, p=pgps; i++ < npgp; p++) {	fputs(p->params, stdout);	if (i<npgp) putchar(',');    }    putchar(')');    if (isForward)	puts(";");    else {	/* Output second part */	putchar('\n');	for (i=0, p=pgps; i++ < npgp; p++) {	    if (p->pclass[0])		fputs(p->pclass, stdout);	/* already xlated */	    printf("%s %s;\n", p->ptype, p->params);	}    }}/*--- convertArrayBound -----------------------------------------------------Given the upper bound of a Pascal array, append the C array size specificationto the buffer tindex.Lower bounds are ignored, 'cause it's safe to do so, and impossibly difficultto handle.----------------------------------------------------------------------------*/voidconvertArrayBound(s, tindex)char *s, *tindex;{    sstr buf;    int ubound;    ubound = atoi(s);    if (ubound == 0) {	/* Probably symbolic */	sprintf(buf, "[%s+1]", s);    } else {	if (ubound < 0)	    expected("positive upper bound");	sprintf(buf, "[%d]", ubound+1);    }    strcat(tindex, buf);}/*---- parseTypeDecl -------------------------------------------------------Translates a type definition in place.  Appends indirection & array subscrips,if any, to the buffers tindir and tindex.Never translates the semicolon- that is done in parseType.On entry, cTok is the token that made us expect to find a type(e.g. the colon in a variable declaration, or the equals in a type declaration,On exit, cTok is the token after the type, usually T_SEMI (but may be T_END in the last declaration in a RECORD).Pascal (or at least, Turbo Pascal) doesn't allow constructions like    a = ^array [0..10] of integer;rather, it forces you to define the base type, too:    b = array [0..10] of integer;    a = ^b;Thus any type definition can be unambiguously broken up into 2 parts:    - the base type (which may be complex)    - if pointer, how many levels of indirection      else if array, how many indices the type has, with limits-----------------------------------------------------------------------*/voidparseTypeDecl(tindir, tindex)char *tindir, *tindex;		/* buffer to put * or [n] in */{    skipSpace();		/* get initial token of type */    switch (cTok.kind) {    case T_DEREF:		/* pointer type */	strcat(tindir, "*");	parseTypeDecl(tindir, tindex);	break;    case T_LPAREN:		/* enumerated type */	fputs("enum {", stdout);	do {	    parseSpace();	    if (cTok.kind != T_RPAREN)		fputs(cTok.str, stdout);	} while (cTok.kind != T_RPAREN);	getThing(";", T_SEMI);	putchar('}');	break;    case T_ARRAY:		/* array type */	getThing("[", T_LBRACKET);	do {					/* Get all the dimensions */	    getThing("lower bound", T_ZIP);	/* Ignore lower bound except */	    if (cTok.str[0] == '-')		/* to make sure >= 0 */		expected("non-negative lower bound");	    getThing("..", T_RANGE);	    getThing("upper bound", T_ZIP);	    convertArrayBound(cTok.str, tindex);	    skipSpace();	} while (cTok.kind == T_COMMA);	expectThing("]", T_RBRACKET);	getThing("OF", T_OF);	parseTypeDecl(tindir, tindex);	break;    case T_STRINGTYPE:		/* Turbo (& UCSD?) string type */	printf("char");	skipSpace();	if (cTok.kind != T_LPAREN && cTok.kind != T_LBRACKET) 	    expected("[ or ( after STRING");	getThing("string length", T_ZIP);	convertArrayBound(cTok.str, tindex);	skipSpace();	if (cTok.kind != T_RPAREN && cTok.kind != T_RBRACKET) 	    expected("] or ) after STRING[");	getThing(";", T_SEMI);	break;    case T_FILE:		/* file type - not supported in C */	strcat(tindir, "*");	printf("FILE /* OF ");	/* show what it's a file of in the comment */	do {	    skipSpace();	    if (cTok.kind != T_COMMENT);	/* avoid nesting comments */		fputs(cTok.str, stdout);	} while (cTok.kind != T_SEMI);	printf(" */ ");	break;    case T_RECORD:		/* struct definition */	printf("struct {");	parseSpace();		/* eat RECORD */	do {	    if (cTok.kind == T_CASE) {		printf("/***# Sorry- variant records not supported\n\t");		do {		    if (cTok.kind != T_COMMENT)			fputs(cTok.str, stdout);		    getTok();		} while (cTok.kind != T_END);		printf(" ***/");		break;	    }	    parseVarDec();	    if (cTok.kind == T_SEMI)		parseSpace();	    else if (cTok.kind == T_END)		putchar(';');		/* Pascal doesn't need ; but C does*/	    else if (cTok.kind != T_CASE)		expected("Either semicolon or END");	} while (cTok.kind != T_END);	parseSpace();		/* eat the END, get the semi */	printf("}");	break;    case T_ZIP:			/* probably a type keyword like 'integer' */	fputs(cTok.str, stdout);	skipSpace();		/* eat the type, get the semi */	break;    default:			/* unexpected */	expected("type");    }}/*---- parseVar -------------------------------------------------------Translates the VAR section of a program or procedure.On entry, cTok is "VAR".On exit, cTok is any section-starting keyword.Turns declarations like    foo : ^integer;into    int *foo;----------------------------------------------------------------------------*/voidparseVar(){    getTok();		/* eat the VAR */    do {	parseVarDec();	if (cTok.kind == T_SEMI)	    parseSpace();    } while (!isSectionKeyword(cTok.kind));}/*---- parseType -----------------------------------------------------------Translates the TYPE section of a program or procedure.On entry, cTok is TYPE.On exit, cTok is any section-starting keyword.Turns declarations like    foo = array [0..10, LO..HI] of integer;    boo = record	    x : foo;	    y : ^foo	  end;into    typedef integer foo[11][HI+1];    typedef struct {	foo x;	foo *y;    } boo;---------------------------------------------------------------------------*/voidparseType(){    parseSpace();    do {	sstr typ;	sstr tindir, tindex;	expectThing("type identifier", T_ZIP);	strcpy(typ, cTok.str);	parseSpace();	expectThing("=", T_EQUALS);	printf("typedef ");	tindir[0]=tindex[0]=0;	parseTypeDecl(tindir, tindex);	expectThing(";", T_SEMI);	printf(" %s%s%s;", tindir, typ, tindex);	parseSpace();    } while (!isSectionKeyword(cTok.kind));}/*---- parseLabel -------------------------------------------------------On entry, cTok is "LABEL".On exit, cTok is whatever follows the semicolon.Turns declarations likeLABEL foo, goo;into/ * LABEL foo, goo; * /----------------------------------------------------------------------------*/voidparseLabel(){    skipSpace();		/* eat the LABEL */    printf("/* LABEL ");    /* Get identifiers, up to the semicolon that marks end of list */    while (cTok.kind != T_SEMI) {	if (cTok.kind != T_ZIP && cTok.kind != T_COMMA)	    expected(" (label declaration) comma or identifier");	fputs(cTok.str, stdout);	skipSpace();    }    /* Get semicolon without wiping out trailing space */    getTok();    fputs("; */", stdout);}

⌨️ 快捷键说明

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