#include #define NIL #define INT int #define CHAR char #define BOOL char #define VOID void #define REPR #define ABS #define FORWARD #define REF #define TRUE 1 #define FALSE 0 #define BEGIN { #define IF if ( #define THEN ) { #define ELIF ;} else if ( #define ELSE ;} else { #define FI ; } #define NOT ! #define OREL || #define ANDTH && #define OR || #define AND && #define MOD % #define WHILE while ( #define DO ) { #define OD ; } #define END } #define tk_EOF EOF #define _arg(n) argv[n] #define exit exit(0); FILE *inpfile; FILE *outfile; FILE *runfile; void close(int f) { if (f==1) fclose(inpfile); else if (f==2) fclose(runfile); else if (f==5) fclose(outfile); return; } int open(int f, char *name) { int r = -1; if (f==1) { inpfile = fopen(name, "rt"); r = inpfile?0:-1; } else if (f==2) { runfile = fopen(name, "rt"); r = runfile?0:-1; } return r; } int establish(int f, char *name) { outfile = fopen(name, "wt"); return (outfile?0:-1); } char readc(int f) { char ch = 0; if (f==1) ch = fgetc(inpfile); else if (f==2) ch = fgetc(runfile); return ch; } #define readchar getchar() #define str2int atoi #define int2str itos #define tk_COLON ABS ':' #define tk_LESS ABS '<' #define tk_GREATER ABS '>' #define tk_DIV ABS '/' #define tk_EQUAL ABS '=' #define tk_MULT ABS '*' #define tk_PLUS ABS '+' #define tk_MINUS ABS '-' #define tk_PIPE ABS '|' #define tk_LBRACKET ABS '[' #define tk_RBRACKET ABS ']' #define tk_LPARENTH ABS '(' #define tk_RPARENTH ABS ')' #define tk_SEMICOLON ABS ';' #define tk_COMMA ABS ',' #define tk_REF 257 #define tk_LOC 258 #define tk_STRUCT 259 #define tk_UNION 260 #define tk_TRUE 261 #define tk_FALSE 262 #define tk_NIL 263 #define tk_CHARCONST 264 #define tk_POWER 265 #define tk_UPB 266 #define tk_LWB 267 #define tk_BEGIN 268 #define tk_END 269 #define tk_IF 270 #define tk_THEN 271 #define tk_ELSE 272 #define tk_ELIF 273 #define tk_FI 274 #define tk_FOR 275 #define tk_FROM 276 #define tk_BY 277 #define tk_TO 278 #define tk_WHILE 279 #define tk_DO 280 #define tk_OD 281 #define tk_REPR 282 #define tk_FORWARD 283 #define tk_MOD 284 #define tk_ESAC 285 #define tk_PROC 286 #define tk_ID 287 #define tk_INTCONST 288 #define tk_STRCONST 289 #define tk_COMMENT 290 #define tk_MODE 291 #define tk_AMODE 292 #define tk_ASSIGN 293 #define tk_OR 294 #define tk_OREL 295 #define tk_AND 296 #define tk_ANDTH 297 #define tk_NOT 298 #define tk_ABS 299 #define tk_NEQ 300 #define tk_GEQ 301 #define tk_LEQ 302 #define tk_IS 303 #define tk_ISNT 304 #define tk_OF 305 /* #define tk_EOF 0 */ #define tk_ERROR 1001 // Forward declarations-macros #ifndef debugger #define debugger debugger() #endif VOID debugger; // General constants #define string_size 256 // (upper bound - 4, size in octets - 4) #define array_header_size 8 #define struc_header_size 0 // New modes & structures typedef CHAR STRING[string_size]; typedef struct TOKEN TOKEN; struct TOKEN { INT id; STRING str; STRING descr; INT line; BOOL used; }; // Variables TOKEN token; CHAR nextChar = REPR 0; INT line = 1; BOOL debug_echo = FALSE; BOOL debug_stop = FALSE; BOOL debug_stepwise = FALSE; BOOL debug_expr = FALSE; BOOL code_refs = FALSE; BOOL code_comments = FALSE; // Error: on error display message and terminate! VOID error(STRING msg) BEGIN printf("ERROR: at token '%s', %s(%i): %s\n", token.str, token.descr, token.id, msg); close(1); close(5); exit; return; END; #ifndef read #define read read() #endif CHAR read BEGIN CHAR ch = readc(1); // IF (ch == 10) THEN line = line + 1 FI; return (ch); END; VOID itos(INT value, REF STRING s) BEGIN INT val = value; INT d, i; INT base; BOOL started = FALSE; base = 1000000; IF val < 0 THEN s[0] = '-'; val = -val; i = 1; ELSE i = 0; FI; WHILE base > 1 DO d = ABS '0'; WHILE val >= base DO d = d + 1; val = val - base; OD; IF started OREL d > ABS '0' THEN s[i] = REPR d; started = TRUE; i = i + 1; FI; base = base / 10; OD; s[i] = REPR (val + ABS '0'); s[i+1] = REPR 0; return; END; BOOL IsDigit(STRING s) BEGIN return (s[0] == '-' OREL (s[0] >= '0' ANDTH s[0] <= '9')); END; BOOL StrEqual(STRING s1, STRING s2) BEGIN INT i = 0; WHILE i < string_size ANDTH s1[i] != REPR 0 ANDTH s2[i] != REPR 0 ANDTH s1[i] == s2[i] DO i = i + 1 OD; return (s1[i] == s2[i]); END; INT StrLen(STRING s) BEGIN INT i = 0; WHILE (s[i] != REPR 0) DO i = i + 1 OD; return (i); END; BOOL StrUCase(STRING s) BEGIN INT i = 0; WHILE i < string_size ANDTH s[i] != REPR 0 ANDTH s[i] >= 'A' ANDTH s[i] <= 'Z' DO i = i + 1 OD; return (s[i] == REPR 0); END; INT StrFind(STRING s, CHAR ch, INT start) BEGIN INT i = start; WHILE i < string_size ANDTH s[i] != REPR 0 ANDTH s[i] != ch DO i = i + 1; OD; return (i); END; BOOL StrBelongs(STRING s, CHAR ch) BEGIN INT i = 0; WHILE i < string_size ANDTH s[i] != REPR 0 ANDTH s[i] != ch DO i = i + 1; OD; return (s[i] != REPR 0); END; VOID StrAssign(REF STRING s1, STRING s2) BEGIN INT i = 0; WHILE i < string_size ANDTH s2[i] != REPR 0 DO s1[i] = s2[i]; i = i + 1 OD; s1[i] = s2[i]; return; END; VOID StrTail(REF STRING s1, STRING s2, INT pos) BEGIN INT i = 0; WHILE i+pos < string_size ANDTH s2[i+pos] != REPR 0 DO s1[i] = s2[i+pos]; i = i + 1 OD; s1[i] = s2[i+pos]; return; END; VOID StrSlice(REF STRING t, STRING s, INT start, INT end) BEGIN INT k = start; WHILE k < string_size ANDTH k <= end DO t[k-start] = s[k]; k = k + 1 OD; t[k-start] = REPR 0; return; END; VOID StrAppend(REF STRING s, STRING s1, STRING s2) BEGIN STRING t; INT i = 0, j = 0; WHILE i < string_size ANDTH s1[i] != REPR 0 DO t[j] = s1[i]; i = i + 1; j = j + 1 OD; i = 0; WHILE i < string_size ANDTH s2[i] != REPR 0 DO t[j] = s2[i]; i = i + 1; j = j + 1 OD; t[j] = REPR 0; StrAssign(s, t); return; END; VOID store_token(INT id, STRING descr) BEGIN token.id = id; StrAssign(token.descr, descr); token.line = line; return; END; #ifndef GetTokenId #define GetTokenId GetTokenId() #endif VOID GetTokenId BEGIN StrAssign(token.descr, "RESERVED"); IF StrEqual(token.str, "REF") THEN token.id = tk_REF; ELIF StrEqual(token.str, "LOC") THEN token.id = tk_LOC; ELIF StrEqual(token.str, "STRUCT") THEN token.id = tk_STRUCT; ELIF StrEqual(token.str, "TRUE") THEN token.id = tk_TRUE; ELIF StrEqual(token.str, "FALSE") THEN token.id = tk_FALSE; ELIF StrEqual(token.str, "NIL") THEN token.id = tk_NIL; ELIF StrEqual(token.str, "ABS") THEN token.id = tk_ABS; ELIF StrEqual(token.str, "NOT") THEN token.id = tk_NOT; ELIF StrEqual(token.str, "AND") THEN token.id = tk_AND; ELIF StrEqual(token.str, "OR") THEN token.id = tk_OR; ELIF StrEqual(token.str, "ANDTH") THEN token.id = tk_ANDTH; ELIF StrEqual(token.str, "OREL") THEN token.id = tk_OREL; ELIF StrEqual(token.str, "IS") THEN token.id = tk_IS; ELIF StrEqual(token.str, "ISNT") THEN token.id = tk_ISNT; ELIF StrEqual(token.str, "OF") THEN token.id = tk_OF; ELIF StrEqual(token.str, "BEGIN") THEN token.id = tk_BEGIN; ELIF StrEqual(token.str, "END") THEN token.id = tk_END; ELIF StrEqual(token.str, "IF") THEN token.id = tk_IF; ELIF StrEqual(token.str, "THEN") THEN token.id = tk_THEN; ELIF StrEqual(token.str, "ELSE") THEN token.id = tk_ELSE; ELIF StrEqual(token.str, "ELIF") THEN token.id = tk_ELIF; ELIF StrEqual(token.str, "FI") THEN token.id = tk_FI; ELIF StrEqual(token.str, "FOR") THEN token.id = tk_FOR; ELIF StrEqual(token.str, "FROM") THEN token.id = tk_FROM; ELIF StrEqual(token.str, "BY") THEN token.id = tk_BY; ELIF StrEqual(token.str, "TO") THEN token.id = tk_TO; ELIF StrEqual(token.str, "WHILE") THEN token.id = tk_WHILE; ELIF StrEqual(token.str, "DO") THEN token.id = tk_DO; ELIF StrEqual(token.str, "OD") THEN token.id = tk_OD; ELIF StrEqual(token.str, "PROC") THEN token.id = tk_PROC; ELIF StrEqual(token.str, "MODE") THEN token.id = tk_MODE; ELIF StrEqual(token.str, "LWB") THEN token.id = tk_LWB; ELIF StrEqual(token.str, "UPB") THEN token.id = tk_UPB; ELIF StrEqual(token.str, "REPR") THEN token.id = tk_REPR; ELIF StrEqual(token.str, "FORWARD") THEN token.id = tk_FORWARD; ELIF StrEqual(token.str, "MOD") THEN token.id = tk_MOD; ELIF StrUCase(token.str) THEN store_token(tk_AMODE, "AMODE"); ELSE store_token(tk_ID, "IDENTIFIER"); FI; return; END; BOOL IsSeparator(CHAR ch) BEGIN BOOL result; IF (ch == '(') OREL (ch == ')') OREL (ch == '[') OREL (ch == ']') OREL (ch == ':') OREL (ch == ';') OREL (ch == ',') OREL (ch == '*') OREL (ch == '+') OREL (ch == '-') OREL (ch == '=') OREL (ch == '/') OREL (ch == '>') OREL (ch == '<') OREL (ch == '|') THEN result = TRUE ELSE result = FALSE FI; return (result); END; BOOL IsBlank(CHAR ch) BEGIN BOOL result; IF ch <= ' ' ANDTH ch != REPR tk_EOF THEN result = TRUE ELSE result = FALSE FI; return (result); END; BOOL IsNumber(CHAR ch) BEGIN BOOL result; IF (ch >= '0') ANDTH (ch <= '9') THEN result = TRUE ELSE result = FALSE FI; return (result); END; BOOL IsIdChar(CHAR ch) BEGIN BOOL result; IF ((ch >= 'A') ANDTH (ch <= 'Z')) OREL ((ch >= 'a') ANDTH (ch <= 'z')) OREL IsNumber(ch) OREL (ch == '_') THEN result = TRUE ELSE result = FALSE FI; return (result); END; #ifndef GetSeparator #define GetSeparator GetSeparator() #endif VOID GetSeparator BEGIN IF nextChar == ':' THEN nextChar = read; IF nextChar == '=' THEN store_token(tk_ASSIGN, "ASSIGN"); // ASSIGN StrAssign(token.str, ":="); nextChar = read; ELSE store_token(tk_COLON, "COLON"); // COLON StrAssign(token.str, ":"); FI; ELIF nextChar == '<' THEN nextChar = read; IF nextChar == '=' THEN store_token(tk_LEQ, "LEQ"); // LESSEQUAL StrAssign(token.str, "<="); nextChar = read; ELSE store_token(tk_LESS, "LESS"); StrAssign(token.str, "<") ; // LESS FI; ELIF nextChar == '>' THEN nextChar = read; IF nextChar == '=' THEN store_token(tk_GEQ, "GEQ"); // GREATEREQUAL StrAssign(token.str, ">="); nextChar = read; ELSE store_token(tk_GREATER, "GREATER"); // GREATER StrAssign(token.str, ">"); FI; ELIF nextChar == '/' THEN nextChar = read; IF nextChar == '=' THEN store_token(tk_NEQ, "NEQ"); // NOTEQUAL StrAssign(token.str, "/="); nextChar = read; ELSE store_token(tk_DIV, "DIV"); // DIV StrAssign(token.str, "/"); FI; ELIF nextChar == '=' THEN nextChar = read; store_token(tk_EQUAL, "EQUAL"); // EQUAL StrAssign(token.str, "="); ELIF nextChar == '*' THEN nextChar = read; IF nextChar == '*' THEN store_token(tk_POWER, "POWER"); // POWER StrAssign(token.str, "**"); nextChar = read; ELSE store_token(tk_MULT, "MULT"); // MULT StrAssign(token.str, "*"); FI; ELIF nextChar == '+' THEN nextChar = read; store_token(tk_PLUS, "PLUS"); // PLUS StrAssign(token.str, "+"); ELIF nextChar == '-' THEN nextChar = read; store_token(tk_MINUS, "MINUS"); // MINUS StrAssign(token.str, "-"); ELIF nextChar == '|' THEN nextChar = read; store_token(tk_PIPE, "PIPE"); // PIPE StrAssign(token.str, "|"); ELIF nextChar == '[' THEN nextChar = read; store_token(tk_LBRACKET, "LBRACKET"); // LEFT BRACKET StrAssign(token.str, "["); ELIF nextChar == ']' THEN nextChar = read; store_token(tk_RBRACKET, "RBRACKET"); // RIGHT BRACKET StrAssign(token.str, "]"); ELIF nextChar == '(' THEN nextChar = read; store_token(tk_LPARENTH, "LPARENTH"); // LEFT PARENTHESIS StrAssign(token.str, "("); ELIF nextChar == ')' THEN nextChar = read; store_token(tk_RPARENTH, "RPARENTH"); // RIGHT PARENTHESIS StrAssign(token.str, ")"); ELIF nextChar == ';' THEN nextChar = read; store_token(tk_SEMICOLON, "SEMICOLON"); // SEMI-COLON StrAssign(token.str, ";"); ELIF nextChar == ',' THEN nextChar = read; store_token(tk_COMMA, "COMMA"); // COMMA StrAssign(token.str, ","); ELSE printf("UNEXPECTED ERROR!\n"); FI; return; END; #ifndef GetNextToken #define GetNextToken GetNextToken() #endif VOID GetNextToken BEGIN INT i = 0; IF debug_stepwise THEN debugger; FI; WHILE IsBlank(nextChar) OREL nextChar == '#' DO WHILE IsBlank(nextChar) DO // Handle WHITE SPACE nextChar = read; OD; IF nextChar == '#' THEN // Handle COMMENTS nextChar = read; WHILE nextChar != '\n' DO nextChar = read OD; nextChar = read; ELIF nextChar == '@' THEN nextChar = read; IF nextChar == '+' THEN debug_echo = TRUE; nextChar = read; ELIF nextChar == '-' THEN debug_echo = FALSE; nextChar = read; ELSE debugger; FI; FI; OD; IF nextChar == REPR tk_EOF THEN store_token(tk_EOF, "EOF"); // --------------------------------------------------------------------------------- # // SEPARATORS # // --------------------------------------------------------------------------------- # ELIF IsSeparator(nextChar) THEN GetSeparator; // --------------------------------------------------------------------------------- # // STRINGS # // --------------------------------------------------------------------------------- # ELIF nextChar == '\"' THEN store_token(tk_STRCONST, "STRCONST"); (token.str)[i] = nextChar; i = i + 1; nextChar = read; WHILE nextChar != '\"' DO (token.str)[i] = nextChar; i = i + 1; IF nextChar == '\\' THEN (token.str)[i] = read; i = i + 1; FI; nextChar = read; OD; (token.str)[i] = nextChar; (token.str)[i+1] = REPR 0; nextChar = read; // --------------------------------------------------------------------------------- # // CHARACTERS # // --------------------------------------------------------------------------------- # ELIF nextChar == '\'' THEN nextChar = read; IF nextChar == '\\' THEN // handle special characters nextChar = read; IF nextChar == '\'' OREL nextChar == '\"' OREL nextChar == '\\' THEN (token.str)[0] = nextChar; ELIF nextChar == 't' THEN (token.str)[0] = REPR 9; ELIF nextChar == 'n' THEN (token.str)[0] = REPR 10; ELSE error("Invalid char constant!"); FI; ELSE (token.str)[0] = nextChar; // store char FI; nextChar = read; IF nextChar != '\'' THEN // end of char error("Invalid char constant!"); ELSE (token.str)[1] = REPR 0; store_token(tk_CHARCONST, "CHARCONST"); FI; nextChar = read; // --------------------------------------------------------------------------------- # // INTEGERS # // --------------------------------------------------------------------------------- # ELIF IsNumber(nextChar) THEN store_token(tk_INTCONST, "INTCONST"); WHILE IsNumber(nextChar) DO (token.str)[i] = nextChar; i = i + 1; nextChar = read; OD; (token.str)[i] = REPR 0; // --------------------------------------------------------------------------------- # // IDENTIFIERS # // --------------------------------------------------------------------------------- # ELIF IsIdChar(nextChar) THEN WHILE IsIdChar(nextChar) DO (token.str)[i] = nextChar; i = i + 1; nextChar = read; OD; (token.str)[i] = REPR 0; GetTokenId; // --------------------------------------------------------------------------------- # // ERROR # // --------------------------------------------------------------------------------- # ELSE store_token(tk_ERROR, "ERROR"); (token.str)[0] = nextChar; (token.str)[1] = REPR 0; nextChar = read; FI; token.used = FALSE; return; END; #ifndef generate_code #define generate_code generate_code() #endif VOID generate_code; #ifndef process_frame #define process_frame process_frame() #endif VOID process_frame; INT lookup(STRING name); #define stack_bound 3000 #define proc_info_bound 1000 #define temps_bound 1000 #define rule_assign 1 #define rule_identity 2 #define rule_itemize 3 #define context_firm 1 #define context_strong 2 #define context_meek 3 #define context_week 4 #define context_soft 5 #define entity_empty 0 #define entity_frame 1 #define entity_var 2 #define entity_tempvar 3 #define entity_ptrvar 4 #define entity_argvar 5 #define entity_param 6 #define entity_constant 7 #define entity_proc 8 #define entity_mode 9 #define entity_label 10 #define entity_startscope 11 #define entity_endscope 12 #define max_nesting 10 #define max_gtemps 10 #define max_files 5 #define max_params 10 STRING dummy; // ##################################################################################################// # // TABLE table_strings: all constant strings are stored here! # // ##################################################################################################// # // - maximum table size # // - where strings are stored during compile time # // current_strindex - next char to be used for storing strings into the table # // current_stroffset - next run-time offset with respect to global register # // ##################################################################################################// # #define table_strings_bound 20000 CHAR table_strings[table_strings_bound]; INT current_stroffset = 0; INT current_strindex = 0; // ##################################################################################################// # // Structure PROCINFO: information about procedures # // ##################################################################################################// # //