📄 token.c
字号:
/* * token - read input file characters into tokens * * Copyright (C) 1999 David I. Bell and Ernest Bowen * * Primary author: David I. Bell * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL. You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * @(#) $Revision: 29.10 $ * @(#) $Id: token.c,v 29.10 2006/06/24 18:43:05 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/token.c,v $ * * Under source code control: 1990/02/15 01:48:25 * File existed as early as: before 1990 * * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include <setjmp.h>#include "calc.h"#include "token.h"#include "string.h"#include "args.h"#include "math_error.h"#define isletter(ch) ((((ch) >= 'a') && ((ch) <= 'z')) || \ (((ch) >= 'A') && ((ch) <= 'Z')))#define isdigit(ch) (((ch) >= '0') && ((ch) <= '9'))#define issymbol(ch) (isletter(ch) || isdigit(ch) || ((ch) == '_'))#define isoctal(ch) (((ch) >= '0') && ((ch) <= '7'))#define STRBUFSIZE 1024/* * Current token. */static struct { short t_type; /* type of token */ char *t_sym; /* symbol name */ long t_strindex; /* index of string value */ long t_numindex; /* index of numeric value */} curtoken;static BOOL rescan; /* TRUE to reread current token */static BOOL newlines; /* TRUE to return newlines as tokens */static BOOL allsyms; /* TRUE if always want a symbol token */static STRINGHEAD strings; /* list of constant strings */static char *numbuf; /* buffer for numeric tokens */static long numbufsize; /* current size of numeric buffer */long errorcount = 0; /* number of compilation errors *//* * Table of keywords */struct keyword { char *k_name; /* keyword name */ int k_token; /* token number */};static struct keyword keywords[] = { {"if", T_IF}, {"else", T_ELSE}, {"for", T_FOR}, {"while", T_WHILE}, {"do", T_DO}, {"continue", T_CONTINUE}, {"break", T_BREAK}, {"goto", T_GOTO}, {"return", T_RETURN}, {"local", T_LOCAL}, {"global", T_GLOBAL}, {"static", T_STATIC}, {"switch", T_SWITCH}, {"case", T_CASE}, {"default", T_DEFAULT}, {"quit", T_QUIT}, {"exit", T_QUIT}, {"define", T_DEFINE}, {"read", T_READ}, {"show", T_SHOW}, {"help", T_HELP}, {"write", T_WRITE}, {"mat", T_MAT}, {"obj", T_OBJ}, {"print", T_PRINT}, {"cd", T_CD}, {"undefine", T_UNDEFINE}, {"abort", T_ABORT}, {NULL, 0}};static void eatcomment(void);static void eatstring(int quotechar);static void eatline(void);static int eatsymbol(void);static int eatnumber(void);/* * Initialize all token information. */voidinittokens(void){ initstr(&strings); newlines = FALSE; allsyms = FALSE; rescan = FALSE; setprompt(conf->prompt1);}/* * Set the new token mode according to the specified flag, and return the * previous value of the flag. */inttokenmode(int flag){ int oldflag; oldflag = TM_DEFAULT; if (newlines) oldflag |= TM_NEWLINES; if (allsyms) oldflag |= TM_ALLSYMS; newlines = FALSE; allsyms = FALSE; if (flag & TM_NEWLINES) newlines = TRUE; if (flag & TM_ALLSYMS) allsyms = TRUE; setprompt(newlines ? conf->prompt1 : conf->prompt2); return oldflag;}/* * Routine to read in the next token from the input stream. * The type of token is returned as a value. If the token is a string or * symbol name, information is saved so that the value can be retrieved. */intgettoken(void){ int ch; /* current input character */ int type; /* token type */ if (rescan) { /* rescanning */ rescan = FALSE; return curtoken.t_type; } curtoken.t_sym = NULL; curtoken.t_strindex = 0; curtoken.t_numindex = 0; type = T_NULL; while (type == T_NULL) { ch = nextchar(); if (allsyms && ch!=' ' && ch!=';' && ch!='"' && ch!='\'' && ch!='\n' && ch!=EOF) { reread(); type = eatsymbol(); break; } switch (ch) { case ' ': case '\t': case '\r': case '\v': case '\f': case '\0': break; case '\n': if (newlines) type = T_NEWLINE; break; case EOF: type = T_EOF; break; case '{': type = T_LEFTBRACE; break; case '}': type = T_RIGHTBRACE; break; case '(': type = T_LEFTPAREN; break; case ')': type = T_RIGHTPAREN; break; case '[': type = T_LEFTBRACKET; break; case ']': type = T_RIGHTBRACKET; break; case ';': type = T_SEMICOLON; break; case ':': type = T_COLON; break; case ',': type = T_COMMA; break; case '?': type = T_QUESTIONMARK; break; case '@': type = T_AT; break; case '`': type = T_BACKQUOTE; break; case '$': type = T_DOLLAR; break; case '"': case '\'': type = T_STRING; eatstring(ch); break; case '^': switch (nextchar()) { case '=': type = T_POWEREQUALS; break; default: type = T_POWER; reread(); } break; case '=': switch (nextchar()) { case '=': type = T_EQ; break; default: type = T_ASSIGN; reread(); } break; case '+': switch (nextchar()) { case '+': type = T_PLUSPLUS; break; case '=': type = T_PLUSEQUALS; break; default: type = T_PLUS; reread(); } break; case '-': switch (nextchar()) { case '-': type = T_MINUSMINUS; break; case '=': type = T_MINUSEQUALS; break; case '>': type = T_ARROW; break; default: type = T_MINUS; reread(); } break; case '*': switch (nextchar()) { case '=': type = T_MULTEQUALS; break; case '*': switch (nextchar()) { case '=': type = T_POWEREQUALS; break; default: type = T_POWER; reread(); } break; default: type = T_MULT; reread(); } break; case '/': switch (nextchar()) { case '/': switch (nextchar()) { case '=': type = T_SLASHSLASHEQUALS; break; default: reread(); type = T_SLASHSLASH; break; } break; case '=': type = T_DIVEQUALS; break; case '*': eatcomment(); break; default: type = T_DIV; reread(); } break; case '%': switch (nextchar()) { case '=': type = T_MODEQUALS; break; default: type = T_MOD; reread(); } break; case '<': switch (nextchar()) { case '=': type = T_LE; break; case '<': switch (nextchar()) { case '=': type = T_LSHIFTEQUALS; break; default: reread(); type = T_LEFTSHIFT; break; } break; default: type = T_LT; reread(); } break; case '>': switch (nextchar()) { case '=': type = T_GE; break; case '>': switch (nextchar()) { case '=': type = T_RSHIFTEQUALS; break; default: reread(); type = T_RIGHTSHIFT; break; } break; default: type = T_GT; reread(); } break; case '&': switch (nextchar()) { case '&': type = T_ANDAND; break; case '=': type = T_ANDEQUALS; break; default: type = T_AND; reread(); break; } break; case '|': switch (nextchar()) { case '|': type = T_OROR; break; case '=': type = T_OREQUALS; break; default: type = T_OR; reread(); break; } break; case '!': switch (nextchar()) { case '=': type = T_NE; break; default: type = T_NOT; reread(); break; } break; case '#': switch(nextchar()) { case '=': type = T_HASHEQUALS; break; case '!': case '#': eatline(); break; case '\n': reread(); break; default: type = T_HASH; reread(); } break; case '~': switch (nextchar()) { case '=': type = T_TILDEEQUALS; break; default: type = T_TILDE; reread(); } break; case '\\': switch (nextchar()) { case '\n': setprompt(conf->prompt2); break; case '=': type = T_BACKSLASHEQUALS; break; default: type = T_BACKSLASH; reread(); } break; default: if (isletter(ch) || ch == '_') { reread(); type = eatsymbol(); break; } if (isdigit(ch) || (ch == '.')) { reread(); type = eatnumber(); break; } scanerror(T_NULL, "Unknown token character '%c'", ch); } } curtoken.t_type = (short)type; return type;}/* * Continue to eat up a comment string. * The leading slash-asterisk has just been scanned at this point. */static voideatcomment(void){ int ch; setprompt(conf->prompt2); for (;;) { ch = nextchar(); if (ch == '*') { ch = nextchar(); if (ch == '/') break; reread(); } if (ch == EOF || ch == '\0') { scanerror(T_NULL, "Unterminated comment"); reread(); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -