📄 lex.cc
字号:
// -*- C++ -*-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com)This file is part of groff.groff is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING. If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "eqn.h"#include "eqn.tab.h"#include "stringclass.h"#include "ptable.h"struct definition { char is_macro; char is_simple; union { int tok; char *contents; }; definition(); ~definition();};definition::definition() : is_macro(1), is_simple(0){ contents = 0;}definition::~definition(){ if (is_macro) a_delete contents;}declare_ptable(definition)implement_ptable(definition)PTABLE(definition) macro_table;static struct { const char *name; int token;} token_table[] = { "over", OVER, "smallover", SMALLOVER, "sqrt", SQRT, "sub", SUB, "sup", SUP, "lpile", LPILE, "rpile", RPILE, "cpile", CPILE, "pile", PILE, "left", LEFT, "right", RIGHT, "to", TO, "from", FROM, "size", SIZE, "font", FONT, "roman", ROMAN, "bold", BOLD, "italic", ITALIC, "fat", FAT, "bar", BAR, "under", UNDER, "accent", ACCENT, "uaccent", UACCENT, "above", ABOVE, "fwd", FWD, "back", BACK, "down", DOWN, "up", UP, "matrix", MATRIX, "col", COL, "lcol", LCOL, "rcol", RCOL, "ccol", CCOL, "mark", MARK, "lineup", LINEUP, "space", SPACE, "gfont", GFONT, "gsize", GSIZE, "define", DEFINE, "sdefine", SDEFINE, "ndefine", NDEFINE, "tdefine", TDEFINE, "undef", UNDEF, "ifdef", IFDEF, "include", INCLUDE, "copy", INCLUDE, "delim", DELIM, "chartype", CHARTYPE, "type", TYPE, "vcenter", VCENTER, "set", SET, "opprime", PRIME, "grfont", GRFONT, "gbfont", GBFONT, "split", SPLIT, "nosplit", NOSPLIT, "special", SPECIAL,};static struct { const char *name; const char *def;} def_table[] = { "ALPHA", "\\(*A", "BETA", "\\(*B", "CHI", "\\(*X", "DELTA", "\\(*D", "EPSILON", "\\(*E", "ETA", "\\(*Y", "GAMMA", "\\(*G", "IOTA", "\\(*I", "KAPPA", "\\(*K", "LAMBDA", "\\(*L", "MU", "\\(*M", "NU", "\\(*N", "OMEGA", "\\(*W", "OMICRON", "\\(*O", "PHI", "\\(*F", "PI", "\\(*P", "PSI", "\\(*Q", "RHO", "\\(*R", "SIGMA", "\\(*S", "TAU", "\\(*T", "THETA", "\\(*H", "UPSILON", "\\(*U", "XI", "\\(*C", "ZETA", "\\(*Z", "Alpha", "\\(*A", "Beta", "\\(*B", "Chi", "\\(*X", "Delta", "\\(*D", "Epsilon", "\\(*E", "Eta", "\\(*Y", "Gamma", "\\(*G", "Iota", "\\(*I", "Kappa", "\\(*K", "Lambda", "\\(*L", "Mu", "\\(*M", "Nu", "\\(*N", "Omega", "\\(*W", "Omicron", "\\(*O", "Phi", "\\(*F", "Pi", "\\(*P", "Psi", "\\(*Q", "Rho", "\\(*R", "Sigma", "\\(*S", "Tau", "\\(*T", "Theta", "\\(*H", "Upsilon", "\\(*U", "Xi", "\\(*C", "Zeta", "\\(*Z", "alpha", "\\(*a", "beta", "\\(*b", "chi", "\\(*x", "delta", "\\(*d", "epsilon", "\\(*e", "eta", "\\(*y", "gamma", "\\(*g", "iota", "\\(*i", "kappa", "\\(*k", "lambda", "\\(*l", "mu", "\\(*m", "nu", "\\(*n", "omega", "\\(*w", "omicron", "\\(*o", "phi", "\\(*f", "pi", "\\(*p", "psi", "\\(*q", "rho", "\\(*r", "sigma", "\\(*s", "tau", "\\(*t", "theta", "\\(*h", "upsilon", "\\(*u", "xi", "\\(*c", "zeta", "\\(*z", "max", "{type \"operator\" roman \"max\"}", "min", "{type \"operator\" roman \"min\"}", "lim", "{type \"operator\" roman \"lim\"}", "sin", "{type \"operator\" roman \"sin\"}", "cos", "{type \"operator\" roman \"cos\"}", "tan", "{type \"operator\" roman \"tan\"}", "sinh", "{type \"operator\" roman \"sinh\"}", "cosh", "{type \"operator\" roman \"cosh\"}", "tanh", "{type \"operator\" roman \"tanh\"}", "arc", "{type \"operator\" roman \"arc\"}", "log", "{type \"operator\" roman \"log\"}", "ln", "{type \"operator\" roman \"ln\"}", "exp", "{type \"operator\" roman \"exp\"}", "Re", "{type \"operator\" roman \"Re\"}", "Im", "{type \"operator\" roman \"Im\"}", "det", "{type \"operator\" roman \"det\"}", "and", "{roman \"and\"}", "if", "{roman \"if\"}", "for", "{roman \"for\"}", "sum", "{type \"operator\" vcenter size +5 \\(*S}", "prod", "{type \"operator\" vcenter size +5 \\(*P}", "int", "{type \"operator\" vcenter size +8 \\(is}", "union", "{type \"operator\" vcenter size +5 \\(cu}", "inter", "{type \"operator\" vcenter size +5 \\(ca}", "times", "type \"binary\" \\(mu", "ldots", "type \"inner\" { . . . }", "inf", "\\(if", "partial", "\\(pd", "nothing", "\"\"", "half", "{1 smallover 2}", "hat_def", "roman \"^\"", "hat", "accent { hat_def }", "dot_def", "back 15 \"\\v'-52M'.\\v'52M'\"", "dot", "accent { dot_def }", "dotdot_def", "back 25 \"\\v'-52M'..\\v'52M'\"", "dotdot", "accent { dotdot_def }", "tilde_def", "\"~\"", "tilde", "accent { tilde_def }", "utilde_def", "\"\\v'75M'~\\v'-75M'\"", "utilde", "uaccent { utilde_def }", "vec_def", "up 52 size -5 \\(->", "vec", "accent { vec_def }", "dyad_def", "up 52 size -5 {\\(<- back 60 \\(->}", "dyad", "accent { dyad_def }", "==", "type \"relation\" \\(==", "!=", "type \"relation\" \\(!=", "+-", "type \"binary\" \\(+-", "->", "type \"relation\" \\(->", "<-", "type \"relation\" \\(<-", "<<", "{ < back 20 < }", ">>", "{ > back 20 > }", "...", "type \"inner\" vcenter { . . . }", "prime", "'", "approx", "type \"relation\" \"\\(~=\"", "grad", "\\(gr", "del", "\\(gr", "cdot", "type \"binary\" vcenter .", "dollar", "$",}; void init_table(const char *device){ for (int i = 0; i < sizeof(token_table)/sizeof(token_table[0]); i++) { definition *def = new definition; def->is_macro = 0; def->tok = token_table[i].token; macro_table.define(token_table[i].name, def); } for (i = 0; i < sizeof(def_table)/sizeof(def_table[0]); i++) { definition *def = new definition; def->is_macro = 1; def->contents = strsave(def_table[i].def); def->is_simple = 1; macro_table.define(def_table[i].name, def); } definition *def = new definition; def->is_macro = 1; def->contents = strsave("1"); macro_table.define(device, def);}class input { input *next;public: input(input *p); virtual ~input(); virtual int get() = 0; virtual int peek() = 0; virtual int get_location(char **, int *); friend int get_char(); friend int peek_char(); friend int get_location(char **, int *); friend void init_lex(const char *str, const char *filename, int lineno);};class file_input : public input { FILE *fp; char *filename; int lineno; string line; const char *ptr; int read_line();public: file_input(FILE *, const char *, input *); ~file_input(); int get(); int peek(); int get_location(char **, int *);};class macro_input : public input { char *s; char *p;public: macro_input(const char *, input *); ~macro_input(); int get(); int peek();};class top_input : public macro_input { char *filename; int lineno; public: top_input(const char *, const char *, int, input *); ~top_input(); int get(); int get_location(char **, int *);};class argument_macro_input: public input { char *s; char *p; char *ap; int argc; char *argv[9];public: argument_macro_input(const char *, int, char **, input *); ~argument_macro_input(); int get(); int peek();};input::input(input *x) : next(x){}input::~input(){}int input::get_location(char **, int *){ return 0;}file_input::file_input(FILE *f, const char *fn, input *p): input(p), lineno(0), ptr(""){ fp = f; filename = strsave(fn);}file_input::~file_input(){ a_delete filename; fclose(fp);}int file_input::read_line(){ for (;;) { line.clear(); lineno++; for (;;) { int c = getc(fp); if (c == EOF) break; else if (illegal_input_char(c)) lex_error("illegal input character code %1", c); else { line += char(c); if (c == '\n') break; } } if (line.length() == 0) return 0; if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'E' && (line[2] == 'Q' || line[2] == 'N') && (line.length() == 3 || line[3] == ' ' || line[3] == '\n' || compatible_flag))) { line += '\0'; ptr = line.contents(); return 1; } }}int file_input::get(){ if (*ptr != '\0' || read_line()) return *ptr++ & 0377; else return EOF;}int file_input::peek(){ if (*ptr != '\0' || read_line()) return *ptr; else return EOF;}int file_input::get_location(char **fnp, int *lnp){ *fnp = filename; *lnp = lineno; return 1;}macro_input::macro_input(const char *str, input *x) : input(x){ p = s = strsave(str);}macro_input::~macro_input(){ a_delete s;}int macro_input::get(){ if (p == 0 || *p == '\0') return EOF; else return *p++ & 0377;}int macro_input::peek(){ if (p == 0 || *p == '\0') return EOF; else return *p & 0377;}top_input::top_input(const char *str, const char *fn, int ln, input *x): macro_input(str, x), lineno(ln){ filename = strsave(fn);}top_input::~top_input(){ a_delete filename;}int top_input::get(){ int c = macro_input::get(); if (c == '\n') lineno++; return c;}int top_input::get_location(char **fnp, int *lnp){ *fnp = filename; *lnp = lineno; return 1;}// Character respresenting $1. Must be illegal input character.#define ARG1 14argument_macro_input::argument_macro_input(const char *body, int ac, char **av, input *x): input(x), argc(ac), ap(0){ for (int i = 0; i < argc; i++) argv[i] = av[i]; p = s = strsave(body); int j = 0; for (i = 0; s[i] != '\0'; i++) if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') { if (s[i+1] != '0') s[j++] = ARG1 + s[++i] - '1'; } else s[j++] = s[i]; s[j] = '\0';}argument_macro_input::~argument_macro_input(){ for (int i = 0; i < argc; i++) a_delete argv[i]; a_delete s;}int argument_macro_input::get(){ if (ap) { if (*ap != '\0') return *ap++ & 0377; ap = 0; } if (p == 0) return EOF; while (*p >= ARG1 && *p <= ARG1 + 8) { int i = *p++ - ARG1; if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { ap = argv[i]; return *ap++ & 0377; } } if (*p == '\0') return EOF; return *p++ & 0377;}int argument_macro_input::peek(){ if (ap) { if (*ap != '\0') return *ap & 0377; ap = 0; } if (p == 0) return EOF; while (*p >= ARG1 && *p <= ARG1 + 8) { int i = *p++ - ARG1; if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { ap = argv[i]; return *ap & 0377; } } if (*p == '\0') return EOF; return *p & 0377;}static input *current_input = 0;/* we insert a newline between input from different levels */int get_char(){ if (current_input == 0) return EOF; else { int c = current_input->get(); if (c != EOF) return c; else { input *tem = current_input; current_input = current_input->next; delete tem; return '\n'; } }}int peek_char(){ if (current_input == 0) return EOF; else { int c = current_input->peek(); if (c != EOF) return c; else return '\n'; }}int get_location(char **fnp, int *lnp){ for (input *p = current_input; p; p = p->next) if (p->get_location(fnp, lnp)) return 1; return 0;}string token_buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -