BEGIN #MODULE 'a-lex' is the lexical analyzer #include "AtoC.h" INT tk_COLON = ABS ':'; INT tk_LESS = ABS '<'; INT tk_GREATER = ABS '>'; INT tk_DIV = ABS '/'; INT tk_EQUAL = ABS '='; INT tk_MULT = ABS '*'; INT tk_PLUS = ABS '+'; INT tk_MINUS = ABS '-'; INT tk_PIPE = ABS '|'; INT tk_LBRACKET = ABS '['; INT tk_RBRACKET = ABS ']'; INT tk_LPARENTH = ABS '('; INT tk_RPARENTH = ABS ')'; INT tk_SEMICOLON = ABS ';'; INT tk_COMMA = ABS ','; INT tk_REF = 257; INT tk_LOC = 258; INT tk_STRUCT = 259; INT tk_UNION = 260; INT tk_TRUE = 261; INT tk_FALSE = 262; INT tk_NIL = 263; INT tk_CHARCONST = 264; INT tk_POWER = 265; INT tk_UPB = 266; INT tk_LWB = 267; INT tk_BEGIN = 268; INT tk_END = 269; INT tk_IF = 270; INT tk_THEN = 271; INT tk_ELSE = 272; INT tk_ELIF = 273; INT tk_FI = 274; INT tk_FOR = 275; INT tk_FROM = 276; INT tk_BY = 277; INT tk_TO = 278; INT tk_WHILE = 279; INT tk_DO = 280; INT tk_OD = 281; INT tk_REPR = 282; INT tk_FORWARD = 283; INT tk_MOD = 284; INT tk_ESAC = 285; INT tk_PROC = 286; INT tk_ID = 287; INT tk_INTCONST = 288; INT tk_STRCONST = 289; INT tk_COMMENT = 290; INT tk_MODE = 291; INT tk_AMODE = 292; INT tk_ASSIGN = 293; INT tk_OR = 294; INT tk_OR = 295; INT tk_AND = 296; INT tk_AND = 297; INT tk_NOT = 298; INT tk_ABS = 299; INT tk_NEQ = 300; INT tk_GEQ = 301; INT tk_LEQ = 302; INT tk_IS = 303; INT tk_ISNT = 304; INT tk_OF = 305; #INLINE /* INT tk_EOF = 0; #INLINE */ INT tk_ERROR = 1001; # Forward declarations-macros FORWARD PROC debugger = VOID; # General constants INT string_size = 256; # (upper bound - 4, size in octets - 4) INT array_header_size = 8; INT struc_header_size = 0; # New modes & structures #INLINE typedef CHAR STRING[string_size]; MODE TOKEN = STRUCT(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! PROC error = (STRING msg) VOID: BEGIN printf("ERROR: at token '%s', %s(%i): %s\n", str OF token, descr OF token, id OF token, msg); close(1); close(5); exit; END; PROC read = CHAR: BEGIN CHAR ch := readc(1); # IF (ch = 10) THEN line := line + 1 FI; ch END; PROC itos = (INT value, REF STRING s) VOID: 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 OR 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; END; PROC IsDigit = (STRING s) BOOL: BEGIN s[0] = '-' OR (s[0] >= '0' AND s[0] <= '9') END; PROC StrEqual = (STRING s1, STRING s2) BOOL: BEGIN INT i := 0; WHILE i < string_size AND s1[i] /= REPR 0 AND s2[i] /= REPR 0 AND s1[i] = s2[i] DO i := i + 1 OD; s1[i] = s2[i] END; PROC StrLen = (STRING s) INT: BEGIN INT i := 0; WHILE (s[i] /= REPR 0) DO i := i + 1 OD; i END; PROC StrUCase = (STRING s) BOOL: BEGIN INT i := 0; WHILE i < string_size AND s[i] /= REPR 0 AND s[i] >= 'A' AND s[i] <= 'Z' DO i := i + 1 OD; s[i] = REPR 0 END; PROC StrFind = (STRING s, CHAR ch, INT start) INT: BEGIN INT i := start; WHILE i < string_size AND s[i] /= REPR 0 AND s[i] /= ch DO i := i + 1; OD; i END; PROC StrBelongs = (STRING s, CHAR ch) BOOL: BEGIN INT i := 0; WHILE i < string_size AND s[i] /= REPR 0 AND s[i] /= ch DO i := i + 1; OD; s[i] /= REPR 0 END; PROC StrAssign = (REF STRING s1, STRING s2) VOID: BEGIN INT i := 0; WHILE i < string_size AND s2[i] /= REPR 0 DO s1[i] := s2[i]; i := i + 1 OD; s1[i] := s2[i]; END; PROC StrTail = (REF STRING s1, STRING s2, INT pos) VOID: BEGIN INT i := 0; WHILE i+pos < string_size AND s2[i+pos] /= REPR 0 DO s1[i] := s2[i+pos]; i := i + 1 OD; s1[i] := s2[i+pos]; END; PROC StrSlice = (REF STRING t, STRING s, INT start, INT end) VOID: BEGIN INT k := start; WHILE k < string_size AND k <= end DO t[k-start] := s[k]; k := k + 1 OD; t[k-start] := REPR 0; END; PROC StrAppend = (REF STRING s, STRING s1, STRING s2) VOID: BEGIN STRING t; INT i := 0, j := 0; WHILE i < string_size AND s1[i] /= REPR 0 DO t[j] := s1[i]; i := i + 1; j := j + 1 OD; i := 0; WHILE i < string_size AND s2[i] /= REPR 0 DO t[j] := s2[i]; i := i + 1; j := j + 1 OD; t[j] := REPR 0; StrAssign(s, t); END; PROC store_token = (INT id, STRING descr) VOID: BEGIN id OF token := id; StrAssign(descr OF token, descr); line OF token := line; END; PROC GetTokenId = VOID: BEGIN StrAssign(descr OF token, "RESERVED"); IF StrEqual(str OF token, "REF") THEN id OF token := tk_REF; ELIF StrEqual(str OF token, "LOC") THEN id OF token := tk_LOC; ELIF StrEqual(str OF token, "STRUCT") THEN id OF token := tk_STRUCT; ELIF StrEqual(str OF token, "TRUE") THEN id OF token := tk_TRUE; ELIF StrEqual(str OF token, "FALSE") THEN id OF token := tk_FALSE; ELIF StrEqual(str OF token, "NIL") THEN id OF token := tk_NIL; ELIF StrEqual(str OF token, "ABS") THEN id OF token := tk_ABS; ELIF StrEqual(str OF token, "NOT") THEN id OF token := tk_NOT; ELIF StrEqual(str OF token, "AND") THEN id OF token := tk_AND; ELIF StrEqual(str OF token, "OR") THEN id OF token := tk_OR; ELIF StrEqual(str OF token, "AND") THEN id OF token := tk_AND; ELIF StrEqual(str OF token, "OR") THEN id OF token := tk_OR; ELIF StrEqual(str OF token, "IS") THEN id OF token := tk_IS; ELIF StrEqual(str OF token, "ISNT") THEN id OF token := tk_ISNT; ELIF StrEqual(str OF token, "OF") THEN id OF token := tk_OF; ELIF StrEqual(str OF token, "BEGIN") THEN id OF token := tk_BEGIN; ELIF StrEqual(str OF token, "END") THEN id OF token := tk_END; ELIF StrEqual(str OF token, "IF") THEN id OF token := tk_IF; ELIF StrEqual(str OF token, "THEN") THEN id OF token := tk_THEN; ELIF StrEqual(str OF token, "ELSE") THEN id OF token := tk_ELSE; ELIF StrEqual(str OF token, "ELIF") THEN id OF token := tk_ELIF; ELIF StrEqual(str OF token, "FI") THEN id OF token := tk_FI; ELIF StrEqual(str OF token, "FOR") THEN id OF token := tk_FOR; ELIF StrEqual(str OF token, "FROM") THEN id OF token := tk_FROM; ELIF StrEqual(str OF token, "BY") THEN id OF token := tk_BY; ELIF StrEqual(str OF token, "TO") THEN id OF token := tk_TO; ELIF StrEqual(str OF token, "WHILE") THEN id OF token := tk_WHILE; ELIF StrEqual(str OF token, "DO") THEN id OF token := tk_DO; ELIF StrEqual(str OF token, "OD") THEN id OF token := tk_OD; ELIF StrEqual(str OF token, "PROC") THEN id OF token := tk_PROC; ELIF StrEqual(str OF token, "MODE") THEN id OF token := tk_MODE; ELIF StrEqual(str OF token, "LWB") THEN id OF token := tk_LWB; ELIF StrEqual(str OF token, "UPB") THEN id OF token := tk_UPB; ELIF StrEqual(str OF token, "REPR") THEN id OF token := tk_REPR; ELIF StrEqual(str OF token, "FORWARD") THEN id OF token := tk_FORWARD; ELIF StrEqual(str OF token, "MOD") THEN id OF token := tk_MOD; ELIF StrUCase(str OF token) THEN store_token(tk_AMODE, "AMODE"); ELSE store_token(tk_ID, "IDENTIFIER"); FI; END; PROC IsSeparator = (CHAR ch) BOOL: BEGIN BOOL result; IF (ch = '(') OR (ch = ')') OR (ch = '[') OR (ch = ']') OR (ch = ':') OR (ch = ';') OR (ch = ',') OR (ch = '*') OR (ch = '+') OR (ch = '-') OR (ch = '=') OR (ch = '/') OR (ch = '>') OR (ch = '<') OR (ch = '|') THEN result := TRUE ELSE result := FALSE FI; result END; PROC IsBlank = (CHAR ch) BOOL: BEGIN BOOL result; IF ch <= ' ' AND ch /= REPR tk_EOF THEN result := TRUE ELSE result := FALSE FI; result END; PROC IsNumber = (CHAR ch) BOOL: BEGIN BOOL result; IF (ch >= '0') AND (ch <= '9') THEN result := TRUE ELSE result := FALSE FI; result END; PROC IsIdChar = (CHAR ch) BOOL: BEGIN BOOL result; IF ((ch >= 'A') AND (ch <= 'Z')) OR ((ch >= 'a') AND (ch <= 'z')) OR IsNumber(ch) OR (ch = '_') THEN result := TRUE ELSE result := FALSE FI; result END; PROC GetSeparator = VOID: BEGIN IF nextChar = ':' THEN nextChar := read; IF nextChar = '=' THEN store_token(tk_ASSIGN, "ASSIGN"); # ASSIGN StrAssign(str OF token, ":="); nextChar := read; ELSE store_token(tk_COLON, "COLON"); # COLON StrAssign(str OF token, ":"); FI; ELIF nextChar = '<' THEN nextChar := read; IF nextChar = '=' THEN store_token(tk_LEQ, "LEQ"); # LESSEQUAL StrAssign(str OF token, "<="); nextChar := read; ELSE store_token(tk_LESS, "LESS"); StrAssign(str OF token, "<") ; # LESS FI; ELIF nextChar = '>' THEN nextChar := read; IF nextChar = '=' THEN store_token(tk_GEQ, "GEQ"); # GREATEREQUAL StrAssign(str OF token, ">="); nextChar := read; ELSE store_token(tk_GREATER, "GREATER"); # GREATER StrAssign(str OF token, ">"); FI; ELIF nextChar = '/' THEN nextChar := read; IF nextChar = '=' THEN store_token(tk_NEQ, "NEQ"); # NOTEQUAL StrAssign(str OF token, "/="); nextChar := read; ELSE store_token(tk_DIV, "DIV"); # DIV StrAssign(str OF token, "/"); FI; ELIF nextChar = '=' THEN nextChar := read; store_token(tk_EQUAL, "EQUAL"); # EQUAL StrAssign(str OF token, "="); ELIF nextChar = '*' THEN nextChar := read; IF nextChar = '*' THEN store_token(tk_POWER, "POWER"); # POWER StrAssign(str OF token, "**"); nextChar := read; ELSE store_token(tk_MULT, "MULT"); # MULT StrAssign(str OF token, "*"); FI; ELIF nextChar = '+' THEN nextChar := read; store_token(tk_PLUS, "PLUS"); # PLUS StrAssign(str OF token, "+"); ELIF nextChar = '-' THEN nextChar := read; store_token(tk_MINUS, "MINUS"); # MINUS StrAssign(str OF token, "-"); ELIF nextChar = '|' THEN nextChar := read; store_token(tk_PIPE, "PIPE"); # PIPE StrAssign(str OF token, "|"); ELIF nextChar = '[' THEN nextChar := read; store_token(tk_LBRACKET, "LBRACKET"); # LEFT BRACKET StrAssign(str OF token, "["); ELIF nextChar = ']' THEN nextChar := read; store_token(tk_RBRACKET, "RBRACKET"); # RIGHT BRACKET StrAssign(str OF token, "]"); ELIF nextChar = '(' THEN nextChar := read; store_token(tk_LPARENTH, "LPARENTH"); # LEFT PARENTHESIS StrAssign(str OF token, "("); ELIF nextChar = ')' THEN nextChar := read; store_token(tk_RPARENTH, "RPARENTH"); # RIGHT PARENTHESIS StrAssign(str OF token, ")"); ELIF nextChar = ';' THEN nextChar := read; store_token(tk_SEMICOLON, "SEMICOLON"); # SEMI-COLON StrAssign(str OF token, ";"); ELIF nextChar = ',' THEN nextChar := read; store_token(tk_COMMA, "COMMA"); # COMMA StrAssign(str OF token, ","); ELSE printf("UNEXPECTED ERROR!\n"); FI; END; PROC GetNextToken = VOID: BEGIN INT i := 0; IF debug_stepwise THEN debugger; FI; WHILE IsBlank(nextChar) OR 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"); (str OF token)[i] := nextChar; i := i + 1; nextChar := read; WHILE nextChar /= '\"' DO (str OF token)[i] := nextChar; i := i + 1; IF nextChar = '\\' THEN (str OF token)[i] := read; i := i + 1; FI; nextChar := read; OD; (str OF token)[i] := nextChar; (str OF token)[i+1] := REPR 0; nextChar := read; # --------------------------------------------------------------------------------- # # CHARACTERS # # --------------------------------------------------------------------------------- # ELIF nextChar = '\'' THEN nextChar := read; IF nextChar = '\\' THEN # handle special characters nextChar := read; IF nextChar = '\'' OR nextChar = '\"' OR nextChar = '\\' THEN (str OF token)[0] := nextChar; ELIF nextChar = 't' THEN (str OF token)[0] := REPR 9; ELIF nextChar = 'n' THEN (str OF token)[0] := REPR 10; ELSE error("Invalid char constant!"); FI; ELSE (str OF token)[0] := nextChar; # store char FI; nextChar := read; IF nextChar /= '\'' THEN # end of char error("Invalid char constant!"); ELSE (str OF token)[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 (str OF token)[i] := nextChar; i := i + 1; nextChar := read; OD; (str OF token)[i] := REPR 0; # --------------------------------------------------------------------------------- # # IDENTIFIERS # # --------------------------------------------------------------------------------- # ELIF IsIdChar(nextChar) THEN WHILE IsIdChar(nextChar) DO (str OF token)[i] := nextChar; i := i + 1; nextChar := read; OD; (str OF token)[i] := REPR 0; GetTokenId; # --------------------------------------------------------------------------------- # # ERROR # # --------------------------------------------------------------------------------- # ELSE store_token(tk_ERROR, "ERROR"); (str OF token)[0] := nextChar; (str OF token)[1] := REPR 0; nextChar := read; FI; used OF token := FALSE; END; #MODULE 'a-symbol' set of data structures & functions to manipulate the symbol table FORWARD PROC generate_code = VOID; FORWARD PROC process_frame = VOID; FORWARD PROC lookup = (STRING name) INT; INT stack_bound = 3000; INT proc_info_bound = 1000; INT temps_bound = 1000; INT rule_assign = 1; INT rule_identity = 2; INT rule_itemize = 3; INT context_firm = 1; INT context_strong = 2; INT context_meek = 3; INT context_week = 4; INT context_soft = 5; INT entity_empty = 0; INT entity_frame = 1; INT entity_var = 2; INT entity_tempvar = 3; INT entity_ptrvar = 4; INT entity_argvar = 5; INT entity_param = 6; INT entity_constant = 7; INT entity_proc = 8; INT entity_mode = 9; INT entity_label = 10; INT entity_startscope = 11; INT entity_endscope = 12; INT max_nesting = 10; INT max_gtemps = 10; INT max_files = 5; INT 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 # # ################################################################################################### # INT table_strings_bound = 20000; [table_strings_bound]CHAR table_strings; INT current_stroffset := 0; INT current_strindex := 0; # ################################################################################################### # # Structure PROCINFO: information about procedures # # ################################################################################################### # #