mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-25 00:29:20 +00:00
gram.y to gram.yc so that we don't try to turn it into a .cpp file. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3874 91177308-0d34-0410-b5e6-96231b3b80d8
260 lines
4.2 KiB
C
260 lines
4.2 KiB
C
char rcsid_lex[] = "$Id$";
|
|
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "b.h"
|
|
#include "fe.h"
|
|
#include "gram.tab.h"
|
|
|
|
static char buf[BUFSIZ];
|
|
|
|
static int yyline = 1;
|
|
|
|
typedef int (*ReadFn) ARGS((void));
|
|
|
|
static char *StrCopy ARGS((char *));
|
|
static int code_get ARGS((void));
|
|
static int simple_get ARGS((void));
|
|
static void ReadCharString ARGS((ReadFn, int));
|
|
static void ReadCodeBlock ARGS((void));
|
|
static void ReadOldComment ARGS((ReadFn));
|
|
|
|
static char *
|
|
StrCopy(s) char *s;
|
|
{
|
|
char *t = (char *)zalloc(strlen(s) + 1);
|
|
strcpy(t,s);
|
|
return t;
|
|
}
|
|
|
|
static int
|
|
simple_get()
|
|
{
|
|
int ch;
|
|
if ((ch = getchar()) == '\n') {
|
|
yyline++;
|
|
}
|
|
return ch;
|
|
}
|
|
|
|
static int
|
|
code_get()
|
|
{
|
|
int ch;
|
|
if ((ch = getchar()) == '\n') {
|
|
yyline++;
|
|
}
|
|
if (ch != EOF) {
|
|
fputc(ch, outfile);
|
|
}
|
|
return ch;
|
|
}
|
|
|
|
void
|
|
yypurge()
|
|
{
|
|
while (code_get() != EOF) ;
|
|
}
|
|
|
|
|
|
static void
|
|
ReadCharString(rdfn, which) ReadFn rdfn; int which;
|
|
{
|
|
int ch;
|
|
int backslash = 0;
|
|
int firstline = yyline;
|
|
|
|
while ((ch = rdfn()) != EOF) {
|
|
if (ch == which && !backslash) {
|
|
return;
|
|
}
|
|
if (ch == '\\' && !backslash) {
|
|
backslash = 1;
|
|
} else {
|
|
backslash = 0;
|
|
}
|
|
}
|
|
yyerror1("Unexpected EOF in string on line ");
|
|
fprintf(stderr, "%d\n", firstline);
|
|
exit(1);
|
|
}
|
|
|
|
static void
|
|
ReadOldComment(rdfn) ReadFn rdfn;
|
|
{
|
|
/* will not work for comments delimiter in string */
|
|
|
|
int ch;
|
|
int starred = 0;
|
|
int firstline = yyline;
|
|
|
|
while ((ch = rdfn()) != EOF) {
|
|
if (ch == '*') {
|
|
starred = 1;
|
|
} else if (ch == '/' && starred) {
|
|
return;
|
|
} else {
|
|
starred = 0;
|
|
}
|
|
}
|
|
yyerror1("Unexpected EOF in comment on line ");
|
|
fprintf(stderr, "%d\n", firstline);
|
|
exit(1);
|
|
}
|
|
|
|
static void
|
|
ReadCodeBlock()
|
|
{
|
|
int ch;
|
|
int firstline = yyline;
|
|
|
|
while ((ch = getchar()) != EOF) {
|
|
if (ch == '%') {
|
|
ch = getchar();
|
|
if (ch != '}') {
|
|
yyerror("bad %%");
|
|
}
|
|
return;
|
|
}
|
|
fputc(ch, outfile);
|
|
if (ch == '\n') {
|
|
yyline++;
|
|
}
|
|
if (ch == '"' || ch == '\'') {
|
|
ReadCharString(code_get, ch);
|
|
} else if (ch == '/') {
|
|
ch = getchar();
|
|
if (ch == '*') {
|
|
fputc(ch, outfile);
|
|
ReadOldComment(code_get);
|
|
continue;
|
|
} else {
|
|
ungetc(ch, stdin);
|
|
}
|
|
}
|
|
}
|
|
yyerror1("Unclosed block of C code started on line ");
|
|
fprintf(stderr, "%d\n", firstline);
|
|
exit(1);
|
|
}
|
|
|
|
static int done;
|
|
void
|
|
yyfinished()
|
|
{
|
|
done = 1;
|
|
}
|
|
|
|
int
|
|
yylex()
|
|
{
|
|
int ch;
|
|
char *ptr = buf;
|
|
|
|
if (done) return 0;
|
|
while ((ch = getchar()) != EOF) {
|
|
switch (ch) {
|
|
case ' ':
|
|
case '\f':
|
|
case '\t':
|
|
continue;
|
|
case '\n':
|
|
yyline++;
|
|
continue;
|
|
case '(':
|
|
case ')':
|
|
case ',':
|
|
case ':':
|
|
case ';':
|
|
case '=':
|
|
return(ch);
|
|
case '/':
|
|
ch = getchar();
|
|
if (ch == '*') {
|
|
ReadOldComment(simple_get);
|
|
continue;
|
|
} else {
|
|
ungetc(ch, stdin);
|
|
yyerror("illegal char /");
|
|
continue;
|
|
}
|
|
case '%':
|
|
ch = getchar();
|
|
switch (ch) {
|
|
case '%':
|
|
return (K_PPERCENT);
|
|
case '{':
|
|
ReadCodeBlock();
|
|
continue;
|
|
case 's':
|
|
case 'g':
|
|
case 't':
|
|
do {
|
|
if (ptr >= &buf[BUFSIZ]) {
|
|
yyerror("ID too long");
|
|
return(ERROR);
|
|
} else {
|
|
*ptr++ = ch;
|
|
}
|
|
ch = getchar();
|
|
} while (isalpha(ch) || isdigit(ch) || ch == '_');
|
|
ungetc(ch, stdin);
|
|
*ptr = '\0';
|
|
if (!strcmp(buf, "term")) return K_TERM;
|
|
if (!strcmp(buf, "start")) return K_START;
|
|
if (!strcmp(buf, "gram")) return K_GRAM;
|
|
yyerror("illegal character after %%");
|
|
continue;
|
|
default:
|
|
yyerror("illegal character after %%");
|
|
continue;
|
|
}
|
|
default:
|
|
if (isalpha(ch) ) {
|
|
do {
|
|
if (ptr >= &buf[BUFSIZ]) {
|
|
yyerror("ID too long");
|
|
return(ERROR);
|
|
} else {
|
|
*ptr++ = ch;
|
|
}
|
|
ch = getchar();
|
|
} while (isalpha(ch) || isdigit(ch) || ch == '_');
|
|
ungetc(ch, stdin);
|
|
*ptr = '\0';
|
|
yylval.y_string = StrCopy(buf);
|
|
return(ID);
|
|
}
|
|
if (isdigit(ch)) {
|
|
int val=0;
|
|
do {
|
|
val *= 10;
|
|
val += (ch - '0');
|
|
ch = getchar();
|
|
} while (isdigit(ch));
|
|
ungetc(ch, stdin);
|
|
yylval.y_int = val;
|
|
return(INT);
|
|
}
|
|
yyerror1("illegal char ");
|
|
fprintf(stderr, "(\\%03o)\n", ch);
|
|
exit(1);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void yyerror1(const char *str)
|
|
{
|
|
fprintf(stderr, "line %d: %s", yyline, str);
|
|
}
|
|
|
|
void
|
|
yyerror(const char *str)
|
|
{
|
|
yyerror1(str);
|
|
fprintf(stderr, "\n");
|
|
exit(1);
|
|
}
|