#include <getopt.h>
#include "ast.h"
+#include "genc.h"
#include "parse.h"
#include "scan.h"
+#include "sem.h"
extern int yylex_destroy(void);
void usage(FILE *out, char *arg0)
"Compile an spl file. If FILE is not specified stdin is used.\n"
"\n"
"Options:\n"
- "\t-p\tJust parse and pretty print\n"
- "\t-t\tJust parse and typecheck\n"
- "\t-c\tparse, typecheck and compile (default)\n"
+ "\t-p\tPretty print the parsed abstract syntax tree\n"
+ "\t-t\tPretty print the typed abstract syntax tree\n"
+ "\t-g LANG\tGenerate LANG code (default: C)\n"
+ "\t \tSupported languages: C\n"
+ "\t-o FILE\tOutput code to FILE (default: a.suf)\n"
"\t-h\tShow this help\n"
, arg0);
}
-enum mode {parse,type,compile};
-
int main(int argc, char *argv[])
{
- int opt;
- enum mode mode = compile;
+ int opt, r;
+ bool pparse = false, ptype = false;
+ char *cfile = NULL;
+ enum {langc} lang = langc;
+ const char *suffix[] = { [langc] = "c" };
+ struct ast *result = NULL;
+ FILE *cout;
- while ((opt = getopt(argc, argv, "hptc")) != -1) {
+ while ((opt = getopt(argc, argv, "g:ho:tp")) != -1) {
switch (opt) {
+ case 'g':
+ if (strcmp(optarg, "c") == 0
+ || strcmp(optarg, "C") == 0) {
+ lang = langc;
+ } else {
+ usage(stderr, argv[0]);
+ }
+ break;
+ case 'o':
+ cfile = safe_strdup(optarg);
+ break;
case 'p':
- mode = parse;
+ pparse = true;
break;
case 't':
- mode = type;
- break;
- case 'c':
- mode = compile;
+ ptype = true;
break;
case 'h':
usage(stdout, argv[0]);
if ((yyin = fopen(argv[optind], "r")) == NULL)
pdie("fopen");
- struct ast *result = NULL;
- int r = yyparse(&result);
+ //Parse
+ r = yyparse(&result);
+ if (yyin != stdin)
+ safe_fclose(yyin);
+ yylex_destroy();
if (r != 0)
+ return r;
+ if (pparse)
+ ast_print(result, stdout);
+
+ //Typecheck
+ if ((result = sem(result)) == NULL) {
return 1;
- yylex_destroy();
- if (mode == parse) {
+ }
+ if (ptype)
ast_print(result, stdout);
- goto end;
+
+ //Generate code
+ if (cfile == NULL)
+ sprintf(cfile = safe_malloc(10), "a.%s", suffix[lang]);
+ cout = safe_fopen(cfile, "w+");
+ free(cfile);
+ switch(lang) {
+ case langc:
+// genc(result, cout);
+ break;
+ default:
+ die("unsupported language\n");
}
-end:
+ safe_fclose(cout);
ast_free(result);
- if (yyin == stdin)
- if (fclose(yyin) == -1)
- perror("fclose");
- return 0;
+ return r;
}