Skip to content

Instantly share code, notes, and snippets.

@mashingan
Last active November 13, 2022 21:46
Show Gist options
  • Save mashingan/2e14c9f219cc8a6fb184d8a27d55bde9 to your computer and use it in GitHub Desktop.
Save mashingan/2e14c9f219cc8a6fb184d8a27d55bde9 to your computer and use it in GitHub Desktop.
Translate English declaration into C variable declaration
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "declare.h"
char* isFunc(char *s) {
char *ss = s;
removeWhiteSpaces(ss);
removeAorAn(ss);
if (strstr(ss, func) == ss) {
ss = strstr(ss, "rn"); // that retu'rn'[s]
ss += 2;
if (ss && *ss == 's') ss++;
return ss;
}
return s;
}
char* isArray(char *s) {
char *ss = s;
removeWhiteSpaces(ss);
removeAorAn(ss);
if (strstr(ss, arrayof) == ss) {
ss = strstr(ss, "of ");
ss += 3;
return ss;
}
return s;
}
char* isStruct(char *s) {
char *ss = s;
removeWhiteSpaces(ss);
removeAorAn(ss);
if (strstr(ss, structof) == ss) {
ss = strstr(ss, "ype ");
ss += 4;
return ss;
}
return s;
}
char *isPtr(char *s) {
char *ss = s;
removeWhiteSpaces(ss);
removeAorAn(ss);
if (strstr(ss, ptrto) == ss) {
ss = strstr(ss, "to ");
ss += 3;
return ss;
}
return s;
}
char* var(char *s, char* name, int namelen) {
char *ss = s;
char *sc;
removeWhiteSpaces(ss);
removeAorAn(ss);
if ((sc = strstr(ss, "is a")) > ss) {
for (int i = 0; i < namelen && !isspace(ss[i]); i++) {
name[i] = ss[i];
}
sc += 4;
if (sc && *sc == 'n') sc++;
return sc;
}
return s;
}
char* isType(char *s, char* typename, int typelen) {
char *ss = s;
char *sc;
removeWhiteSpaces(ss);
removeAorAn(ss);
memset(typename, 0, typelen);
if (strstr(ss, "int") == ss) {
memcpy(typename, "int", 3);
ss += 3;
} else if (strstr(ss, "void") == ss) {
memcpy(typename, "void", 4);
ss += 4;
} else if (strstr(ss, "char") == ss) {
memcpy(typename, "char", 4);
ss += 4;
} else if (strstr(ss, "float") == ss) {
memcpy(typename, "float", 5);
ss += 5;
} else if (strstr(ss, "double") == ss) {
memcpy(typename, "double", 6);
ss += 6;
} else {
return s;
}
while(!isspace(*ss)) {
ss++;
if (*ss == '.') break;
}
return ss;
}
char* fetchFunc(char *s, struct syms *thesym) {
thesym->modifier = ModFunc;
char *ss = s;
/*
thesym->fnc.ret = malloc(sizeof(struct syms));
parse(&ss, thesym->fnc.ret);
*/
return ss;
}
char *fetchArray(char *s, struct syms *thesym) {
char *st = s;
thesym->modifier = ModArray;
thesym->arrval.size = 0;
removeWhiteSpaces(st);
removeAorAn(st);
char *stt = strchr(st, ' ');
if (!stt) return s;
char buf[10];
#if DEBUG
printf("stt: %s\n", stt);
char temp[stt-st+2];
memcpy(temp, st, stt-st);
temp[stt-st+1] = '\0';
printf("temp arr: %s\n", temp);
#endif
for (char *st2 = st; st2 < stt; st2++) {
if (!isdigit(*st2)) {
return s;
}
}
memcpy(buf, st, stt-st);
thesym->arrval.size = atoi(buf);
return stt;
}
char *fetchStruct(char *s, struct syms *thesym) {
thesym->modifier = ModStruct;
#if DEBUG
printf("*s fetchStruct: %s\n", s);
#endif
char *ss = s;
#define structnamelen 20
char typename[structnamelen];
int typelen = 0;
if (isType(ss, typename, structnamelen) > ss) {
typelen = strlen(typename);
memcpy(thesym->stcval.thetype, typename, typelen);
} else {
removeWhiteSpaces(ss);
for (int i = 0; i < structnamelen && ss[i] && !isspace(ss[i]); i++, typelen++) {
if (ss[i] == '.') break;
thesym->stcval.thetype[i] = ss[i];
}
if (typelen < structnamelen) {
thesym->stcval.thetype[typelen] = '\0';
}
s = ss;
}
#undef structnamelen
return s + typelen;
}
char *fetchPtr(char *s, struct syms *thesym) {
thesym->modifier = ModPtr;
return s;
}
enum modifier parse(char **s, struct syms* thesym) {
char *ss = *s;
char typename[10];
if ((ss = isFunc(*s)) > *s) {
#if DEBUG
printf("parse got func\n");
#endif
*s = fetchFunc(ss, thesym);
} else if ((ss = isArray(*s)) > *s) {
#if DEBUG
printf("parse got array\n");
#endif
*s = fetchArray(ss, thesym);
} else if ((ss = isPtr(*s)) > *s) {
#if DEBUG
printf("parse got pointer\n");
#endif
thesym->modifier = ModPtr;
*s = ss;
} else if ((ss = isStruct(*s)) > *s) {
#if DEBUG
printf("parse got struct\n");
#endif
*s = fetchStruct(ss, thesym);
} else if ((ss = isType(*s, typename, 10)) > *s) {
thesym->modifier = ModPlain;
memset(thesym->typeplain, 0, 10);
memcpy(thesym->typeplain, typename, strlen(typename));
*s = ss;
} else {
thesym->modifier = ModEnd;
}
return thesym->modifier;
}
void checkSyms(struct syms *thesym) {
if (!thesym) return;
printf("modifier: %s", modstring[thesym->modifier]);
switch (thesym->modifier) {
case ModPlain:
printf(" with type: %s\n", thesym->typeplain);
break;
case ModArray:
printf(" with size: %d\n", thesym->arrval.size);
break;
case ModPtr:
printf("^\n");
break;
case ModStruct:
printf(" of type %s\n", thesym->stcval.thetype);
break;
case ModEnd:
printf(";\n");
break;
case ModFunc:
printf(" return "); //checkSyms(thesym->fnc.ret);
printf("\n");
break;
default:
printf("\n");
break;
}
}
void freesyms(struct syms *thesym) {
if (!thesym) return;
if (thesym->modifier == ModFunc)
freefnc(thesym->fnc);
else
free(thesym);
}
void freefnc(struct fnc fnc) {
freesyms(fnc.args);
freesyms(fnc.ret);
}
char* translate(struct syms symbs[], int symlen, char *varname, char* out[], int buflen) {
sprintf(*out, "%s", varname);
#if DEBUG
printf("the current out: %s from varname %s\n", *out, varname);
#endif
struct syms *thetype = NULL;
char temp[buflen];
memset(temp, 0, buflen);
for (int i = 0; i < symlen; i++) {
struct syms sym = symbs[i];
if (sym.modifier == ModPtr) {
#if DEBUG
printf("got pointer\n");
#endif
int outlen = strlen(*out);
memcpy(temp, *out, outlen);
sprintf(*out, "(*%s)", temp);
memset(temp, 0, outlen);
} else if (sym.modifier == ModStruct) {
#if DEBUG
printf("got struct\n");
#endif
int outlen = strlen(*out);
memcpy(temp, *out, outlen);
sprintf(*out, "struct %s %s", sym.stcval.thetype, temp);
memset(temp, 0, outlen);
} else if (sym.modifier == ModEnd) {
#if DEBUG
printf("got end\n");
#endif
strcat(*out, ";");
} else if (sym.modifier == ModArray) {
#if DEBUG
printf("got array\n");
#endif
int outlen = strlen(*out);
memcpy(temp, *out, outlen);
if (sym.arrval.size == 0) {
sprintf(*out, "%s[]", temp);
} else {
sprintf(*out, "%s[%d]", temp, sym.arrval.size);
}
memset(temp, 0, outlen);
} else if (sym.modifier == ModPlain) {
#if DEBUG
printf("got plain type\n");
#endif
thetype = &symbs[i];
} else if (sym.modifier == ModFunc) {
#if DEBUG
printf("got func\n");
#endif
int outlen = strlen(*out);
memcpy(temp, *out, outlen);
sprintf(*out, "%s()", temp);
memset(temp, 0, outlen);
}
#if DEBUG
printf("the current out: %s\n", *out);
#endif
}
if (thetype) {
int outlen = strlen(*out);
memcpy(temp, *out, outlen);
sprintf(*out, "%s %s", thetype->typeplain, temp);
}
#if DEBUG
printf("the current out: %s\n", *out);
#endif
return *out;
}
//#define sample "y is an array of 10 floats."
//#define sample "y is a float."
//#define sample "y is an array of 10 pointers to floats."
//#define sample "z is a pointer to a struct of type a_struct."
//#define sample "zk is a pointer to function that return int."
//#define sample "zz is a pointer to function that return pointer to int."
#define sample "x is a pointer to an array of 10 pointers to functions that return pointer to struct of type resfunc."
//#define sample "x is a pointer to function that return pointer to function that return pointer to int."
int main(int argc, char *argv[]) {
#define buflen 512
//char bufout[buflen];
char *bufout = malloc(buflen);
char *input = sample;
if (argc > 1) {
input = malloc(buflen);
memcpy(input, argv[1], buflen);
}
char *initialinput = input;
printf("input is '%s'\n", input);
char varname[10];
memset(varname, '\0', 10);
char *newinput = var(input, varname, 10);
struct syms symbs[10];
if (newinput == input) {
perror("Invalid variable assignment");
exit(1);
}
input = newinput;
int symcount = 0;
enum modifier parsemod = ModPlain;
while(input && symcount < 10 && parsemod != ModEnd) {
parsemod = parse(&input, &symbs[symcount]);
#if DEBUG
checkSyms(&symbs[symcount]);
printf("count %2d now input '%s'\n", symcount, input);
#endif
symcount++;
}
#if DEBUG
printf("varname is '%s' with rest of input is '%s' and input after parse '%s'\n",
varname, newinput, input);
#endif
translate(symbs, symcount, varname, &bufout, buflen);
printf("the translation from '%s' is '%s'\n", initialinput, bufout);
for (int i = 0; i < 10; i++) {
if (symbs[i].modifier == ModFunc) {
freefnc(symbs[i].fnc);
}
}
free(bufout);
free(input);
#undef buflen
return 0;
}
#define arrayof "array"
#define ptrto "pointer"
#define func "function"
#define structof "struct"
#define removeWhiteSpaces(ss) while(isspace(*(ss))) (ss)++
#define removeAorAn(ss) if (*(ss) == 'a' && (ss)[1] == 'n') {\
(ss) += 2; removeWhiteSpaces(ss);\
} else if (*(ss) == 'a' && (ss)[1] == ' ') {\
(ss)++; removeWhiteSpaces((ss));\
}
enum modifier {
ModPlain,
ModPtr,
ModArray,
ModFunc,
ModStruct,
ModEnum,
ModEnd,
};
static const char *modstring[] = {"Plain Type",
"Pointer",
"Array",
"Function",
"Struct",
"Enum",
"End",
};
struct arr {
int size;
};
struct stc {
char thetype[20];
};
struct fnc {
struct syms *args;
struct syms *ret;
};
struct syms {
enum modifier modifier;
union {
char typeplain[10];
struct fnc fnc;
struct arr arrval;
struct stc stcval;
};
};
char* isFunc(char *s);
char* isArray(char *s);
char* isStruct(char *s);
char* isPtr(char *s);
char* var(char *s, char*, int);
char* isType(char *s, char*, int);
enum modifier parse(char **s, struct syms*);
char* fetchFunc(char *s, struct syms*);
char* fetchArray(char *s, struct syms*);
char* fetchStruct(char *s, struct syms*);
char* fetchPtr(char *s, struct syms*);
void checkSyms(struct syms *thesym);
void freesyms(struct syms *thesym);
void freefnc(struct fnc fnc);
char* translate(struct syms[], int, char*, char*[], int);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment