parser now generates the datastructure for the code generation

This commit is contained in:
overflowerror 2021-05-03 14:16:48 +02:00
parent c355db419d
commit ee136f5130
4 changed files with 211 additions and 11 deletions

View file

@ -2,12 +2,11 @@ LEX = flex
YACC = bison YACC = bison
YFLAGS = -y -d YFLAGS = -y -d
CC = gcc CC = gcc
LD = gcc
BIN_NAME = marshaller BIN_NAME = marshaller
marshaller: gen/lex.yy.c gen/y.tab.c marshaller: gen/lex.yy.c gen/y.tab.c
$(CC) -o $@ $^ $(CC) -Isrc/ -o $@ $^
gen/y.tab.c gen/y.tab.h: src/parser.y gen/y.tab.c gen/y.tab.h: src/parser.y
$(YACC) $(YFLAGS) $< $(YACC) $(YFLAGS) $<

28
marshaller/src/helper.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef HELPER_H
#define HELPER_H
struct typeinfo {
char* type;
bool isPointer;
};
struct memberinfo {
struct typeinfo* type;
char* name;
};
struct structinfo {
char* names[2];
size_t memberno;
struct memberinfo** members;
};
struct declarsinfo {
size_t structno;
struct structinfo** structs;
};
void _panic(const char* f, const char* s);
#define panic(s) _panic(__func__, s)
#endif

View file

@ -2,26 +2,71 @@
%{ %{
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <helper.h>
int yylex(); int yylex();
void yyerror(char*); void yyerror(char*);
struct typeinfo* newTypeInfo(bool isPointer, char* type);
struct memberinfo* newMemberInfo(struct typeinfo* type, char* name);
struct structinfo* newStructInfo();
struct declarsinfo* newDeclarsInfo();
void addMember(struct structinfo* _struct, struct memberinfo* member);
void addStruct(struct declarsinfo* declars, struct structinfo* _struct);
char* prefix(char* string, const char* prefix);
%} %}
%union {
struct typeinfo* typeinfo;
struct memberinfo* memberinfo;
struct structinfo* structinfo;
struct declarsinfo* declarsinfo;
long long number;
char* id;
}
%type <typeinfo> type
%type <memberinfo> structmember
%type <structinfo> structmembers
%type <structinfo> structbody
%type <structinfo> typedef
%type <structinfo> structdef
%type <structinfo> declar
%type <declarsinfo> declars
%type <declarsinfo> file
%token TYPEDEF STRUCT %token TYPEDEF STRUCT
%token LONG DOUBLE STRING %token LONG DOUBLE STRING
%token POINTER %token POINTER
%token SEMICOLON OPEN_BRACES CLOSE_BRACES OPEN_BRACKETS CLOSE_BRACKETS %token SEMICOLON OPEN_BRACES CLOSE_BRACES OPEN_BRACKETS CLOSE_BRACKETS
%token ID NUM %token <id> ID
%token NUM
%start file %start file
%% %%
file: declars file: declars
{
}
; ;
declars: /* empty */ declars: /* empty */
{
$$ = newDeclarsInfo();
}
| declar SEMICOLON declars | declar SEMICOLON declars
{
$$ = $3;
addStruct($3, $1);
}
; ;
declar: structdef declar: structdef
@ -29,28 +74,62 @@ declar: structdef
; ;
structdef: STRUCT ID structbody structdef: STRUCT ID structbody
{
$$ = $3;
$$->names[0] = prefix($2, "struct ");
}
; ;
typedef: TYPEDEF STRUCT structbody ID typedef: TYPEDEF STRUCT structbody ID
{
$$ = $3;
$$->names[0] = $4;
}
| TYPEDEF STRUCT ID structbody ID | TYPEDEF STRUCT ID structbody ID
{
$$ = $4;
$$->names[0] = prefix($3, "struct ");
$$->names[1] = $5;
}
; ;
structbody: OPEN_BRACES structmembers CLOSE_BRACES structbody: OPEN_BRACES structmembers CLOSE_BRACES
{
$$ = $2;
}
; ;
structmembers: /* empty */ structmembers: /* empty */
{
$$ = newStructInfo();
}
| structmember SEMICOLON structmembers | structmember SEMICOLON structmembers
{
$$ = $3;
addMember($$, $1);
}
; ;
structmember: type ID structmember: type ID
{
$$ = newMemberInfo($1, $2);
}
; ;
type: LONG type: LONG { $$ = newTypeInfo(false, "long"); }
| DOUBLE | DOUBLE { $$ = newTypeInfo(false, "double"); }
| STRING | STRING { $$ = newTypeInfo(false, "string"); }
| STRUCT ID | STRUCT ID { yyerror("structs without typedef are not yet supported"); YYERROR; }
| ID | ID { $$ = newTypeInfo(false, $1); }
| type POINTER | type POINTER
{
if ($1->isPointer || $1->type == "string") {
yyerror("multiple pointer types are not supported");
YYERROR;
} else {
$$ = newTypeInfo(true, $1->type);
}
}
; ;
%% %%
@ -60,11 +139,103 @@ int main(void) {
return 0; return 0;
} }
void _panic(const char* f, const char* s) {
fprintf(stderr, "panic: %s: %s: %s\n", f, s, strerror(errno));
exit(3);
}
void yyerror(char* s) { void yyerror(char* s) {
extern int yylineno; extern int yylineno;
fprintf(stderr, "%s (line %d)\n", s, yylineno); fprintf(stderr, "%s (line %d)\n", s, yylineno);
exit(2); exit(2);
} }
struct typeinfo* newTypeInfo(bool isPointer, char* type) {
struct typeinfo* info = malloc(sizeof(struct typeinfo));
if (info == NULL) {
panic("malloc");
}
info->isPointer = isPointer;
errno = EINVAL;
if (type == NULL) {
panic("type name is NULL");
}
info->type = type;
return info;
}
struct memberinfo* newMemberInfo(struct typeinfo* type, char* name) {
struct memberinfo* info = malloc(sizeof(struct memberinfo));
if (info == NULL) {
panic("malloc");
}
errno = EINVAL;
if (name == NULL) {
panic("name is NULL");
}
info->type = type;
info->name = name;
return info;
}
struct structinfo* newStructInfo() {
struct structinfo* info = malloc(sizeof(struct structinfo));
if (info == NULL) {
panic("malloc");
}
info->names[0] = NULL;
info->names[1] = NULL;
info->memberno = 0;
info->members = NULL;
}
struct declarsinfo* newDeclarsInfo() {
struct declarsinfo* info = malloc(sizeof(struct declarsinfo));
if (info == NULL) {
panic("malloc");
}
info->structno = 0;
info->structs = NULL;
return info;
}
void addMember(struct structinfo* _struct, struct memberinfo* member) {
_struct->members = realloc(_struct->members, sizeof(struct memberinfo*) * (_struct->memberno + 1));
if (_struct->members == NULL) {
panic("realloc");
}
_struct->members[_struct->memberno++] = member;
}
void addStruct(struct declarsinfo* declars, struct structinfo* _struct) {
declars->structs = realloc(declars->structs, sizeof(struct structinfo*) * (declars->structno + 1));
if (declars->structs == NULL) {
panic("realloc");
}
declars->structs[declars->structno++] = _struct;
}
char* prefix(char* string, const char* prefix) {
char* new = malloc(strlen(string) + strlen(prefix) + 1);
if (new == NULL) {
panic("malloc");
}
strcpy(new, prefix);
strcat(new, string);
free(string);
return new;
}

View file

@ -26,8 +26,10 @@ string "const "?"char"{whitespace}*"*"
%{ %{
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include "y.tab.h" #include "y.tab.h"
#include <helper.h>
%} %}
<*>"/*" { BEGIN(COMMENT); } <*>"/*" { BEGIN(COMMENT); }
@ -54,9 +56,9 @@ string "const "?"char"{whitespace}*"*"
<INITIAL>"[" { return OPEN_BRACKETS; } <INITIAL>"[" { return OPEN_BRACKETS; }
<INITIAL>"]" { return CLOSE_BRACKETS; } <INITIAL>"]" { return CLOSE_BRACKETS; }
<INITIAL>{id} { return ID; } <INITIAL>{id} { yylval.id = strdup(yytext); return ID; }
<INITIAL>{hex} { yylval = strtol(yytext, NULL, 16); return NUM; } <INITIAL>{hex} { yylval.number = strtol(yytext, NULL, 16); return NUM; }
<INITIAL>{dec} { yylval = strtol(yytext, NULL, 10); return NUM; } <INITIAL>{dec} { yylval.number = strtol(yytext, NULL, 10); return NUM; }
<INITIAL>{whitespace}+ { } <INITIAL>{whitespace}+ { }
<INITIAL>. { fprintf(stderr, "lexical error in line %d.\n", yylineno); exit(1); } <INITIAL>. { fprintf(stderr, "lexical error in line %d.\n", yylineno); exit(1); }