%option noyywrap bison-bridge bison-locations
%{
#include <stdio.h>
#include <stdlib.h>
#define TAG_IDENT 1
#define TAG_KEYW 2
char *tag_names[] = {
"END_OF_PROGRAM", "IDENT", "KEYW"
};
struct Position {
int line, pos, index;
};
void print_pos(struct Position *p) {
printf("(%d, %d)", p->line, p->pos);
}
struct Fragment {
struct Position starting, following;
};
typedef struct Fragment YYLTYPE;
void print_frag(struct Fragment *f) {
print_pos(&(f->starting));
printf("-");
print_pos(&(f->following));
}
union Token {
int code;
long num;
char ch;
};
typedef union Token YYSTYPE;
int continued;
struct Position cur;
#define YY_USER_ACTION \
{\
int i; \
if (! continued)\
yylloc->starting = cur;\
continued = 0;\
\
for (i = 0; i < yyleng; i++) {\
if (yytext[i] == '\n') {\
cur.line++;\
cur.pos = 1;\
}\
else\
cur.pos++;\
cur.index++;\
}\
yylloc->following = cur;\
}
void init_scanner(char *program) {
continued = 0;
cur.line = 1;
cur.pos = 1;
cur.index = 0;
yy_scan_string(program);
}
struct Error
{
struct Position pos;
char *msg;
} *errors;
int capacity = 0;
int errLength = 0;
void err(char *msg, struct Position pos) {
struct Error err;
err.msg = msg;
err.pos = pos;
if (capacity == errLength) {
if (capacity == 0) {
capacity = 1;
} else {
capacity *= 2;
}
struct Error* errors1 = (struct Error*)malloc((capacity) * sizeof(struct Error));
int i;
for (i = 0; i < errLength; i++) {
errors1[i] = errors[i];
}
free(errors);
errors = errors1;
}
errors[errLength] = err;
errLength++;
}
struct Comment
{
struct Fragment pos;
} *comments;
int capacityCom = 0;
int comLength = 0;
void com(struct Fragment pos) {
struct Fragment f;
f.starting = pos.starting;
f.following = pos.following;
struct Comment com;
com.pos = f;
if (capacityCom == comLength) {
if (capacityCom == 0) {
capacityCom = 1;
} else {
capacityCom *= 2;
}
struct Comment* comments1 = (struct Comment*)malloc((capacityCom) * sizeof(struct Comment));
int i;
for (i = 0; i < comLength; i++) {
comments1[i] = comments[i];
}
free(comments);
comments = comments1;
}
comments[comLength] = com;
comLength++;
}
char **names;
int nameslen = 0;
int contain(char *name) {
int i;
for (i = 0; i < nameslen; i++) {
if (strcmp(names[i], name) == 0) {
return i;
}
}
return -1;
}
int addName(char *name) {
if (contain(name) == -1) {
if (!nameslen % 10) {
char** names1 = (char**)malloc((nameslen +10) * sizeof(char*));
int i;
for (i = 0; i < nameslen; i++) {
names1[i] = names[i];
}
free(names);
names = names1;
}
names[nameslen] = name;
return nameslen++;
} else {
return contain(name);
}
}
%}
%x STATE1
%%
[ \n\t]+
(with|end|\*\*) {
yylval->code = addName(yytext);
yylloc->following = cur;
return TAG_KEYW;
}
[a-zA-Z]+ {
if (yyleng % 2 == 1) {
yylval->code = addName(yytext);
yylloc->following = cur;
return TAG_IDENT;
} else {
err("syntax error", yylloc->starting);
BEGIN(0);
}
}
[\*]{3,} {
yylval->code = addName(yytext);
yylloc->following = cur;
return TAG_IDENT;
}
[\*]{1} BEGIN(STATE1); continued = 1;
<STATE1>[^\n]* {
com(*yylloc);
yylloc->following = cur;
BEGIN(0);
}
[.] {
err("syntax error", yylloc->starting);
BEGIN(0);
}
<<EOF>> {
return 0;
}
%%
#define PROGRAM "*njnbbjntj\n bmkgmglkm *** ** gggmgm with "
int main() {
int tag;
YYSTYPE value;
YYLTYPE coords;
init_scanner(PROGRAM);
do {
tag = yylex(&value, &coords);
if (tag != 0) {
printf("%s ", tag_names[tag]);
print_frag(&coords);
printf(" %s\n", names[value.code]);
} else {
int i;
for (i = 0; i < comLength; i++) {
printf("COMMENT ");
print_frag(&(comments[i].pos));
printf("\n");
}
for (i = 0; i < errLength; i++) {
printf("ERROR ");
print_pos(&(errors[i].pos));
printf(" %s ", errors[i].msg);
printf("\n");
}
printf("END_OF_PROGRAM ");
print_pos(&(coords.following));
printf("\n");
}
} while (tag != 0);
return 0;
}