📄 lemon.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**)(((unsigned long)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(a,b,cmp,offset)char *a;char *b;int (*cmp)();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(list,next,cmp)char *list;char **next;int (*cmp)();{ unsigned long offset; char *ep; char *set[LISTSIZE]; int i; offset = (unsigned long)next - (unsigned long)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(n,k,err)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(n)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(i,err)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(i,err)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,((unsigned long)end)-(unsigned long)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,((unsigned long)end)-(unsigned long)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(a,o,err)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(){ 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 *OptArg(n)int n;{ int i; i = argindex(n); return i>=0 ? argv[i] : 0;}void OptErr(n)int n;{ int i; i = argindex(n); if( i>=0 ) errline(i,0,errstream);}void OptPrint(){ 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: len += 9; /* length of "<integer>" */ break; case OPT_DBL: case OPT_FDBL: len += 6; /* length of "<real>" */ break; case OPT_STR: case OPT_FSTR: len += 8; /* length of "<string>" */ break; } if( len>max ) max = len; } for(i=0; op[i].label; i++){ switch( op[i].type ){ case OPT_FLAG: case OPT_FFLAG: fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message); break; case OPT_INT: case OPT_FINT: fprintf(errstream," %s=<integer>%*s %s\n",op[i].label, max-strlen(op[i].label)-9,"",op[i].message); break; case OPT_DBL: case OPT_FDBL: fprintf(errstream," %s=<real>%*s %s\n",op[i].label, max-strlen(op[i].label)-6,"",op[i].message); break; case OPT_STR: case OPT_FSTR: fprintf(errstream," %s=<string>%*s %s\n",op[i].label, max-strlen(op[i].label)-8,"",op[i].message); break; } }}/*********************** From the file "parse.c" ****************************//*** Input file parser for the LEMON parser generator.*//* The state of the parser */struct pstate { char *filename; /* Name of the input file */ int tokenlineno; /* Linenumber at which current token starts */ int errorcnt; /* Number of errors so far */ char *tokenstart; /* Text of current token */ struct lemon *gp; /* Global state vector */ enum e_state { INITIALIZE, WAITING_FOR_DECL_OR_RULE, WAITING_FOR_DECL_KEYWORD, WAITING_FOR_DECL_ARG, WAITING_FOR_PRECEDENCE_SYMBOL, WAITING_FOR_ARROW, IN_RHS, LHS_ALIAS_1, LHS_ALIAS_2, LHS_ALIAS_3,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -