📄 lemon.c
字号:
if( lem.errorcnt ) exit(lem.errorcnt); if( lem.rule==0 ){ fprintf(stderr,"Empty grammar.\n"); exit(1); } /* Count and index the symbols of the grammar */ lem.nsymbol = Symbol_count(); Symbol_new("{default}"); lem.symbols = Symbol_arrayof(); qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),Symbolcmpp); for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; for(i=1; safe_isupper(lem.symbols[i]->name[0]); i++); lem.nterminal = i; /* Generate a reprint of the grammar, if requested on the command line */ if( rpflag ){ Reprint(&lem); }else{ /* Initialize the size for all follow and first sets */ SetSize(lem.nterminal); /* Find the precedence for every production rule (that has one) */ FindRulePrecedences(&lem); /* Compute the lambda-nonterminals and the first-sets for every ** nonterminal */ FindFirstSets(&lem); /* Compute all LR(0) states. Also record follow-set propagation ** links so that the follow-set can be computed later */ lem.nstate = 0; FindStates(&lem); lem.sorted = State_arrayof(); /* Tie up loose ends on the propagation links */ FindLinks(&lem); /* Compute the follow set of every reducible configuration */ FindFollowSets(&lem); /* Compute the action tables */ FindActions(&lem); /* Compress the action tables */ if( compress==0 ) CompressTables(&lem); /* Generate a report of the parser generated. (the "y.output" file) */ if( !quiet ) ReportOutput(&lem); /* Generate the source code for the parser */ ReportTable(&lem, mhflag); /* Produce a header file for use by the scanner. (This step is ** omitted if the "-m" option is used because makeheaders will ** generate the file for us.) */ if( !mhflag ) ReportHeader(&lem); } if( statistics ){ printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n", lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); printf(" %d states, %d parser table entries, %d conflicts\n", lem.nstate, lem.tablesize, lem.nconflict); } if( lem.nconflict ){ fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); } exit(lem.errorcnt + lem.nconflict);}/******************** From the file "msort.c" *******************************//*** A generic merge-sort program.**** USAGE:** Let "ptr" be a pointer to some structure which is at the head of** a null-terminated list. Then to sort the list call:**** ptr = msort(ptr,&(ptr->next),cmpfnc);**** In the above, "cmpfnc" is a pointer to a function which compares** two instances of the structure and returns an integer, as in** strcmp. The second argument is a pointer to the pointer to the** second element of the linked list. This address is used to compute** the offset to the "next" field within the structure. The offset to** the "next" field must be constant for all structures in the list.**** The function returns a new pointer which is the head of the list** after sorting.**** ALGORITHM:** Merge-sort.*//*** Return a pointer to the next structure in the linked list.*/#define NEXT(A) (*(char**)(((char *)A)+offset))/*** Inputs:** a: A sorted, null-terminated linked list. (May be null).** b: A sorted, null-terminated linked list. (May be null).** cmp: A pointer to the comparison function.** offset: Offset in the structure to the "next" field.**** Return Value:** A pointer to the head of a sorted list containing the elements** of both a and b.**** Side effects:** The "next" pointers for elements in the lists a and b are** changed.*/static char *merge(char *a, char *b, int (*cmp)(const void *, const void *), int offset){ char *ptr, *head; if( a==0 ){ head = b; }else if( b==0 ){ head = a; }else{ if( (*cmp)(a,b)<0 ){ ptr = a; a = NEXT(a); }else{ ptr = b; b = NEXT(b); } head = ptr; while( a && b ){ if( (*cmp)(a,b)<0 ){ NEXT(ptr) = a; ptr = a; a = NEXT(a); }else{ NEXT(ptr) = b; ptr = b; b = NEXT(b); } } if( a ) NEXT(ptr) = a; else NEXT(ptr) = b; } return head;}/*** Inputs:** list: Pointer to a singly-linked list of structures.** next: Pointer to pointer to the second element of the list.** cmp: A comparison function.**** Return Value:** A pointer to the head of a sorted list containing the elements** orginally in list.**** Side effects:** The "next" pointers for elements in list are changed.*/#define LISTSIZE 30char *msort(char *list, char **next, int (*cmp)(const void *, const void *)){ int offset; char *ep; char *set[LISTSIZE]; int i; offset = (char *)next - (char *)list; for(i=0; i<LISTSIZE; i++) set[i] = 0; while( list ){ ep = list; list = NEXT(list); NEXT(ep) = 0; for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){ ep = merge(ep,set[i],cmp,offset); set[i] = 0; } set[i] = ep; } ep = 0; for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset); return ep;}/************************ From the file "option.c" **************************/static char **argv;static struct s_options *op;static FILE *errstream;#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)/*** Print the command line with a carrot pointing to the k-th character** of the n-th field.*/static void errline(int n, int k, FILE *err){ int spcnt, i; spcnt = 0; if( argv[0] ) fprintf(err,"%s",argv[0]); spcnt = strlen(argv[0]) + 1; for(i=1; i<n && argv[i]; i++){ fprintf(err," %s",argv[i]); spcnt += strlen(argv[i]+1); } spcnt += k; for(; argv[i]; i++) fprintf(err," %s",argv[i]); if( spcnt<20 ){ fprintf(err,"\n%*s^-- here\n",spcnt,""); }else{ fprintf(err,"\n%*shere --^\n",spcnt-7,""); }}/*** Return the index of the N-th non-switch argument. Return -1** if N is out of range.*/static int argindex(int n){ int i; int dashdash = 0; if( argv!=0 && *argv!=0 ){ for(i=1; argv[i]; i++){ if( dashdash || !ISOPT(argv[i]) ){ if( n==0 ) return i; n--; } if( strcmp(argv[i],"--")==0 ) dashdash = 1; } } return -1;}static char emsg[] = "Command line syntax error: ";/*** Process a flag command line argument.*/static int handleflags(int i, FILE *err){ int v; int errcnt = 0; int j; for(j=0; op[j].label; j++){ if( strcmp(&argv[i][1],op[j].label)==0 ) break; } v = argv[i][0]=='-' ? 1 : 0; if( op[j].label==0 ){ if( err ){ fprintf(err,"%sundefined option.\n",emsg); errline(i,1,err); } errcnt++; }else if( op[j].type==OPT_FLAG ){ *((int*)op[j].arg) = v; }else if( op[j].type==OPT_FFLAG ){ (*(void(*)())(op[j].arg))(v); }else{ if( err ){ fprintf(err,"%smissing argument on switch.\n",emsg); errline(i,1,err); } errcnt++; } return errcnt;}/*** Process a command line switch which has an argument.*/static int handleswitch(int i, FILE *err){ int lv = 0; double dv = 0.0; char *sv = 0, *end; char *cp; int j; int errcnt = 0; cp = strchr(argv[i],'='); *cp = 0; for(j=0; op[j].label; j++){ if( strcmp(argv[i],op[j].label)==0 ) break; } *cp = '='; if( op[j].label==0 ){ if( err ){ fprintf(err,"%sundefined option.\n",emsg); errline(i,0,err); } errcnt++; }else{ cp++; switch( op[j].type ){ case OPT_FLAG: case OPT_FFLAG: if( err ){ fprintf(err,"%soption requires an argument.\n",emsg); errline(i,0,err); } errcnt++; break; case OPT_DBL: case OPT_FDBL: dv = strtod(cp,&end); if( *end ){ if( err ){ fprintf(err,"%sillegal character in floating-point argument.\n",emsg); errline(i,(int)(end-argv[i]),err); } errcnt++; } break; case OPT_INT: case OPT_FINT: lv = strtol(cp,&end,0); if( *end ){ if( err ){ fprintf(err,"%sillegal character in integer argument.\n",emsg); errline(i,(int)(end-argv[i]),err); } errcnt++; } break; case OPT_STR: case OPT_FSTR: sv = cp; break; } switch( op[j].type ){ case OPT_FLAG: case OPT_FFLAG: break; case OPT_DBL: *(double*)(op[j].arg) = dv; break; case OPT_FDBL: (*(void(*)())(op[j].arg))(dv); break; case OPT_INT: *(int*)(op[j].arg) = lv; break; case OPT_FINT: (*(void(*)())(op[j].arg))((int)lv); break; case OPT_STR: *(char**)(op[j].arg) = sv; break; case OPT_FSTR: (*(void(*)())(op[j].arg))(sv); break; } } return errcnt;}int optinit(char **a, struct s_options *o, FILE *err){ int errcnt = 0; argv = a; op = o; errstream = err; if( argv && *argv && op ){ int i; for(i=1; argv[i]; i++){ if( argv[i][0]=='+' || argv[i][0]=='-' ){ errcnt += handleflags(i,err); }else if( strchr(argv[i],'=') ){ errcnt += handleswitch(i,err); } } } if( errcnt>0 ){ fprintf(err,"Valid command line options for \"%s\" are:\n",*a); optprint(); exit(1); } return 0;}int optnargs(void){ int cnt = 0; int dashdash = 0; int i; if( argv!=0 && argv[0]!=0 ){ for(i=1; argv[i]; i++){ if( dashdash || !ISOPT(argv[i]) ) cnt++; if( strcmp(argv[i],"--")==0 ) dashdash = 1; } } return cnt;}char *get_optarg(int n){ int i; i = argindex(n); return i>=0 ? argv[i] : 0;}void get_opterr(int n){ int i; i = argindex(n); if( i>=0 ) errline(i,0,errstream);}void optprint(void){ int i; int max, len; max = 0; for(i=0; op[i].label; i++){ len = strlen(op[i].label) + 1; switch( op[i].type ){ case OPT_FLAG: case OPT_FFLAG: break; case OPT_INT: case OPT_FINT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -