mirror of
https://github.com/sigmasternchen/libargo
synced 2025-03-15 21:28:54 +00:00
parser now generates the datastructure for the code generation
This commit is contained in:
parent
c355db419d
commit
ee136f5130
4 changed files with 211 additions and 11 deletions
|
@ -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
28
marshaller/src/helper.h
Normal 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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
Loading…
Reference in a new issue