This commit is contained in:
Oliver Lehmann 1989-04-05 11:16:43 +00:00
parent b992d20a86
commit 590be809a9
4 changed files with 464 additions and 0 deletions

View File

@ -0,0 +1,122 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "constants.h"
# include "globals.h"
/*
** NUMBER -- process a numeric token
** Number gets a number as, either floating or integer,
** with the QL format, from inside a QL statement,
** and adds it to the symbol space.
**
** Parameters:
** chr -- the first character of the number
**
** Returns:
** The lexical code for the appropriate
** type of number.
**
** Side Effects:
** Adds a token to the symbols space.
** yylval is set to the node added.
*/
number(chr)
register int chr;
{
register char *ptr;
register int toktyp;
double ftemp;
long ltemp;
char buf[MAXFIELD + 1];
extern char *yylval;
extern char *addsym();
extern char *salloc();
ptr = buf;
if ((*ptr = toktyp = chr) != '.')
{
do
{
/* get integer portion */
if ((ptr - buf) > MAXFIELD)
{
/* buffer overflow
* return integer 0,
* and signal error.
*/
bufovflo :
*ptr = '\0';
yysemerr("numeric too long", buf);
yylval = addsym("0");
return (Tokens.sp_i2const);
}
*++ptr = toktyp = getch();
} while (CMAP(toktyp) == NUMBR);
}
/* do rest of type determination */
switch (toktyp)
{
case '.':
/* floating point */
do
{
/* fill into ptr with up to next non-digit */
if ((ptr - buf) > MAXFIELD)
goto bufovflo;
*++ptr = toktyp = getch();
} while (CMAP(toktyp) == NUMBR);
if (toktyp != 'e' && toktyp != 'E')
{
backup(toktyp);
*ptr = '\0';
goto convr;
}
case 'e':
case 'E':
if ((ptr - buf) > MAXFIELD)
goto bufovflo;
*++ptr = toktyp = getch();
if (CMAP(toktyp) == NUMBR || toktyp == '-' || toktyp == '+')
{
do
{
/* get exponent */
if ((ptr - buf) > MAXFIELD)
goto bufovflo;
*++ptr = toktyp = getch();
} while (CMAP(toktyp) == NUMBR);
}
backup(toktyp);
*ptr = '\0';
convr:
if (AA_atof(buf, &ftemp))
{
/* floating conversion error */
yysemerr("numeric ofverflow", buf);
yylval = addsym("0");
return (Tokens.sp_f8const);
}
yylval = addsym(salloc(buf));
toktyp = Tokens.sp_f8const;
break;
default:
/* integer */
backup(toktyp);
*ptr = '\0';
/* long conversion error */
if (AA_atol(buf, &ltemp) || ltemp > 32767 || ltemp < -32768)
goto convr;
yylval = addsym(salloc(buf));
toktyp = Tokens.sp_i2const;
break;
}
return (toktyp);
}

View File

@ -0,0 +1,88 @@
# include <stdio.h>
# include "gen.h"
# include "constants.h"
# include "globals.h"
/*
** OPERATOR -- process a token starting with an operator
**
** Processes operators, strings, comments, and
** floating constants without a leading 0.
**
** Parameters:
** chr - first character of token {CMAP(chr) == OPATR}
**
** Returns:
** NUMBER or STRING token, or operator token.
** CONTINUE on error.
**
** Side Effects:
** Adds a node to the Symbol space, and returns adress
** in "yylval".
** Opcode is set to the opcode of the operator.
** May backup a character.
*/
operator(chr)
register int chr;
{
register struct optab *op;
register int next_ch;
char opbuf[3];
extern char *yylval;
extern char *addsym();
opbuf[0] = chr;
opbuf[1] = next_ch = getch();
opbuf[2] = '\0';
if (opbuf[0] == '.' && CMAP(next_ch) == NUMBR)
{
/* floating mantissa w/o leading 0 */
backup(next_ch);
return (number(opbuf[0]));
}
if (CMAP(next_ch) != OPATR)
{
backup(next_ch);
opbuf[1] = '\0';
}
/* operator has been reduced to its smallest
* possible length, now try to find it in the
* operator table[tokens.y]
*/
for ( ; ; )
{
for (op = Optab; op->op_term; op++)
if (AAsequal(op->op_term, opbuf))
break;
if (!op->op_term && opbuf[1])
{
/* reduce a 2 char operator to 1 char,
* and re-search
*/
backup(opbuf[1]);
opbuf[1] = '\0';
continue;
}
break;
}
if (op->op_term)
{
/* string quotes ? */
if (op->op_token == Tokens.sp_quote)
return (string(op));
/* comment indicator ? */
if (op->op_token == Tokens.sp_bgncmnt)
return (comment());
/* {AAsequal(opbuf, op->op_term)} */
Opcode = op->op_code;
yylval = addsym(op->op_term);
return (op->op_token);
}
yysemerr("bad operator", opbuf);
/* operator not found, skip token and try again */
return (CONTINUE);
}

View File

@ -0,0 +1,87 @@
# include <stdio.h>
# include "gen.h"
# include "constants.h"
# include "globals.h"
/*
** STRING -- processes a string constant
** Strings are kept internally exactly as their external
** appearance, except for the outermost '"'.
** A string may be at most MAXSTRING characters
** long, and may have escaped newlines.
**
** Parameters:
** op -- pointer to string quote operator
** table entry.
**
** Returns:
** SCONST
*/
string(op)
struct optab *op;
{
char buf[MAXSTRING + 1];
register int c;
register char *cp;
register int escape;
register int error;
extern char *yylval;
extern char *addsym();
extern char *salloc();
error = escape = 0;
cp = buf;
for ( ; ; )
{
switch (c = getch())
{
case '\\' :
if (!escape)
escape = 2;
goto regchar;
case '\n' :
if (escape)
goto regchar;
*cp = '\0';
yysemerr("non-terminated string", !error? buf :(char *) 0);
break;
case EOF_TOK :
backup(c);
*cp = '\0';
yysemerr("EOF in string", !error? buf :(char *) 0);
break;
default :
regchar :
if (c == *op->op_term && !escape)
{
/* end of string */
*cp = '\0';
break;
}
if (!error)
{
if (cp - buf < MAXSTRING)
{
if (CMAP(c) == CNTRL)
yysemerr("control character in string eliminated", (char *) 0);
else
*cp++ = c;
}
else
{
yysemerr("string too long, rest discarded", (char *) 0);
error = 1;
}
}
if (escape)
--escape;
continue;
}
break;
}
yylval = addsym(salloc(buf));
return (Tokens.sp_sconst);
}

View File

@ -0,0 +1,167 @@
# include <stdio.h>
# include "gen.h"
# include "constants.h"
# include "globals.h"
int yyline;
/*
** YYLEX -- Lexical analyzer
** Yylex controls the return to the parser of lexemes,
** and the copying out of C_CODE on the all to yylex
** after yylex() returned the C_CODE.
**
** Returns:
** Lexical tokens.
**
** Side Effects:
** Copies C code out on call after seeing it.
** Puts terminals in symbol space.
*/
yylex()
{
register int rtval;
register int chr;
extern char *yysterm[];
/* get next token */
rtval = CONTINUE;
while (rtval == CONTINUE)
{
if (C_code_flag)
{
copy_c_code();
Newline = 1;
}
Pre_proc_flag = 0;
/* END OF FILE ? */
if ((chr = getch()) == EOF_TOK)
{
# ifdef xDEBUG
if (Lex_debug)
printf("end of file\n");
# endif
return (0);
}
/* Test for a line of C code */
if (Newline && if_c_code(chr))
{
if (C_code_flag)
continue;
rtval = Tokens.sp_c_code;
C_code_flag = 1;
break;
}
else
{
C_code_flag = 0;
if (Newline)
{
Newline = 0;
continue;
}
}
/* CARRIAGE CONTROL ? */
Newline = chr == '\n';
switch (CMAP(chr))
{
case PUNCT :
continue;
case OPATR :
rtval = operator(chr);
break;
case NUMBR :
rtval = number(chr);
break;
case ALPHA :
rtval = name(chr);
break;
}
}
if (Lex_debug)
printf("YYLEX : %s: '%s'\n", yysterm[rtval - 256],
yylval? ((struct disp_node *) yylval)->d_elm: "");
return (rtval);
}
/*
** COPY_C_CODE -- Copies out a line of C code
** The test for Charcnt != 0 is beacuse if a C pre-processor
** line follows an EQL line, and equate_lines() puts out no
** newline, the initial '#' will not be on the beginning of
** the line. As is, if this should happen, then the line
** with the '#' will be one line in the output ahead of
** where it should be.
*/
copy_c_code()
{
register int c;
char ch[2];
ch[1] = 0;
equate_lines();
if (Pre_proc_flag)
{
if (Charcnt)
w_raw("\n");
w_raw("#");
}
do
{
if ((c = getch()) == EOF_TOK)
return;
*ch = c;
w_raw(ch);
} while (*ch != '\n');
}
/*
** IF_C_CODE -- Test to see if a line is C code
**
** Sees if a line begins with "##" to see if it is EQL.
**
** Parameters:
** chr -- first char of line
**
** Returns:
** 0 -- QL line
** 1 -- C line
*/
if_c_code(chr)
register int chr;
{
for ( ; ; )
{
if (chr != '#')
{
backup(chr);
return (1);
}
Pre_proc_flag = 1;
if ((chr = getch()) == EOF_TOK)
{
return (0);
}
if (chr != '#')
{
backup(chr);
return (1);
}
else
{
return (0);
}
}
}