qzdoom/tools/dehsupp/scanner.re
Randy Heit de5d4715c2 - Added Linux support for the CMakeLists. This meant downgrading them for
CMake 2.4, since the distros don't seem to consider 2.6 stable yet.
  As a bonus, GTK+ is no longer a required dependency; now it's optional.
- Made dehsupp ignore CR characters, so it doesn't spew warnings on Linux.



SVN r1092 (trunk)
2008-07-25 01:37:44 +00:00

179 lines
3.4 KiB
C++

#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include "dehsupp.h"
#define BSIZE 8192
#define YYCTYPE uchar
#define YYCURSOR cursor
#define YYLIMIT s->lim
#define YYMARKER s->ptr
#define YYFILL(n) {cursor = fill(s, cursor);}
#define RET(i) {s->cur = cursor; return i;}
uchar *fill(Scanner *s, uchar *cursor)
{
if(!s->eof)
{
ptrdiff_t cnt = s->tok - s->bot;
if(cnt)
{
memcpy(s->bot, s->tok, s->lim - s->tok);
s->tok = s->bot;
s->ptr -= cnt;
cursor -= cnt;
s->pos -= cnt;
s->lim -= cnt;
}
if((s->top - s->lim) < BSIZE)
{
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
memcpy(buf, s->tok, s->lim - s->tok);
s->tok = buf;
s->ptr = &buf[s->ptr - s->bot];
cursor = &buf[cursor - s->bot];
s->pos = &buf[s->pos - s->bot];
s->lim = &buf[s->lim - s->bot];
s->top = &s->lim[BSIZE];
free(s->bot);
s->bot = buf;
}
if((cnt = fread((char*) s->lim, 1, BSIZE, s->fd)) != BSIZE)
{
s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
}
s->lim += cnt;
}
return cursor;
}
int scan(Scanner *s)
{
uchar *cursor = s->cur;
std:
s->tok = cursor;
/*!re2c
any = [\000-\377];
O = [0-7];
D = [0-9];
L = [a-zA-Z_];
H = [a-fA-F0-9];
ESC = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
*/
/*!re2c
"/*" { goto comment; } /* C comment */
"//" (any\"\n")* "\n" /* C++ comment */
{
if(cursor == s->eof) RET(EOI);
s->tok = s->pos = cursor; s->line++;
goto std;
}
"endl" { RET(ENDL); }
"print" { RET(PRINT); }
"Actions" { RET(Actions); }
"OrgHeights" { RET(OrgHeights); }
"ActionList" { RET(ActionList); }
"CodePConv" { RET(CodePConv); }
"OrgSprNames" { RET(OrgSprNames); }
"StateMap" { RET(StateMap); }
"SoundMap" { RET(SoundMap); }
"InfoNames" { RET(InfoNames); }
"ThingBits" { RET(ThingBits); }
"DeathState" { RET(DeathState); }
"SpawnState" { RET(SpawnState); }
"FirstState" { RET(FirstState); }
"RenderStyles" { RET(RenderStyles); }
L (L|D)* { RET(SYM); }
("0" [xX] H+) | ("0" D+) | (D+)
{ RET(NUM); }
(["] (ESC|any\[\n\\"])* ["])
{ RET(STRING); }
[ \t\v\f]+ { goto std; }
"|" { RET(OR); }
"^" { RET(XOR); }
"&" { RET(AND); }
"-" { RET(MINUS); }
"+" { RET(PLUS); }
"*" { RET(MULTIPLY); }
"/" { RET(DIVIDE); }
"(" { RET(LPAREN); }
")" { RET(RPAREN); }
"," { RET(COMMA); }
"{" { RET(LBRACE); }
"}" { RET(RBRACE); }
";" { RET(SEMICOLON); }
"\n"
{
if(cursor == s->eof) RET(EOI);
s->pos = cursor; s->line++;
goto std;
}
any
{
if (*s->tok != '\r')
{
printf("unexpected character: %c (%#02x)\n", *s->tok, *s->tok);
}
goto std;
}
*/
comment:
/*!re2c
"*/" { goto std; }
"\n"
{
if(cursor == s->eof) RET(EOI);
s->tok = s->pos = cursor; s->line++;
goto comment;
}
any { goto comment; }
*/
}
int lex(Scanner *s, struct Token *tok)
{
int tokentype = scan(s);
char *p, *q;
tok->val = 0;
tok->string = NULL;
switch (tokentype)
{
case NUM:
tok->val = strtol((char *)s->tok, NULL, 0);
break;
case STRING:
tok->string = (char *)malloc(s->cur - s->tok - 1);
strncpy(tok->string, (char *)s->tok + 1, s->cur - s->tok - 2);
tok->string[s->cur - s->tok - 2] = '\0';
for (p = q = tok->string; *p; ++p, ++q)
{
if (p[0] == '\\' && p[1] == '\\')
++p;
*q = *p;
}
break;
case SYM:
tok->string = (char *)malloc(s->cur - s->tok + 1);
strncpy(tok->string, (char *)s->tok, s->cur - s->tok);
tok->string[s->cur - s->tok] = '\0';
break;
}
return tokentype;
}