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

📄 lex.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 3 页
字号:
// -*- 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 "pic.h"#include "ptable.h"#include "object.h"#include "pic.tab.h"declare_ptable(char)implement_ptable(char)PTABLE(char) macro_table;class macro_input : public input {  char *s;  char *p;public:  macro_input(const char *);  ~macro_input();  int get();  int peek();};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 **);  ~argument_macro_input();  int get();  int peek();};input::input() : next(0){}input::~input(){}int input::get_location(const char **, int *){  return 0;}file_input::file_input(FILE *f, const char *fn): lineno(0), ptr(""), filename(fn){  fp = f;}file_input::~file_input(){  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] == 'P'	  && (line[2] == 'S' || line[2] == 'E' || line[2] == 'F')	  && (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 (unsigned char)*ptr++;  else    return EOF;}int file_input::peek(){  if (*ptr != '\0' || read_line())    return (unsigned char)*ptr;  else    return EOF;}int file_input::get_location(const char **fnp, int *lnp){  *fnp = filename;  *lnp = lineno;  return 1;}macro_input::macro_input(const char *str){  p = s = strsave(str);}macro_input::~macro_input(){  a_delete s;}int macro_input::get(){  if (p == 0 || *p == '\0')    return EOF;  else    return (unsigned char)*p++;}int macro_input::peek(){  if (p == 0 || *p == '\0')    return EOF;  else    return (unsigned char)*p;}// Character respresenting $1.  Must be illegal input character.#define ARG1 14char *process_body(const char *body){  char *s = strsave(body);  int j = 0;  for (int 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';  return s;}argument_macro_input::argument_macro_input(const char *body, int ac, char **av): argc(ac), ap(0){  for (int i = 0; i < argc; i++)    argv[i] = av[i];  p = s = process_body(body);}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 (unsigned char)*ap++;    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 (unsigned char)*ap++;    }  }  if (*p == '\0')    return EOF;  return (unsigned char)*p++;}int argument_macro_input::peek(){  if (ap) {    if (*ap != '\0')      return (unsigned char)*ap;    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 (unsigned char)*ap;    }  }  if (*p == '\0')    return EOF;  return (unsigned char)*p;}class input_stack {  static input *current_input;  static int bol_flag;public:  static void push(input *);  static void clear();  static int get_char();  static int peek_char();  static int get_location(const char **fnp, int *lnp);  static void push_back(unsigned char c, int was_bol = 0);  static int bol();};input *input_stack::current_input = 0;int input_stack::bol_flag = 0;inline int input_stack::bol(){  return bol_flag;}void input_stack::clear(){  while (current_input != 0) {    input *tem = current_input;    current_input = current_input->next;    delete tem;  }  bol_flag = 1;}void input_stack::push(input *in){  in->next = current_input;  current_input = in;}void lex_init(input *top){  input_stack::clear();  input_stack::push(top);}void lex_cleanup(){  while (input_stack::get_char() != EOF)    ;}int input_stack::get_char(){  while (current_input != 0) {    int c = current_input->get();    if (c != EOF) {      bol_flag = c == '\n';      return c;    }    // don't pop the top-level input off the stack    if (current_input->next == 0)      return EOF;    input *tem = current_input;    current_input = current_input->next;    delete tem;  }  return EOF;}int input_stack::peek_char(){  while (current_input != 0) {    int c = current_input->peek();    if (c != EOF)      return c;    if (current_input->next == 0)      return EOF;    input *tem = current_input;    current_input = current_input->next;    delete tem;  }  return EOF;}class char_input : public input {  int c;public:  char_input(int);  int get();  int peek();};char_input::char_input(int n) : c((unsigned char)n){}int char_input::get(){  int n = c;  c = EOF;  return n;}int char_input::peek(){  return c;}void input_stack::push_back(unsigned char c, int was_bol){  push(new char_input(c));  bol_flag = was_bol;}int input_stack::get_location(const char **fnp, int *lnp){  for (input *p = current_input; p; p = p->next)    if (p->get_location(fnp, lnp))      return 1;  return 0;}string context_buffer;string token_buffer;double token_double;int token_int;void interpolate_macro_with_args(const char *body){  char *argv[9];  int argc = 0;  for (int i = 0; i < 9; i++)    argv[i] = 0;  int level = 0;  int c;  enum { NORMAL, IN_STRING, IN_STRING_QUOTED } state = NORMAL;  do {    token_buffer.clear();    for (;;) {      c = input_stack::get_char();      if (c == EOF) {	lex_error("end of input while scanning macro arguments");	break;      }      if (state == NORMAL && level == 0 && (c == ',' || c == ')')) {	if (token_buffer.length() > 0) {	  token_buffer +=  '\0';	  argv[argc] = strsave(token_buffer.contents());	}	// for `foo()', argc = 0	if (argc > 0 || c != ')' || i > 0)	  argc++;	break;      }      token_buffer += char(c);      switch (state) {      case NORMAL:	if (c == '"')	  state = IN_STRING;	else if (c == '(')	  level++;	else if (c == ')')	  level--;	break;      case IN_STRING:	if (c == '"')	  state = NORMAL;	else if (c == '\\')	  state = IN_STRING_QUOTED;	break;      case IN_STRING_QUOTED:	state = IN_STRING;	break;      }    }  } while (c != ')' && c != EOF);  input_stack::push(new argument_macro_input(body, argc, argv));}static int docmp(const char *s1, int n1, const char *s2, int n2){  if (n1 < n2) {    int r = memcmp(s1, s2, n1);    return r ? r : -1;  }  else if (n1 > n2) {    int r = memcmp(s1, s2, n2);    return r ? r : 1;  }  else    return memcmp(s1, s2, n1);}int lookup_keyword(const char *str, int len){  static struct keyword {    const char *name;    int token;  } table[] = {    "Here", HERE,    "above", ABOVE,    "aligned", ALIGNED,    "and", AND,    "arc", ARC,    "arrow", ARROW,    "at", AT,    "atan2", ATAN2,    "below", BELOW,    "between", BETWEEN,    "bottom", BOTTOM,    "box", BOX,    "by", BY,    "ccw", CCW,    "center", CENTER,    "chop", CHOP,    "circle", CIRCLE,    "command", COMMAND,    "copy", COPY,    "cos", COS,    "cw", CW,    "dashed", DASHED,    "define", DEFINE,    "diam", DIAMETER,    "diameter", DIAMETER,    "do", DO,    "dotted", DOTTED,    "down", DOWN,    "ellipse", ELLIPSE,    "else", ELSE,    "end", END,    "exp", EXP,    "fill", FILL,    "filled", FILL,    "for", FOR,    "from", FROM,    "height", HEIGHT,    "ht", HEIGHT,    "if", IF,    "int", INT,    "invis", INVISIBLE,    "invisible", INVISIBLE,    "last", LAST,    "left", LEFT,    "line", LINE,    "ljust", LJUST,    "log", LOG,    "lower", LOWER,    "max", K_MAX,    "min", K_MIN,    "move", MOVE,    "of", OF,    "plot", PLOT,    "print", PRINT,    "rad", RADIUS,    "radius", RADIUS,    "rand", RAND,    "reset", RESET,    "right", RIGHT,    "rjust", RJUST,    "same", SAME,    "sh", SH,    "sin", SIN,    "spline", SPLINE,    "sprintf", SPRINTF,    "sqrt", SQRT,    "start", START,    "the", THE,    "then", THEN,    "thick", THICKNESS,    "thickness", THICKNESS,    "thru", THRU,    "to", TO,    "top", TOP,    "undef", UNDEF,    "until", UNTIL,    "up", UP,    "upper", UPPER,    "way", WAY,    "wid", WIDTH,    "width", WIDTH,    "with", WITH,  };    const keyword *start = table;  const keyword *end = table + sizeof(table)/sizeof(table[0]);  while (start < end) {    // start <= target < end    const keyword *mid = start + (end - start)/2;        int cmp = docmp(str, len, mid->name, strlen(mid->name));    if (cmp == 0)      return mid->token;    if (cmp < 0)      end = mid;    else      start = mid + 1;  }  return 0;}int get_token_after_dot(int c){  // get_token deals with the case where c is a digit  switch (c) {  case 'h':    input_stack::get_char();    c = input_stack::peek_char();    if (c == 't') {      input_stack::get_char();      context_buffer = ".ht";      return DOT_HT;    }    else if (c == 'e') {      input_stack::get_char();      c = input_stack::peek_char();      if (c == 'i') {	input_stack::get_char();	c = input_stack::peek_char();	if (c == 'g') {	  input_stack::get_char();	  c = input_stack::peek_char();	  if (c == 'h') {	    input_stack::get_char();	    c = input_stack::peek_char();	    if (c == 't') {	      input_stack::get_char();	      context_buffer = ".height";	      return DOT_HT;	    }	    input_stack::push_back('h');	  }	  input_stack::push_back('g');	}	input_stack::push_back('i');      }      input_stack::push_back('e');    }    input_stack::push_back('h');    return '.';  case 'x':    input_stack::get_char();    context_buffer = ".x";    return DOT_X;  case 'y':    input_stack::get_char();    context_buffer = ".y";    return DOT_Y;  case 'c':    input_stack::get_char();    c = input_stack::peek_char();    if (c == 'e') {      input_stack::get_char();      c = input_stack::peek_char();      if (c == 'n') {	input_stack::get_char();	c = input_stack::peek_char();	if (c == 't') {	  input_stack::get_char();	  c = input_stack::peek_char();	  if (c == 'e') {	    input_stack::get_char();	    c = input_stack::peek_char();	    if (c == 'r') {	      input_stack::get_char();	      context_buffer = ".center";	      return DOT_C;	    }	    input_stack::push_back('e');	  }	  input_stack::push_back('t');	}	input_stack::push_back('n');      }      input_stack::push_back('e');    }    context_buffer = ".c";    return DOT_C;  case 'n':    input_stack::get_char();    c = input_stack::peek_char();    if (c == 'e') {      input_stack::get_char();      context_buffer = ".ne";      return DOT_NE;    }    else if (c == 'w') {      input_stack::get_char();      context_buffer = ".nw";      return DOT_NW;    }    else {      context_buffer = ".n";      return DOT_N;    }    break;  case 'e':    input_stack::get_char();    c = input_stack::peek_char();    if (c == 'n') {      input_stack::get_char();      c = input_stack::peek_char();      if (c == 'd') {	input_stack::get_char();	context_buffer = ".end";	return DOT_END;      }      input_stack::push_back('n');      context_buffer = ".e";      return DOT_E;    }    context_buffer = ".e";    return DOT_E;  case 'w':    input_stack::get_char();    c = input_stack::peek_char();

⌨️ 快捷键说明

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