Last active
November 13, 2022 21:46
-
-
Save mashingan/2e14c9f219cc8a6fb184d8a27d55bde9 to your computer and use it in GitHub Desktop.
Translate English declaration into C variable declaration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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