📄 parse_noyacc.c
字号:
*/Program *ParseMacro(char *expr, char **msg, char **stoppedAt){ Program *prog; BeginCreatingProgram(); /* call yyparse to parse the string and check for success. If the parse failed, return the error message and string index (the grammar aborts parsing at the first error) */ InPtr = expr; if (yyparse()) { *msg = ErrMsg; *stoppedAt = InPtr; FreeProgram(FinishCreatingProgram()); return NULL; } /* get the newly created program */ prog = FinishCreatingProgram(); /* parse succeeded */ *msg = ""; *stoppedAt = InPtr; return prog;}static int yylex(void){ int i, len; Symbol *s; static DataValue value = {NO_TAG, {0}}; static char escape[] = "\\\"ntbrfav"; static char replace[] = "\\\"\n\t\b\r\f\a\v"; /* skip whitespace, backslash-newline combinations, and comments, which are all considered whitespace */ for (;;) { if (*InPtr == '\\' && *(InPtr + 1) == '\n') InPtr += 2; else if (*InPtr == ' ' || *InPtr == '\t') InPtr++; else if (*InPtr == '#') while (*InPtr != '\n' && *InPtr != '\0') { /* Comments stop at escaped newlines */ if (*InPtr == '\\' && *(InPtr + 1) == '\n') { InPtr += 2; break; } InPtr++; } else break; } /* return end of input at the end of the string */ if (*InPtr == '\0') { return 0; } /* process number tokens */ if (isdigit((unsigned char)*InPtr)) { /* number */ char name[28]; sscanf(InPtr, "%d%n", &value.val.n, &len); sprintf(name, "const %d", value.val.n); InPtr += len; value.tag = INT_TAG; if ((yylval.sym=LookupSymbol(name)) == NULL) yylval.sym = InstallSymbol(name, CONST_SYM, value); return NUMBER; } /* process symbol tokens. "define" is a special case not handled by this parser, considered end of input. Another special case is action routine names which are allowed to contain '-' despite the ambiguity, handled in matchesActionRoutine. */ if (isalpha((unsigned char)*InPtr) || *InPtr == '$') { if ((s=matchesActionRoutine(&InPtr)) == NULL) { char symName[MAX_SYM_LEN+1], *p = symName; *p++ = *InPtr++; while (isalnum((unsigned char)*InPtr) || *InPtr=='_') { if (p >= symName + MAX_SYM_LEN) InPtr++; else *p++ = *InPtr++; } *p = '\0'; if (!strcmp(symName, "while")) return WHILE; if (!strcmp(symName, "if")) return IF; if (!strcmp(symName, "else")) return ELSE; if (!strcmp(symName, "for")) return FOR; if (!strcmp(symName, "break")) return BREAK; if (!strcmp(symName, "continue")) return CONTINUE; if (!strcmp(symName, "return")) return RETURN; if (!strcmp(symName, "in")) return IN; if (!strcmp(symName, "delete") && follow_non_whitespace('(', SYMBOL, DELETE) == DELETE) return DELETE; if (!strcmp(symName, "define")) { InPtr -= 6; return 0; } if ((s=LookupSymbol(symName)) == NULL) { s = InstallSymbol(symName, symName[0]=='$' ? (isdigit((unsigned char)symName[1]) ? ARG_SYM : GLOBAL_SYM) : LOCAL_SYM, value); s->value.tag = NO_TAG; } } yylval.sym = s; return SYMBOL; } /* process quoted strings w/ embedded escape sequences */ if (*InPtr == '\"') { char string[MAX_STRING_CONST_LEN], *p = string; InPtr++; while (*InPtr != '\0' && *InPtr != '\"' && *InPtr != '\n') { if (p >= string + MAX_STRING_CONST_LEN) { InPtr++; continue; } if (*InPtr == '\\') { InPtr++; if (*InPtr == '\n') { InPtr++; continue; } for (i=0; escape[i]!='\0'; i++) { if (escape[i] == '\0') { *p++= *InPtr++; break; } else if (escape[i] == *InPtr) { *p++ = replace[i]; InPtr++; break; } } } else *p++= *InPtr++; } *p = '\0'; InPtr++; yylval.sym = InstallStringConstSymbol(string); return STRING; } /* process remaining two character tokens or return single char as token */ switch(*InPtr++) { case '>': return follow('=', GE, GT); case '<': return follow('=', LE, LT); case '=': return follow('=', EQ, '='); case '!': return follow('=', NE, NOT); case '+': return follow2('+', INCR, '=', ADDEQ, '+'); case '-': return follow2('-', DECR, '=', SUBEQ, '-'); case '|': return follow2('|', OR, '=', OREQ, '|'); case '&': return follow2('&', AND, '=', ANDEQ, '&'); case '*': return follow2('*', POW, '=', MULEQ, '*'); case '/': return follow('=', DIVEQ, '/'); case '%': return follow('=', MODEQ, '%'); case '^': return POW; default: return *(InPtr-1); }}/*** look ahead for >=, etc.*/static int follow(char expect, int yes, int no){ if (*InPtr++ == expect) return yes; InPtr--; return no;}static int follow2(char expect1, int yes1, char expect2, int yes2, int no){ char next = *InPtr++; if (next == expect1) return yes1; if (next == expect2) return yes2; InPtr--; return no;}static int follow_non_whitespace(char expect, int yes, int no){ char *localInPtr = InPtr; while (1) { if (*localInPtr == ' ' || *localInPtr == '\t') { ++localInPtr; } else if (*localInPtr == '\\' && *(localInPtr + 1) == '\n') { localInPtr += 2; } else if (*localInPtr == expect) { return(yes); } else { return(no); } }}/*** Look (way) ahead for hyphenated routine names which begin at inPtr. A** hyphenated name is allowed if it is pre-defined in the global symbol** table. If a matching name exists, returns the symbol, and update "inPtr".**** I know this is horrible language design, but existing nedit action routine** names contain hyphens. Handling them here in the lexical analysis process** is much easier than trying to deal with it in the parser itself. (sorry)*/static Symbol *matchesActionRoutine(char **inPtr){ char *c, *symPtr; int hasDash = False; char symbolName[MAX_SYM_LEN+1]; Symbol *s; symPtr = symbolName; for (c = *inPtr; isalnum((unsigned char)*c) || *c=='_' || ( *c=='-' && isalnum((unsigned char)(*(c+1)))); c++) { if (*c == '-') hasDash = True; *symPtr++ = *c; } if (!hasDash) return NULL; *symPtr = '\0'; s = LookupSymbol(symbolName); if (s != NULL) *inPtr = c; return s;}/*** Called by yacc to report errors (just stores for returning when** parsing is aborted. The error token action is to immediate abort** parsing, so this message is immediately reported to the caller** of ParseExpr)*/static int yyerror(char *s){ ErrMsg = s; return 0;}#line 965 "y.tab.c"/* allocate initial stack or double stack size, up to YYMAXDEPTH */static int yygrowstack(){ int newsize, i; short *newss; YYSTYPE *newvs; if ((newsize = yystacksize) == 0) newsize = YYINITSTACKSIZE; else if (newsize >= YYMAXDEPTH) return -1; else if ((newsize *= 2) > YYMAXDEPTH) newsize = YYMAXDEPTH; i = yyssp - yyss; newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) : (short *)malloc(newsize * sizeof *newss); if (newss == NULL) return -1; yyss = newss; yyssp = newss + i; newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) : (YYSTYPE *)malloc(newsize * sizeof *newvs); if (newvs == NULL) return -1; yyvs = newvs; yyvsp = newvs + i; yystacksize = newsize; yysslim = yyss + newsize - 1; return 0;}#define YYABORT goto yyabort#define YYREJECT goto yyabort#define YYACCEPT goto yyaccept#define YYERROR goto yyerrlab#ifndef YYPARSE_PARAM#if defined(__cplusplus) || __STDC__#define YYPARSE_PARAM_ARG void#define YYPARSE_PARAM_DECL#else /* ! ANSI-C/C++ */#define YYPARSE_PARAM_ARG#define YYPARSE_PARAM_DECL#endif /* ANSI-C/C++ */#else /* YYPARSE_PARAM */#ifndef YYPARSE_PARAM_TYPE#define YYPARSE_PARAM_TYPE void *#endif#if defined(__cplusplus) || __STDC__#define YYPARSE_PARAM_ARG YYPARSE_PARAM_TYPE YYPARSE_PARAM#define YYPARSE_PARAM_DECL#else /* ! ANSI-C/C++ */#define YYPARSE_PARAM_ARG YYPARSE_PARAM#define YYPARSE_PARAM_DECL YYPARSE_PARAM_TYPE YYPARSE_PARAM;#endif /* ANSI-C/C++ */#endif /* ! YYPARSE_PARAM */intyyparse (YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL{ register int yym, yyn, yystate;#if YYDEBUG register const char *yys; if ((yys = getenv("YYDEBUG"))) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; }#endif yynerrs = 0; yyerrflag = 0; yychar = (-1); if (yyss == NULL && yygrowstack()) goto yyoverflow; yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0;yyloop: if ((yyn = yydefred[yystate])) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0;#if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, yystate, yychar, yys); }#endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) {#if YYDEBUG if (yydebug) printf("%sdebug: state %d, shifting to state %d\n", YYPREFIX, yystate, yytable[yyn]);#endif if (yyssp >= yysslim && yygrowstack()) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -