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

📄 parse.y

📁 nedit 是一款linux下的开发源码的功能强大的编辑器
💻 Y
📖 第 1 页 / 共 2 页
字号:
            | numexpr GT numexpr  {                ADD_OP(OP_GT);            }            | numexpr GE numexpr  {                ADD_OP(OP_GE);            }            | numexpr LT numexpr  {                ADD_OP(OP_LT);            }            | numexpr LE numexpr  {                ADD_OP(OP_LE);            }            | numexpr EQ numexpr  {                ADD_OP(OP_EQ);            }            | numexpr NE numexpr  {                ADD_OP(OP_NE);            }            | numexpr '&' numexpr {                ADD_OP(OP_BIT_AND);            }            | numexpr '|' numexpr  {                ADD_OP(OP_BIT_OR);            }            | numexpr and numexpr %prec AND {                ADD_OP(OP_AND); SET_BR_OFF($2, GetPC());            }            | numexpr or numexpr %prec OR {                ADD_OP(OP_OR); SET_BR_OFF($2, GetPC());            }            | NOT numexpr {                ADD_OP(OP_NOT);            }            | INCR SYMBOL {                ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_INCR);                ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);            }            | SYMBOL INCR {                ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);                ADD_OP(OP_INCR); ADD_OP(OP_ASSIGN); ADD_SYM($1);            }            | DECR SYMBOL {                ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_DECR);                ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);            }            | SYMBOL DECR {                ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);                ADD_OP(OP_DECR); ADD_OP(OP_ASSIGN); ADD_SYM($1);            }            | numexpr IN numexpr {                ADD_OP(OP_IN_ARRAY);            }            ;while:  WHILE {            $$ = GetPC(); StartLoopAddrList();        }        ;for:    FOR {            StartLoopAddrList(); $$ = GetPC();        }        ;else:   ELSE {            ADD_OP(OP_BRANCH); $$ = GetPC(); ADD_BR_OFF(0);        }        ;cond:   /* nothing */ {            ADD_OP(OP_BRANCH_NEVER); $$ = GetPC(); ADD_BR_OFF(0);        }        | numexpr {            ADD_OP(OP_BRANCH_FALSE); $$ = GetPC(); ADD_BR_OFF(0);        }        ;and:    AND {            ADD_OP(OP_DUP); ADD_OP(OP_BRANCH_FALSE); $$ = GetPC();            ADD_BR_OFF(0);        }        ;or:     OR {            ADD_OP(OP_DUP); ADD_OP(OP_BRANCH_TRUE); $$ = GetPC();            ADD_BR_OFF(0);        }        ;blank:  /* nothing */        | blank '\n'        ;%% /* User Subroutines Section *//*** Parse a null terminated string and create a program from it (this is the** parser entry point).  The program created by this routine can be** executed using ExecuteProgram.  Returns program on success, or NULL** on failure.  If the command failed, the error message is returned** as a pointer to a static string in msg, and the length of the string up** to where parsing failed in stoppedAt.*/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;}

⌨️ 快捷键说明

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