%{ #include #include #include #include #include #include "log.h" #include "taccutil.h" #include "sscanr.h" #include "debug.h" #include "mmalloc.h" /* This program parses a Coral66 source file, and walks the parse tree to output the source with consistent case and indentation. The input for this program must come from the "filter" program also in this directory. The grammar needs to be refactored a little; currently it parses anything starting with BEGIN as a single block unit; it needs to split those up into separate statements and keep an explicit stack of nested constructs. Note that the language uses ";" as a separator, not a terminator, so some statements require a terminating semicolon and some don't. Could make a refactored grammar a little tricky. */ /* This is the type of objects passed around as $1, $$ etc. */ #define USERTYPE char * #define RBRACE '}' /* Bug in tacc translation - } skipped OK in strings but not int consts */ #define SQUOTE 39 #define DQUOTE 34 int exit_flag = FALSE; int printing = TRUE; int ilev = 0; /* nested begin/end for now. Later use a stack */ int delayed_ilev = 0; extern int _debug; /* set to true for parser diags */ int label = FALSE; char *ProgName = "c66tohtml"; extern char **argv; extern int argc; int verbose = FALSE; void indent(int ilev) { while (ilev-- > 0) printf(" "); } void outs(char *line) { int i, c; static int soft = FALSE, outpos = 0; i = ilev*4; // while (i-- > 0) fputc(' ', stdout); for (;;) { c = (*line++)&255; if (c == '\0') break; if (c == '\n') { i = ilev*4; fputc('\n', stdout); outpos = 0; while (i-- > 0) {fputc(' ', stdout); outpos++;} ilev += delayed_ilev; delayed_ilev = 0; soft = TRUE; } else { if (soft && ((c == ';') || (c == '\n'))) { } else { if (c == ' ' && (outpos >= 72)/* && (outpos + strlen(line) > 78)*/) { fputc('\n', stdout); outpos = 0; i = ilev*4; while (i-- > 0) {fputc(' ', stdout); outpos++;} fputc(' ', stdout); fputc(' ', stdout); outpos += 2; } else { fputc(c, stdout); outpos++; } soft = FALSE; } } } } char *doubleup(char *text, int c) { char *s, *t; int ccount = 0; s = text; while (*s != '\0') if (*s++ == c) ccount += 1; t = s = stackmalloc(strlen(text)+ccount+1); if (s == NULL) { fprintf(stderr, "copyof: malloc fails - not enough room.\n"); exit(EXIT_FAILURE); } for (;;) { if (*text == c) *s++ = c; if ((*s++ = *text++) == '\0') break; } return(t); } char *formatf(char *s, ...) { /* Size the string by vfprint'ing it to /dev/null... */ /* then heapmalloc an appropriate area */ char *APPROPRIATE_STRING; va_list ap; va_start(ap, s); { static FILE *nullfile = NULL; int string_length; if (nullfile == NULL) nullfile = fopen("/dev/null", "w"); if (nullfile == NULL) { fprintf(stderr, "Major error - cannot open /dev/null\n"); fflush(stderr); exit(1); } string_length = vfprintf(nullfile, s, ap); /* fclose(nullfile); */ APPROPRIATE_STRING = tempheapmalloc(string_length+1); vsprintf(APPROPRIATE_STRING, s, ap); } va_end(ap); return(APPROPRIATE_STRING); } char *strlwr(char *orig) { char *s = orig; for (;;) { if (*s == '\0') break; if ((isalpha(*s)) && (isupper(*s))) *s = tolower(*s); s++; } return(orig); } %} /* Main cheats - it invokes the parsing routines explicitly, in order to reduce the size of the parse tree for a whole file. Also allows recovery of errors at useful boundaries */ main: "" { YYTYPE *subroot; void *stacktop; int i; if (strcmp(argv[argc-1], "-v") == 0) { argc -= 1; verbose = TRUE; } if (strcmp(argv[argc-1], "-d") == 0) { argc -= 1; _debug = TRUE; } if (strcmp(argv[argc-1], "-vd") == 0) { argc -= 1; _debug = TRUE; verbose = TRUE; } if (argc == 1) { yyin = fopen("test.ii", "r"); } else if (argc != 2) { fprintf(stderr, "syntax: c66tohtml infile.ii\n"); /* Let's just resume for now... */ yyin = fopen(argv[1], "r"); } else { yyin = fopen(argv[1], "r"); } if (yyin == NULL) { fprintf(stderr, "c66tohtml: cannot open input\n"); exit(EXIT_FAILURE); } fprintf(stderr, "%s: processing %s\n", argv[0], argv[1] == NULL ? "test.ii" : argv[1]); if (verbose) fprintf(stderr, "Starting\n"); for (;;) { stacktop = stackmark(); if (Statementlist_parse(&subroot)) { execute_parsetree(subroot); } else { return(FALSE); } stackrelease(stacktop); if (exit_flag) return(TRUE); //printf("\n"); } } ; Actual: { $$ = $1; } | { $$ = $1; } | { $$ = $1; } | { $$ = $1; }; Actuallist: { $$ = formatf("%s%s", $1, $2); }; RestofActuallist: "," { $$ = formatf(", %s%s", $2, $3); } | "" { $$ = formatf(""); }; Addoperator: "+" { /* NOTE: No void choice. Compare against ... */ $$ = formatf(" + "); } | "\-" { $$ = formatf(" - "); }; Alternative: { $$ = $1; }; Answerspec: { $$ = $1; } | "" { /* Void */ $$ = formatf(""); }; Answerstatement: "ANSWER" { $$ = formatf("'ANSWER' %s", $2); }; Arraydec: "ARRAY" { $$ = formatf("%s'ARRAY' %s%s", $1, $3, $4); }; Arrayitem: "\[" "\]" { $$ = formatf("%s[ %s ]", $1, $3); }; Arraylist: { $$ = formatf("%s%s", $1, $2); }; RestofArraylist: "," { $$ = formatf(", %s%s", $2, $3); } | "" { $$ = formatf(""); }; Assignmentstatement: ":=" { $$ = formatf("%s := %s", $1, $3); } | ":=" { $$ = formatf("%s := %s", $1, $3); }; Base: "\(" "\)" { $$ = formatf("(%s)", $2); } | "\[" "\]" { $$ = formatf("%s[%s]", $1, $3); }; Bitposition: { $$ = $1; }; Block: "BEGIN" { /* ";" "END" */ $$ = formatf("'BEGIN'"); delayed_ilev += 1; }; Booleanword: { $$ = formatf("%s%s", $1, $2); }; RestofBooleanexpr: { $$ = formatf("%s%s%s", $1, $2, $3); } | "" { $$ = formatf(""); }; Boolop: "DIFFER" { $$ = formatf(" 'DIFFER' "); } | "UNION" { $$ = formatf(" 'UNION' "); } | "MASK" { $$ = formatf(" 'MASK' "); } | "SRL" { $$ = formatf(" 'SRL' "); } | "SLL" { $$ = formatf(" 'SLL' "); }; OldBooleanword: { } | "DIFFER" { }; BooleanwordA: { } | "UNION" { }; BooleanwordB: "MASK" { }; BooleanwordC: { } | { }; BooleanwordD: { } | { }; BooleanwordE: { /* Hmmm... 3 and 6 are an infinite loop ... */} | { }; Bracketedcomment: "\([^\)]*\)" { /* ( any sequence of characters in which round brackets are matched ) */ /* TO DO: Add nesting. */ $$ = formatf("%s", @1.text); } | "" { $$ = formatf(""); }; Codesequence: "<[^>]*>" { /* defined in a particular implementation */ /* For example, machine code */ $$ = formatf("%s", @1.text); }; Codestatement: "CODE" "BEGIN" "END" { $$ = formatf("'CODE' 'BEGIN' %s 'END'%s", $3, $4); }; Commentsentence: "COMMENT" "[^;]*" { /* any sequence of characters not including a semi-colon ; * /* TO DO: Allow newlines. Steal code from Algol60 grammar */ $$ = formatf("'COMMENT' %s", @2.text); }; clines: "[^;]*" "$" { $$ = formatf("%s\n%s", @1.text, $3); } | "" { $$ = formatf(""); }; Commoncommunicator: "\(" "\)" { $$ = formatf("%s(%s)", $1, $3); }; exttype: "COMMON" { $$ = formatf("'COMMON' "); } | "EXTERNAL" { $$ = formatf("'EXTERNAL' "); }; Commonitem: { $$ = $1; } | { $$ = $1; } | { $$ = $1; } | { /* removed Void alternative */ $$ = $1; } | { $$ = $1; }; Commonitemlist: ";" { $$ = formatf("%s; %s", $1, $3); }; RestofCommonitemlist: ";" { $$ = formatf("%s; %s", $1, $3); } | "" { $$ = formatf(""); }; Comparator: "=" { $$ = formatf(" = "); } | ">=" { $$ = formatf(" >= "); } | ">" { $$ = formatf(" > "); } | "<=" { $$ = formatf(" <= "); } | "<>" { $$ = formatf(" <> "); } | "<" { $$ = formatf(" < "); }; Comparison: { $$ = formatf("%s%s%s", $1, $2, $3); }; Compoundstatement: "BEGIN" { /* "END" */ $$ = formatf("'BEGIN'"); delayed_ilev += 1; }; Condition: { $$ = formatf("%s%s", $1, $2); }; RestofCondition: "OR" { $$ = formatf(" 'OR' %s%s", $2, $3); } | "" { $$ = formatf(""); }; Conditionalexpression: "IF" "THEN" "ELSE" { $$ = formatf("'IF' %s 'THEN' %s 'ELSE' %s", $2, $4, $6); }; Conditionalstatement: "IF" "THEN" { if ((strncmp($4, "'BEGIN'", 7) == 0) || (strncmp($5, "'BEGIN'", 7) == 0)) { $$ = formatf("'IF' %s 'THEN' %s%s\n", $2, $4, $5); } else { $$ = formatf("'IF' %s 'THEN'\n %s%s", $2, $4, $5); } }; RestofConditionalstatement: "ELSE" { $$ = formatf("\n'ELSE'\n %s", $2); } | "" { $$ = formatf(""); }; Constant: { $$ = $1; } | { $$ = formatf("%s%s", $1, $2); } | { /* ONLY IF ANY s IN ARE ALREADY DEFINED AS CONSTANT SYMBOLS */ $$ = $1; }; Constantlist: { $$ = formatf("%s%s", $1, $2); }; RestofConstantlist: "," { $$ = formatf(", %s%s", $2, $3); } | "" { $$ = formatf(""); }; Datadec: { $$ = $1; } | { $$ = $1; } | { $$ = $1; }; Dec: { $$ = $1; } | { $$ = $1; } | { $$ = $1; } | { $$ = $1; }; Declist: { $$ = formatf("%s%s", $1, $2); }; RestofDeclist: ";" { $$ = formatf("; %s%s", $2, $3); } | "" { $$ = formatf(""); }; Destination: