%option noyywrap bison-bridge bison-locations
%{
#include <stdio.h>
#include <stdlib.h>
#define TAG_EOF 0
#define TAG_IDT 1
#define TAG_KEY 2
char *tag_names[] = {
"EOF",
"IDT",
"KEY"
};
int continued;
struct Position {
int line, pos, index;
} cur;
void print_pos(struct Position *p) {
printf("(%d, %d)", p->line, p->pos);
}
struct Fragment {
struct Position starting, ending;
} *comments;
void print_fragment(struct Fragment *f) {
print_pos(&(f->starting));
printf("-");
print_pos(&(f->ending));
}
union Token {
int code;
long num;
char ch;
};
typedef struct Fragment YYLTYPE;
typedef union Token YYSTYPE;
struct Error {
struct Position position;
char *message;
} *errors;
int errorLen = 0;
void err(char *msg, struct Position pos) {
if (! continued) {
struct Error error;
error.message = msg;
error.position = pos;
if(errorLen%10 == 0) {
struct Error *errorsNew = (struct Error*)malloc((10+errorLen)*sizeof(struct Error));
int i;
for(i = 0; i < errorLen; i++) {
errorsNew[i] = errors[i];
}
free(errors);
errors = errorsNew;
}
errors[errorLen] = error;
errorLen++;
}
}
int commentLen = 0;
void comment(struct Fragment *comment) {
if (! continued) {
struct Fragment cmt;
cmt.starting = comment->starting;
cmt.ending = comment->ending;
if(commentLen%10 == 0) {
struct Fragment *commentsNew = (struct Fragment*)malloc((10+commentLen)*sizeof(struct Fragment));
int i;
for(i = 0; i < commentLen; i++) {
commentsNew[i] = comments[i];
}
free(comments);
comments = commentsNew;
}
comments[commentLen] = cmt;
commentLen++;
}
}
char **names;
int namesLen = 0;
int containsKey(char *name) {
int i;
for(i = 0; i < namesLen; i++) {
if(!strcmp(names[i], name)) {
return 1;
}
}
return 0;
}
int addName(char *name) {
if(!containsKey(name) && namesLen%10 == 0) {
char **namesNew = (char**)malloc((10+namesLen)*sizeof(char*));
int i;
for(i = 0; i < namesLen; i++) {
namesNew[i] = names[i];
}
free(names);
names = namesNew;
}
names[namesLen] = name;
return namesLen++;
}
#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++; \
} \
}
void init_scanner(char *program) {
continued = 0;
cur.index = 0;
cur.pos = 1;
cur.line = 1;
yy_scan_string(program);
}
%}
%x COMMENT
%x IDENT IDT_BODY IDT_END
%%
[\n\t ]+ continued = 0;
[^\n\t \/<<EOF>>]+ {
if(!continued) {
err("Unexpected character", yylloc->starting);
continued = 1;
}
BEGIN(0);
}
\/\/ BEGIN(COMMENT); continued = 1;
\/(do|while|end)\/ {
yylloc->ending = cur;
yylval->code = addName(yytext);
BEGIN(0);
return TAG_KEY;
}
\/ BEGIN(IDT_BODY); continued = 1;
<<EOF>> {
yylloc->ending = cur;
yylloc->starting = cur;
return 0;
}
<COMMENT>[^\n]* continued = 1; yylloc->ending = cur;
<COMMENT>\n {
comment(yylloc);
BEGIN(0);
}
<IDT_BODY>[^\/\n]+ {
char *name = (char*)malloc((yyleng+2)*sizeof(char));
strcpy(name, "/");
strcat(name, yytext);
strcat(name, "/");
yylval->code = addName(name);
yylloc->ending = cur;
continued = 1;
BEGIN(IDT_END);
}
<IDT_END>\/ {
BEGIN(0);
return TAG_IDT;
}
<IDT_END>\n {
namesLen--;
err("\"/\" expected", yylloc->ending);
BEGIN(0);
}
%%
#define PROGRAM "//adfsdf \n"\
" //ads \n"\
"w /ww0/ www\n"\
" /q \n"\
" //11\n"\
" /do/\n"\
" /while/ "\
int main() {
int tag;
YYSTYPE value;
YYLTYPE coords;
init_scanner(PROGRAM);
printf("TOKENS:\n");
do {
tag = yylex(&value, &coords);
print_fragment(&coords);
printf(" %s", tag_names[tag]);
if(tag) {
printf(": %s\n", names[value.code]);
} else {
printf("\n");
}
} while (tag != 0);
free(names);
printf("\n");
int i;
if (commentLen != 0) {
printf("COMMENTS:\n");
for(i = 0; i < commentLen; i++) {
print_fragment(&(comments[i]));
printf("\n");
}
free(comments);
printf("\n");
}
if (errorLen != 0) {
printf("ERRORS:\n");
for(i = 0; i < errorLen; i++) {
print_pos(&(errors[i].position));
printf(" %s\n", errors[i].message);
}
free(errors);
}
return 0;
}