📄 lexan.l
字号:
%{/*| This material contains proprietary software of Entropic Processing, Inc.| Any reproduction, distribution, or publication without the the prior | written permission of Entropic Processing, Inc. is strictly prohibited| Any public distribution of copies of this work authorized in writing by| Entropic Processing, Inc. must bear the notice | | "Copyright 1986 Entropic Processing, Inc."| | Written by: Alan Parker, based on amsim by Joseph T. Buck| | Module: lexan.l | | Lexical analyzer for select. Since keywords that may be abbreviated are| used, start states are used to decide what type of token to expect at| a given point. | | A token value may be an integer, a string (for filenames), a floating| value, or a pointer to a structure indicating a register or memory| location. | | We redefine the input macro to get characters using the Getc function in| the "io.c" module. This function takes care of prompting and log files.*/ #ifdef SCCS static char *sccs_id = "%W% %G% EPI";#endif#ifdef USGvoid exit(), clearerr();#endif#include "parsetab.h"/* Redefine Lex's input macro to use our Getc function and get rid of yylineno*/#undef input#define input()((yytchar=yysptr>yysbuf?U(*--yysptr):Getc(yyin))==EOF?0:yytchar)#include <ctype.h>#include <stdio.h>extern YYSTYPE yylval;char *savestring(), *quotestring();double atof();long atol(), gethex();int com_file_depth = 0;/* prev_command saves the last STEP, EXAMINE, or INSTRUCTION */static prev_command = EXAMINE;struct key { char *text; int code;};/* keyword tables. prim gives keywords at beginning of line. */static struct key prim[] = { "clear", CLEAR, "close", CLOSE, "from", FROM, "header", HEADER, "help", HELP, "log", LOG, "quit", QUIT, "select", SELECT, "show", SHOW, "size", SIZE, "to", TO, "write", WRITE, "version", VERSION, 0, 0};static struct key kshow[] = { "last", LAST, "select", SELECT, "to", TO, 0, 0};static struct key kto[] = { "with", WITH, "without", WITHOUT, 0, 0};/* Start states:At the beginning of a line, we're in state BOL. We expect a keywordfrom the primary keyword table. Other states:S_KEY: want second keyword for a SHOW command.T_KEY: want second keyword for TO command.FILEARG: want a file argument Or we want a string argumentEAT: this state eats input till end of line, returns token for EOL It's meant to be used after an error has been seenDOARG: rest of line returned as a stringQUERY: want query*/%}%Start S_KEY T_KEY FILEARG BOL EAT DOARG QUERYL [A-Za-z]A [A-Za-z0-9_]D [0-9]KEY {L}{A}*S [-+]?E [eE]{S}{D}+H [0-9A-Fa-f]NB [^ \t\n]NQ [^\"\n]NA [^\'\n]EQ \\\"EA \\\'%%<DOARG>.*$ { yylval.sval = savestring(yytext); BEGIN ARGS; return STRING; }<BOL>"@"[^ \t\n;]+ { (void) command_file (yytext + 1);}";" { BEGIN BOL; return ';'; /* statement separator */ }^"!".*\n { /* shell escape : no token returned */ yytext[yyleng-1] = '\0'; /* zap the newline */ (void) system(yytext+1); }<BOL>{KEY} { /* look up the keyword, select next state. Always return the keyword as the token. */ int v = key_lookup(prim,""); switch (v) { case PRINT: BEGIN P_KEY; break; case CLEAR: BEGIN C_KEY; break; case SHOW: BEGIN S_KEY; break; case MONITOR: BEGIN M_KEY; break; case LOAD: case DUMP: case RESTORE: case LOG: case DEFINE: case SYMBOL: case CD: case PIPE: BEGIN FILEARG; break; case QUI: BEGIN EAT; errmsg("QUIT must be typed in full\n"); msg_prt++; return BAD; case BAD: BEGIN EAT; break; case EXAMINE: case INSTRUCTION: case STEP: prev_command = v; default: BEGIN ARGS; break; } return v; }<P_KEY>{KEY} { int v = key_lookup(kprint,"print "); if (v==BAD) BEGIN EAT; else BEGIN ARGS; return v; }<M_KEY>{KEY} { int v = key_lookup(kmon,"monitor "); if (v==BAD) BEGIN EAT; else BEGIN ARGS; if (v) return v; /* wait for next token if 0 */ }<S_KEY>{KEY} { int v = key_lookup(kshow,"show "); if (v==BAD) BEGIN EAT; else if (v==DEFINE) BEGIN FILEARG; else BEGIN ARGS; return v; }<C_KEY>{KEY} { int v = key_lookup(kclear,"clear "); if (v==BAD) BEGIN EAT; else BEGIN ARGS; return v; }<EAT>.*\n { /* EAT state eats rest of line after bad keyword */ BEGIN BOL; return 0; }<FILEARG>[^ \t\n;]+ { /* Filename: any sequence of nonblanks, but ; */ yylval.sval = savestring(yytext); BEGIN ARGS; return STRING; }<ARGS>do[ \t]* { BEGIN DOARG; return yylval.ival = DO;}<ARGS>DO[ \t]* { BEGIN DOARG; return yylval.ival = DO;}<ARGS>{D}{H}*[hH] { yylval.lval = gethex(yytext); return VALUE; }<ARGS>[1-9]{D}* { /* leading zero means hex */ yylval.lval = atol(yytext); return VALUE; }<ARGS>{D}{H}* { /* allow H to be omitted if hex letter present */ yylval.lval = gethex(yytext); return VALUE; }<ARGS>"%"?{L}{A}* { /* pseudo-regs begin with "%". First see if it's * a special token name. If not, see if it's a * register. If not, see if it's a defined symbol. */ if (yylval.ival = srch_token (yytext)) return yylval.ival; else if (!(yylval.locn = lookup_reg(yytext))) { SYMDEF *p = get_def(yytext); if (p) { yylval = p->ddef; return p->stype; } errmsg1("No such symbol or register: %s\n", yytext); msg_prt++; BEGIN EAT; return BAD; } return LOCATION; }<ARGS>{MEM}[1-9]{D}* { /* We have something like I.34 */ yylval.locn = make_locn(bank(*yytext), atol(yytext+2)); return LOCATION; }<ARGS>{MEM}{H}+[Hh]? { /* Something like A.34h or B.2c */ yylval.locn = make_locn(bank(*yytext), gethex(yytext+2)); return LOCATION; }<ARGS>{D}*"."{D}+ { /* no minus here; parser has unary minus op */ yylval.dval = atof(yytext); return FLOVAL; }<ARGS>{D}+"." { yylval.dval = atof(yytext); return FLOVAL;}<ARGS>"," { return (yylval.ival = ':'); /* synonym for ':' */}<ARGS>\\\/ { return (yylval.ival = FUTURE);}<ARGS>"<<" { return (yylval.ival = LS); }<ARGS>">>" { return (yylval.ival = RS); }<ARGS>\'({NA}|{EA})*\' { /* to put a quote in a string, precede with \ */ yytext[yyleng-1] = '\0'; yylval.sval = quotestring (yytext + 1); return STRING; }<ARGS>\'({NA}|{EA})*$ { /* catch mismatched strings: no multiline strings */ errmsg ("Missing \'.\n"); BEGIN EAT; return BAD; }<ARGS>\"({NQ}|{EQ})*\" { /* to put a quote in a string, precede with \ */ yytext[yyleng-1] = '\0'; yylval.sval = quotestring (yytext + 1); return STRING; }<ARGS>\"({NQ}|{EQ})*$ { /* catch mismatched strings: no multiline strings */ errmsg ("Missing \".\n"); BEGIN EAT; return BAD; } <BOL>\n { /* Blank line is a command: push back the \n */ if (!com_file_depth) { /* not in com files */ BEGIN ARGS; unput ('\n'); return prev_command; } }[ \t] ; /* always ignore blanks, tabs */\n { /* newline ends command */ BEGIN BOL; return 0;}"==" { return (yylval.ival = EQL); }"!=" { return (yylval.ival = NE); }">=" { return (yylval.ival = GE); }"<=" { return (yylval.ival = LE); }<ARGS>. { /* single character tokens */ return (yylval.ival = yytext[0]); }. { errmsg1("Unexpected character '%c'\n",yytext[0]); msg_prt++; BEGIN EAT; return BAD; }<BOL>#.*\n ; /* if whole line is commented out, eat newline */#.*$ ; /* comment, ignore */%%static int key_lookup(table,msg)struct key *table;char *msg;{ char *s = yytext; while (*s) { if (isupper(*s)) *s = tolower(*s); s++; } while (table->text) { yylval.sval = table->text; if (strncmp(yytext,table->text,yyleng) == 0) return table->code; else table++; } errmsg2("Unknown command: \"%s%s\"\n",msg,yytext); msg_prt++; return BAD;}/* If any non-hex characters are in the string, gethex returns immediately.*/long gethex(s)char *s;{ int hex = 0; while (*s) { if (isupper(*s)) *s = tolower(*s); if (isdigit(*s)) hex = 16*hex - '0' + *s; else if (*s>='a' && *s<='f') hex = 16*hex - 'a' + 10 + *s; else return hex; s++; } return hex;}/* put lexical analyzer in proper state */init_lex(){ BEGIN BOL;}#define MAX_COM_DEPTH 3static FILE *fd_stack[MAX_COM_DEPTH+1];command_file (name)char *name;{ FILE *cmd_fd; if (com_file_depth >= MAX_COM_DEPTH) { errmsg ("Maximum nesting depth for command files exceeded\n"); return 0; }/* delete any leading spaces */ while (isspace(*name)) name++; if ((cmd_fd = fopen (name, "r")) == NULL) errmsg1 ("Can't open command file %s\n", name); else { fd_stack[com_file_depth++] = yyin; yyin = cmd_fd; return 1; } return 0;}/* The lexical analyzer calls yywrap at EOF. If input is a terminal, make the user type QUIT. */staticyywrap() { static int nquit = 0; if (com_file_depth) { (void) fclose (yyin); yyin = fd_stack[--com_file_depth]; fd_stack[com_file_depth] = NULL; return 0; } else if (isatty(fileno(yyin))) { errmsg(nquit > 2 ? "OK, if you insist...\n" : "Type QUIT to exit\n"); if (nquit > 2) exit(1); nquit++; clearerr(yyin); return 0; } eof_flag = 1; return 1;}/* Close any open command files */abort_command_file () { int n = com_file_depth; while (com_file_depth) (void) yywrap (); eof_flag = 0; return n;}staticbank (key)char key;{ if (isupper(key)) key = tolower (key); switch (key) { case 'a': return B_ARAM; case 'b': return B_BRAM; case 'd': return B_DMEM; case 'i': return B_IRAM; case 'p': return B_PMEM; case 's': return B_BASE; default: errmsg ("Internal error in lexical analyzer!\n"); } return 0;}/* function tokens that can appear in ARGS state. */static struct fn_entry { char *fn_name; int fn_tokval;};struct fn_entry fn_table[] = { "sqrt", SQRT, "do", DO, 0, 0};staticsrch_token (name)char *name;{ register struct fn_entry *p; for (p = fn_table; p->fn_name; p++) { if (strcmp (name, p->fn_name) == 0) return p->fn_tokval; } return 0;}/* This function is called from the parser on an error. It zaps the rest of the current command (unless the current token is an end-of-line mark).*/lex_reset () { int c; if (*yytext != '\n' && *yytext != ';') while ((c = yyinput()) != '\n' && c != ';') /* null statement */; BEGIN BOL;}static char *quotestring(s)char *s;{ /* process escape sequences in quoted string */ /* YYLMAX is the size of LEX's token buffer, which is the maximum size string the lexical analyzer can pass to quotestring */ char *p, buf[YYLMAX]; p = buf; while (*s) { if (*s != '\\') *p++ = *s++; else { *p++ = slash (*++s); s++; } } *p = '\0'; return savestring(buf);}/* handle beasts like \n in strings and character constants */slash(c)char c;{ switch (c) { case 'n': return '\n'; case 'r': return '\r'; case 'b': return '\b'; case 'e': return '\033'; case '0': return '\0'; case 't': return '\t'; case 'f': return '\f'; default: return c; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -