/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1989-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* expression library default lexical analyzer
*/
#include "exlib.h"
#if !defined(TRACE_lex) && _BLD_DEBUG
#endif
#if TRACE_lex
/*
* trace c for op
*/
static void
{
char* s;
char* t;
t = "";
switch (c)
{
case 0:
s = " EOF";
break;
case '=':
s = t = buf;
*t++ = ' ';
*t++ = c;
*t = 0;
break;
case AND:
s = " AND ";
t = "&&";
break;
case DEC:
s = " DEC ";
t = "--";
break;
case DECLARE:
s = " DECLARE ";
break;
case DYNAMIC:
s = " DYNAMIC ";
break;
case EQ:
s = " EQ ";
t = "==";
break;
case FLOATING:
s = " FLOATING ";
break;
case GE:
s = " GE ";
t = ">=";
break;
case ID:
s = " ID ";
break;
case INC:
s = "INC ";
t = "++";
break;
case INTEGER:
s = " INTEGER ";
break;
case LABEL:
s = " LABEL ";
break;
case LE:
s = " LE ";
t = "<=";
break;
case LS:
s = " LS ";
t = "<<";
break;
case NAME:
s = " NAME ";
break;
case NE:
s = " NE ";
t = "!=";
break;
case OR:
s = " OR ";
t = "||";
break;
case RS:
s = " RS ";
t = ">>";
break;
case STRING:
s = " STRING ";
break;
case UNSIGNED:
s = " UNSIGNED ";
break;
case BREAK:
s = " break";
break;
case CASE:
s = " case";
break;
case CONTINUE:
s = " continue";
break;
case DEFAULT:
s = " default";
break;
case ELSE:
s = " else";
break;
case EXIT:
s = " exit";
break;
case FOR:
s = " for";
break;
case IF:
s = " if";
break;
case PRAGMA:
s = " pragma";
break;
case PRINTF:
s = " printf";
break;
case QUERY:
s = " query";
break;
case RETURN:
s = " return";
break;
case SPRINTF:
s = " sprintf";
break;
case SWITCH:
s = " switch";
break;
case WHILE:
s = " while";
break;
default:
if (c < 0177)
{
s = buf;
*s++ = c;
*s = 0;
s = " ";
}
break;
}
}
/*
* trace wrapper for extoken()
*/
int
{
int c;
return c;
}
#else
#define trace(p,a,b,c)
#endif
/*
* get the next expression char
*/
static int
{
register int c;
for (;;)
{
{
{
continue;
}
}
{
{
continue;
}
}
{
{
continue;
c = 0;
}
else if ((ex->disc->flags & EX_INTERACTIVE) && c == '\n' && ex->input->next && !ex->input->next->next && ex->input->nesting <= 0)
{
error_info.line++;
c = 0;
}
}
else c = 0;
if (c == '\n')
setcontext(ex);
else if (c)
putcontext(ex, c);
return c;
}
}
/*
* get the next expression token
*/
int
{
register int c;
register char* s;
register int q;
int b;
char* e;
Dt_t* v;
return 0;
for (;;)
{
case 0:
goto eof;
case '/':
{
case '*':
{
case '\n':
if (error_info.line)
error_info.line++;
continue;
case '*':
{
case 0:
goto eof;
case '\n':
if (error_info.line)
error_info.line++;
break;
case '*':
break;
case '/':
goto again;
}
break;
}
break;
case '/':
if (!c)
goto eof;
break;
default:
goto opeq;
}
/*FALLTHROUGH*/
case '\n':
if (error_info.line)
error_info.line++;
/*FALLTHROUGH*/
case ' ':
case '\t':
break;
case '(':
case '{':
case '[':
case ')':
case '}':
case ']':
case '+':
case '-':
goto opeq;
case '*':
case '%':
case '^':
opeq:
if (q == '=')
c = '=';
else if (q == '%' && c == '%')
{
goto eof;
}
return c;
case '&':
case '|':
{
return '=';
}
if (q == c)
case '<':
case '>':
{
c = '=';
return c;
}
goto relational;
case '=':
case '!':
if (q == '=') switch (c)
{
case '<':
c = LE;
break;
case '>':
c = GE;
break;
case '=':
c = EQ;
break;
case '!':
c = NE;
break;
}
case '#':
{
s--;
{
{
case DYNAMIC:
case ID:
case NAME:
break;
default:
s = "";
break;
}
if (streq(s, "include"))
{
exerror("#%s: string argument expected", s);
{
setcontext(ex);
goto again;
}
}
else exerror("unknown directive");
}
}
case '\'':
case '"':
q = c;
{
if (c == '\\')
{
}
if (!c)
{
exerror("unterminated %c string", q);
goto eof;
}
if (c == '\n')
{
if (error_info.line)
error_info.line++;
}
}
{
goto eof;
return STRING;
}
return INTEGER;
case '.':
{
goto floating;
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
q = INTEGER;
b = 0;
{
b = 16;
for (;;)
{
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
continue;
}
break;
}
}
else
{
while (isdigit(c))
{
}
if (c == '#')
{
do
{
}
else
{
if (c == '.')
{
q = FLOATING;
}
if (c == 'e' || c == 'E')
{
q = FLOATING;
{
}
while (isdigit(c))
{
}
}
}
}
if (q == FLOATING)
else
{
if (c == 'u' || c == 'U')
{
q = UNSIGNED;
}
else
if (*e)
{
*--e = 1;
}
}
{
exerror("%s: invalid numeric constant", s);
goto eof;
}
return q;
default:
{
if (v)
{
{
exnospace();
goto eof;
}
/*
* LABELs are in the parent scope!
*/
else
}
/*
* lexical analyzer state controlled by the grammar
*/
{
case DECLARE:
{
/*
* `char*' === `string'
* the * must immediately follow char
*/
if (c == '*')
{
}
}
break;
case NAME:
/*
* action labels are disambiguated from ?:
* through the expr.nolabel grammar hook
* the : must immediately follow labels
*/
return LABEL;
break;
case PRAGMA:
/*
* user specific statement stripped and
* passed as string
*/
{
int b;
int n;
int pc;
int po;
int t;
/*UNDENT...*/
b = 1;
n = 0;
po = 0;
t = 0;
{
switch (c)
{
case 0:
goto eof;
case '/':
{
case '*':
for (;;)
{
{
case '\n':
if (error_info.line)
error_info.line++;
continue;
case '*':
{
case 0:
goto eof;
case '\n':
if (error_info.line)
error_info.line++;
continue;
case '*':
continue;
case '/':
break;
default:
continue;
}
break;
}
if (!b++)
goto eof;
break;
}
break;
case '/':
if (!c)
goto eof;
if (error_info.line)
error_info.line++;
b = 1;
break;
default:
b = 0;
break;
}
continue;
case '\n':
if (error_info.line)
error_info.line++;
b = 1;
continue;
case ' ':
case '\t':
if (!b++)
goto eof;
continue;
case '(':
case '{':
case '[':
b = 0;
if (!po)
{
switch (po = c)
{
case '(':
pc = ')';
break;
case '{':
pc = '}';
break;
case '[':
pc = ']';
break;
}
n++;
}
else if (c == po)
n++;
continue;
case ')':
case '}':
case ']':
b = 0;
if (!po)
{
break;
}
if (c == pc && --n <= 0)
{
if (t == po)
break;
po = 0;
}
continue;
case ';':
b = 0;
if (!n)
break;
continue;
case '\'':
case '"':
b = 0;
q = c;
{
if (c == '\\')
{
}
if (!c)
{
exerror("unterminated %c string", q);
goto eof;
}
if (c == '\n')
{
if (error_info.line)
error_info.line++;
}
}
continue;
default:
b = 0;
continue;
}
break;
}
/*..INDENT*/
}
goto again;
}
}
}
eof:
}