home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / p / p024 / 12.img / ADS1.LIB / CALLEX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-26  |  11.9 KB  |  442 lines

  1. /*****************************************************************************
  2.       CALLEX.C
  3.       (C) ¬⌐┼v 1988-1992  Autodesk ñ╜Ñq
  4.  
  5.       Ñ╗╡{ªíñwÑ╤ Autodesk ñ╜Ñq╡∙ÑU¬⌐┼v, ╢╚⌐≤ñU¡z▒í¬pñUÑi▒┬╗P▒zíu│\ÑiívíC
  6.       ╗╒ñUñú▒oÑHÑ⌠ª≤º╬ªí╡oªµ⌐╬ÑX¬⌐ª╣╡{ªí¬║íu¡∞⌐l╜Xív; ª²ñ╣│\▒zªb»S⌐w¡lÑ═
  7.       ¬║ñuº@ñW╡▓ªXª╣╡{ªí¬║íuÑ╪¬║╜Xív¿╧Ñ╬íCª│├÷│o├■¡lÑ═ñuº@¬║▒°Ñ≤ªpñU:
  8.  
  9.       ( i)  │]¡pñW╗Pñuº@ñW¼╥»┬║Θ░w╣∩ Autodesk ñ╜Ñq¬║▓ú½~íC
  10.       (ii)  ╕ⁿª│íu¬⌐┼v  (C) 1988-1992  Autodesk ñ╜Ñqív¬║¬⌐┼v│qºiíC
  11.  
  12.  
  13.  
  14.       AUTODESKñ╜Ñq┤ú¿╤ª╣╡{ªí╢╚¿╤º@íu├■ªⁿív¬║░╤ª╥, ª╙ÑBñú▒╞░úª│Ñ⌠ª≤┐∙╗~¬║
  15.       Ñi»αíCAUTODESKñ╜Ñq»Sª╣º_╗{Ñ⌠ª≤»S⌐wÑ╬│~ñº╛A║┘⌐╩, ÑHñ╬░╙╖~╛P░Γ⌐╥┴⌠ºt
  16.       ÑX¿π¬║½O├╥íCAUTODESKñ╜ÑqªP«╔ÑτñúÑX¿πª╣╡{ªí░⌡ªµ«╔ñ@⌐wñú╖|íuññ┬_ív⌐╬
  17.       íuº╣Ñ■╡L╗~ív¬║½O├╥íC
  18.  
  19.  
  20.   Description: Lexical analyser for the Geometry Calculator ADS application.
  21.  
  22. *****************************************************************************/
  23.  
  24.  
  25. /****************************************************************************/
  26. /*  INCLUDES                                                                */
  27. /****************************************************************************/
  28.  
  29. #include "cal.h"
  30.  
  31.  
  32. /****************************************************************************/
  33. /*  EXPORTED VARIABLES                                                      */
  34. /****************************************************************************/
  35.  
  36. lex_output_type cal_lex;              /* Output from the lexical analyser */
  37.  
  38.  
  39. /****************************************************************************/
  40. /*  STATIC VARIABLES AND FUNCTIONS                                          */
  41. /****************************************************************************/
  42.  
  43. /* Keyword table */
  44.  
  45. static struct {char *ident; symbol_type symbol;} kw[] =
  46. {
  47.     "PI",      pi_sym,
  48.     "GETVAR",  getvar_sym,
  49.     "CVUNIT",  cvunit_sym,
  50. };
  51.  
  52. #define NKWS  ELEMENTS(kw)            /* Number of keywords */
  53.  
  54. static char ch;                       /* The current character         */
  55. static char *ch_ptr;                  /* Pointer to the next character */
  56. static int  end_of_line;              /* TRUE=next_char() reached EOLN */
  57.  
  58. static void        str_toupper          _((char *str));
  59. static symbol_type is_keyword           _((char *ident));
  60. static void        next_char            _((void));
  61. static void        number               _((void));
  62. static void        number_angle_or_feet _((void));
  63.  
  64.  
  65. /****************************************************************************/
  66. /*.doc str_toupper(internal)*/
  67. /*+
  68.   Converts the given string to upper case (I cannot understand why this is
  69.   not a standard function somewhere in a standard library).
  70. -*/
  71. /****************************************************************************/
  72.  
  73.  
  74. static void
  75. /*FCN*/str_toupper(str)
  76.  
  77.   char *str;
  78. {
  79.     while ((*str = ads_toupper(*str)) != 0) {
  80.         str++;
  81.     }
  82. } /*str_toupper*/
  83.  
  84.  
  85. /****************************************************************************/
  86. /*.doc is_keyword(internal)*/
  87. /*+
  88.   Returns the keyword symbol if the given identitier is a keyword or
  89.   symbol 'ident_sym' if it is not.
  90. -*/
  91. /****************************************************************************/
  92.  
  93.  
  94. static symbol_type
  95. /*FCN*/is_keyword(ident)
  96.  
  97.   char *ident;
  98. {
  99.     register int i;
  100.  
  101.     for (i = 0; i < NKWS; i++)
  102.         if (strcmp(ident, kw[i].ident) == 0) {
  103.             return(kw[i].symbol);
  104.         }
  105.     return(ident_sym);
  106. } /*is_keyword*/
  107.  
  108.  
  109. /****************************************************************************/
  110. /*.doc next_char(internal)*/
  111. /*+
  112.   Delivers the next character from the input stream. The character is
  113.   stored in 'ch', the pointer to the next character is 'ch_ptr'.
  114. -*/
  115. /****************************************************************************/
  116.  
  117.  
  118. static void
  119. /*FCN*/next_char()
  120. {
  121.     if (*ch_ptr != EOS) {
  122.         ch = ads_toupper(*ch_ptr++);
  123.     } else {
  124.         ch = ' ';
  125.         end_of_line = TRUE;
  126.     }
  127. } /*next_char*/
  128.  
  129.  
  130. /****************************************************************************/
  131. /*.doc number(internal)*/
  132. /*+
  133.   Parses the terminal symbol NUMBER.
  134. -*/
  135. /****************************************************************************/
  136.  
  137.  
  138. static void
  139. /*FCN*/number()
  140. {
  141.     char *sym_begin;
  142.     char num_str[MAX_SYMBOL_LENGTH+1];
  143.     int  sym_len;
  144.     int  success;
  145.  
  146.     if (cal_err)
  147.         return;
  148.  
  149.     cal_lex.sym = int_sym;
  150.     sym_begin   =  ch_ptr - 1;
  151.  
  152.     while (ads_isdigit(ch)) {
  153.         next_char();
  154.     }
  155.  
  156.     if (ch == '.') {
  157.         cal_lex.sym = real_sym;
  158.         next_char();
  159.         while (ads_isdigit(ch)) {
  160.             next_char();
  161.         }
  162.     }
  163.     if (ch == 'E') {
  164.         cal_lex.sym = real_sym;
  165.         next_char();
  166.         if ((ch == '+') || (ch == '-'))
  167.             next_char();
  168.         if (!(ads_isdigit(ch))) {
  169.             error(1, NULL);
  170.             return;
  171.         }
  172.         do {
  173.             next_char();
  174.         } while (ads_isdigit(ch));
  175.     }
  176.  
  177.     sym_len = ch_ptr - sym_begin - 1;
  178.     if (end_of_line) {
  179.         sym_len++;
  180.     }
  181.     if (sym_len > MAX_SYMBOL_LENGTH) {
  182.         sym_len = MAX_SYMBOL_LENGTH;
  183.     }
  184.  
  185.     strncpy(num_str, sym_begin, sym_len);
  186.     num_str[sym_len] = EOS;
  187.  
  188.     success = sscanf(num_str, "%lf", &cal_lex.real_num);
  189.     if (success != 1) {
  190.         error(1, num_str);
  191.         return;
  192.     }
  193.     if ((errno == ERANGE) || (errno == EDOM) ||
  194.         (cal_lex.real_num == HUGE_VAL)) {
  195.  
  196.         error(1, num_str);
  197.         return;
  198.     }
  199.     if ((cal_lex.sym == int_sym) &&
  200.         ((cal_lex.real_num > 32767) || (cal_lex.real_num < -32768))) {
  201.         error(3, NULL);
  202.         return;
  203.     }
  204. } /*number*/
  205.  
  206.  
  207. /****************************************************************************/
  208. /*.doc number_angle_or_feet(internal)*/
  209. /*+
  210.   Parses the terminal symbols NUMBER, ANGLE and FEET-INCHES.
  211. -*/
  212. /****************************************************************************/
  213.  
  214.  
  215. static void
  216. /*FCN*/number_angle_or_feet()
  217. {
  218.     if (cal_err)
  219.         return;
  220.  
  221.     number();
  222.     if (cal_err)
  223.         return;
  224.  
  225.     if (ch == 'G') {                  /*grads*/
  226.         cal_lex.sym      = real_sym;
  227.         cal_lex.real_num = cal_lex.real_num * 0.9;
  228.         next_char();
  229.  
  230.     } else if (ch == 'R') {           /*radians*/
  231.         cal_lex.sym      = real_sym;
  232.         cal_lex.real_num = cal_lex.real_num / DEGRAD;
  233.         next_char();
  234.  
  235.     } else if (ch == 'D') {           /*<deg>d<min>'<sec>"*/
  236.         double deg, min, sec;
  237.  
  238.         deg = cal_lex.real_num;
  239.         min = sec = 0.0;
  240.  
  241.         next_char();
  242.         if (!ads_isdigit(ch)) {
  243.             goto End_degminsec;
  244.         }
  245.         number();
  246.  
  247.         if (ch == '\'') {
  248.             min = cal_lex.real_num;
  249.             next_char();
  250.             if (!ads_isdigit(ch)) {
  251.                 goto End_degminsec;
  252.             }
  253.             number();
  254.         }
  255.  
  256.         if (ch == '"') {
  257.             sec = cal_lex.real_num;
  258.             next_char();
  259.         } else {
  260.             error(34, NULL);
  261.             return;
  262.         }
  263.  
  264. End_degminsec:
  265.         if (cal_err)
  266.             return;
  267.  
  268.         cal_lex.sym      = real_sym;
  269.         cal_lex.real_num = deg + min / 60.0 + sec / 3600.0;
  270.  
  271.     } else if ((ch == '\'') || (ch == '"')) { /*<feet>'<inches>"*/
  272.         double feet = 0, inches = 0;
  273.  
  274.         if (ch == '\'') {
  275.             feet = cal_lex.real_num;
  276.  
  277.             next_char();
  278.             if (ch == '-') {
  279.                 next_char();
  280.             }
  281.  
  282.             if (ads_isdigit(ch)) {
  283.                 number();
  284.                 if (ch != '"') {
  285.                     error(22, NULL);
  286.                     return;
  287.                 }
  288.                 inches = cal_lex.real_num;
  289.                 next_char();
  290.             }
  291.         } else {
  292.             inches = cal_lex.real_num;
  293.             next_char();
  294.         }
  295.  
  296.         if (cal_err)
  297.             return;
  298.  
  299.         cal_lex.sym      = real_sym;
  300.         cal_lex.real_num = 12 * feet + inches;
  301.     } /*if*/
  302.  
  303. } /*number_angle_or_feet*/
  304.  
  305.  
  306. /****************************************************************************/
  307. /*.doc cal_next_symbol(internal)*/
  308. /*+
  309.   Delivers the next symbol from the input stream. The returned symbol
  310.   is stored in the global structure 'cal_lex'.
  311. -*/
  312. /****************************************************************************/
  313.  
  314.  
  315. void
  316. /*FCN*/cal_next_symbol()
  317. {
  318.     char         *sym_begin;
  319.     int          sym_len;
  320.     register int i;
  321.  
  322.     if (cal_err)
  323.         return;
  324.  
  325.     while ((ch == ' ') && !end_of_line) {
  326.         next_char();
  327.     }
  328.  
  329.     if (ch == ' ') {
  330.         cal_lex.sym = no_sym;
  331.  
  332.     } else if (ads_isalpha(ch)) {
  333.  
  334.         cal_lex.sym = ident_sym;
  335.         sym_begin   = ch_ptr - 1;
  336.  
  337.         do {
  338.             next_char();
  339.         } while (ads_isalnum(ch) || (ch == '_'));
  340.  
  341.         sym_len = ch_ptr - sym_begin - 1;
  342.         if (end_of_line) {
  343.             sym_len++;
  344.         }
  345.         if (sym_len > MAX_SYMBOL_LENGTH) {
  346.             sym_len = MAX_SYMBOL_LENGTH;
  347.         }
  348.  
  349.         strncpy(cal_lex.id, sym_begin, sym_len);
  350.         cal_lex.id[sym_len] = EOS;
  351.         str_toupper(cal_lex.id);
  352.  
  353.         /* Is it a keyword ? */
  354.  
  355.         cal_lex.sym = is_keyword(cal_lex.id);
  356.         if (cal_lex.sym != ident_sym)
  357.             return;
  358.  
  359.         /* Is it a function name? */
  360.  
  361.         for (i = 0; i < cal_funcs_number; i++) {
  362.             if (strcmp(cal_lex.id, cal_funcs_table[i].name) == 0) {
  363.                 cal_lex.sym      = func_sym;
  364.                 cal_lex.func_ptr = cal_funcs_table[i].func;
  365.                 return;
  366.             } /*if*/
  367.         } /*for*/
  368.  
  369.     } else if (ch == '\'') {
  370.         /* The name of AutoLISP symbol enclosed in apostrophes */
  371.  
  372.         cal_lex.sym = ident_sym;
  373.         next_char();
  374.  
  375.         i = 0;
  376.         while (!end_of_line && (i < MAX_SYMBOL_LENGTH) && (ch != '\'')) {
  377.             cal_lex.id[i++] = ch;
  378.             next_char();
  379.         }
  380.         cal_lex.id[i] = EOS;
  381.  
  382.         if (end_of_line) {
  383.             error(9, NULL);
  384.             return;
  385.         } if (ch != '\'') {
  386.             error(31, cal_lex.id);
  387.             return;
  388.         }
  389.  
  390.         next_char();
  391.  
  392.     } else if (ads_isdigit(ch) || (ch == '.')) {
  393.         number_angle_or_feet();
  394.  
  395.     } else if (ch == '[') { cal_lex.sym = lbracket_sym;  next_char(); }
  396.     else   if (ch == ']') { cal_lex.sym = rbracket_sym;  next_char(); }
  397.     else   if (ch == ',') { cal_lex.sym = comma_sym;     next_char(); }
  398.     else   if (ch == '-') { cal_lex.sym = minus_sym;     next_char(); }
  399.     else   if (ch == '+') { cal_lex.sym = plus_sym;      next_char(); }
  400.     else   if (ch == '*') { cal_lex.sym = asterisk_sym;  next_char(); }
  401.     else   if (ch == '/') { cal_lex.sym = slash_sym;     next_char(); }
  402.     else   if (ch == '(') { cal_lex.sym = lparent_sym;   next_char(); }
  403.     else   if (ch == ')') { cal_lex.sym = rparent_sym;   next_char(); }
  404.     else   if (ch == '^') { cal_lex.sym = caret_sym;     next_char(); }
  405.     else   if (ch == '@') { cal_lex.sym = at_sym;        next_char(); }
  406.     else   if (ch == '<') { cal_lex.sym = lessthan_sym;  next_char(); }
  407.     else   if (ch == '&') { cal_lex.sym = ampersand_sym; next_char(); }
  408.     else   if (ch == '=') { cal_lex.sym = equal_sym;     next_char(); }
  409.     else {
  410.         cal_lex.id[0] = ch;
  411.         cal_lex.id[1] = EOS;
  412.         error(2, cal_lex.id);
  413.         return;
  414.     }
  415.  
  416. } /*cal_next_symbol*/
  417.  
  418.  
  419. /****************************************************************************/
  420. /*.doc cal_lex_start(external)*/
  421. /*+
  422.   Initializes the lexical analyser with the input string 'line'. Reads the
  423.   first symbol ahead.
  424. -*/
  425. /****************************************************************************/
  426.  
  427.  
  428. void
  429. /*FCN*/cal_lex_start(line)
  430.  
  431.   char *line;
  432. {
  433.     cal_err     = 0;
  434.     errno       = 0;
  435.     ch          = ' ';
  436.     ch_ptr      = line;
  437.     end_of_line = FALSE;
  438.     next_char();
  439.     cal_next_symbol();
  440. } /*cal_lex_start*/
  441.  
  442.