BEGIN 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_CASE = 283; INT tk_OUT = 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; INT tk_EOF = 0; INT tk_ERROR = 1001; # General constants INT string_size = 128; # (upper bound - 4, size in octets - 4) INT array_header_size = 8; INT struc_header_size = 8; # New modes & structures MODE TOKEN = STRUCT(INT id, STRING str, STRING descr, INT line, BOOL used); # Variables STRUCT(INT id, STRING str, STRING descr, INT line, BOOL used) token; CHAR nextChar := REPR 0; INT line := 1; BOOL debug_echo := FALSE; BOOL debug_stop := FALSE; BOOL debug_stepwise := FALSE; BOOL debug_expr := FALSE; # Dummy debugger! PROC debugger = VOID: BEGIN 1; END; # 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(2); close(1); exit; END; PROC read = CHAR: BEGIN CHAR ch := readc(1); # IF (ch = 10) THEN line := line + 1 FI; ch END; PROC IsDigit = (STRING s) BOOL: BEGIN s[0] = '-' OR (s[0] >= '0' AND s[0] <= '9') 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 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; s := t; END; PROC store_token = (INT id, STRING descr) VOID: BEGIN id OF token := id; descr OF token := descr; line OF token := line; END; PROC GetTokenId = VOID: BEGIN STRING s := str OF token; descr OF token := "RESERVED"; id OF token := IF s = "REF" THEN tk_REF ELIF s = "LOC" THEN tk_LOC ELIF s = "STRUCT" THEN tk_STRUCT ELIF s = "TRUE" THEN tk_TRUE ELIF s = "FALSE" THEN tk_FALSE ELIF s = "NIL" THEN tk_NIL ELIF s = "ABS" THEN tk_ABS ELIF s = "NOT" THEN tk_NOT ELIF s = "AND" THEN tk_AND ELIF s = "OR" THEN tk_OR ELIF s = "AND" THEN tk_AND ELIF s = "OR" THEN tk_OR ELIF s = "IS" THEN tk_IS ELIF s = "ISNT" THEN tk_ISNT ELIF s = "OF" THEN tk_OF ELIF s = "BEGIN" THEN tk_BEGIN ELIF s = "END" THEN tk_END ELIF s = "IF" THEN tk_IF ELIF s = "THEN" THEN tk_THEN ELIF s = "ELSE" THEN tk_ELSE ELIF s = "ELIF" THEN tk_ELIF ELIF s = "FI" THEN tk_FI ELIF s = "FOR" THEN tk_FOR ELIF s = "FROM" THEN tk_FROM ELIF s = "BY" THEN tk_BY ELIF s = "TO" THEN tk_TO ELIF s = "WHILE" THEN tk_WHILE ELIF s = "DO" THEN tk_DO ELIF s = "OD" THEN tk_OD ELIF s = "PROC" THEN tk_PROC ELIF s = "MODE" THEN tk_MODE ELIF s = "LWB" THEN tk_LWB ELIF s = "UPB" THEN tk_UPB ELIF s = "REPR" THEN tk_REPR ELIF StrUCase(s) THEN descr OF token := "AMODE"; tk_AMODE ELSE descr OF token := "IDENTIFIER"; tk_ID 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 # IF ch <= ' ' AND ch /= _eof THEN ch <= ' ' AND ch /= REPR 0 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 str OF token := ":="; nextChar := read; ELSE store_token(tk_COLON, "COLON"); # COLON str OF token := ":"; FI; ELIF nextChar = '<' THEN nextChar := read; IF nextChar = '=' THEN store_token(tk_LEQ, "LEQ"); # LESSEQUAL str OF token := "<="; nextChar := read; ELSE store_token(tk_LESS, "LESS"); str OF token := "<"; # LESS FI; ELIF nextChar = '>' THEN nextChar := read; IF nextChar = '=' THEN store_token(tk_GEQ, "GEQ"); # GREATEREQUAL str OF token := ">="; nextChar := read; ELSE store_token(tk_GREATER, "GREATER"); # GREATER str OF token := ">"; FI; ELIF nextChar = '/' THEN nextChar := read; IF nextChar = '=' THEN store_token(tk_NEQ, "NEQ"); # NOTEQUAL str OF token := "/="; nextChar := read; ELSE store_token(tk_DIV, "DIV"); # DIV str OF token := "/"; FI; ELIF nextChar = '=' THEN nextChar := read; store_token(tk_EQUAL, "EQUAL"); # EQUAL str OF token := "="; ELIF nextChar = '*' THEN nextChar := read; IF nextChar = '*' THEN store_token(tk_POWER, "POWER"); # POWER str OF token := "**"; nextChar := read; ELSE store_token(tk_MULT, "MULT"); # MULT str OF token := "*"; FI; ELIF nextChar = '+' THEN nextChar := read; store_token(tk_PLUS, "PLUS"); # PLUS str OF token := "+"; ELIF nextChar = '-' THEN nextChar := read; store_token(tk_MINUS, "MINUS"); # MINUS str OF token := "-"; ELIF nextChar = '|' THEN nextChar := read; store_token(tk_PIPE, "PIPE"); # PIPE str OF token := "|"; ELIF nextChar = '[' THEN nextChar := read; store_token(tk_LBRACKET, "LBRACKET"); # LEFT BRACKET str OF token := "["; ELIF nextChar = ']' THEN nextChar := read; store_token(tk_RBRACKET, "RBRACKET"); # RIGHT BRACKET str OF token := "]"; ELIF nextChar = '(' THEN nextChar := read; store_token(tk_LPARENTH, "LPARENTH"); # LEFT PARENTHESIS str OF token := "("; ELIF nextChar = ')' THEN nextChar := read; store_token(tk_RPARENTH, "RPARENTH"); # RIGHT PARENTHESIS str OF token := ")"; ELIF nextChar = ';' THEN nextChar := read; store_token(tk_SEMICOLON, "SEMICOLON"); # SEMI-COLON str OF token := ";"; ELIF nextChar = ',' THEN nextChar := read; store_token(tk_COMMA, "COMMA"); # COMMA str OF token := ","; ELSE prints("GetSeparator: UNEXPECTED ERROR!"); printn; FI; END; PROC GetNextToken = VOID: BEGIN INT i := 0; STRING debugg := "THERE!"; 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; ELSE 1; FI; OD; # CAUTION: this is EOF IF nextChar = REPR 0 THEN store_token(tk_EOF, "EOF"); ELIF IsSeparator(nextChar) THEN # Handle SEPARATORS GetSeparator; ELIF nextChar = '\"' THEN # Handle STRING constants 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; nextChar := read; OD; (str OF token)[i] := nextChar; (str OF token)[i+1] := REPR 0; nextChar := read; ELIF nextChar = '\'' THEN # Handle CHAR constants (str OF token)[i] := nextChar; i := i + 1; nextChar := read; IF nextChar = '\\' THEN # store backslash (str OF token)[i] := nextChar; i := i + 1; nextChar := read; FI; (str OF token)[i] := nextChar; # store char i := i + 1; nextChar := read; IF nextChar /= '\'' THEN # store backslash store_token(tk_ERROR, "ERROR"); (str OF token)[i] := nextChar; (str OF token)[i+1] := REPR 0; # printf("%s: ERROR: invalid char constant\n",str OF token); ELSE (str OF token)[i] := nextChar; (str OF token)[i+1] := REPR 0; store_token(tk_CHARCONST, "CHARCONST"); FI; nextChar := read; ELIF IsNumber(nextChar) THEN # Handle INTEGER constants 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; ELIF IsIdChar(nextChar) THEN # Handle IDENTIFIERS WHILE IsIdChar(nextChar) DO (str OF token)[i] := nextChar; i := i + 1; nextChar := read; OD; (str OF token)[i] := REPR 0; GetTokenId; ELSE # ERROR store_token(tk_ERROR, "ERROR"); (str OF token)[0] := nextChar; (str OF token)[1] := REPR 0; nextChar := read; FI; used OF token := FALSE; END; STRING message; STRING inpfile := argv[1]; IF open(1, inpfile) < 0 THEN message := "File not found!"; prints(message); printn; exit; FI; message := "Starting lexical analysis..."; prints(message); printn; nextChar := ' '; message := " -> "; GetNextToken; WHILE nextChar /= REPR 0 DO prints(str OF token); prints(message); prints(descr OF token); printn; GetNextToken; OD; close(1); END