GET "LIBHDR"
GET "pattern"
STATIC $(
WORK=0; WP=0; SUCCFLAG=FALSE
PAT=0; AUX=0
CH=0; PATP=0; PATLEN=0
ERRORFLAG=FALSE
$)
// The Interpreter
LET MATCH(PAT, AUX, STR) = VALOF
$(1 LET W = VEC 128
LET S = 0
WORK, WP, SUCCFLAG := W, 0, FALSE
PUT(1)
UNLESS GETBYTE(AUX,0)=0 DO PUT(GETBYTE(AUX,0))
$(2 // FIRST COMPLETE THE CLOSURE
$( LET N = 1
UNTIL N>WP DO
$( LET P = WORK!N
LET K, Q = GETBYTE(PAT,P), GETBYTE(AUX,P)
SWITCHON K INTO
$( CASE '#': PUT(P+1)
CASE '%': PUT(Q)
DEFAULT: ENDCASE
CASE '(':
CASE '/': PUT(P+1)
UNLESS Q=0 DO PUT(Q)
$)
N := N+1
$)
IF S>=GETBYTE(STR,0) RESULTIS SUCCFLAG
IF WP=0 RESULTIS FALSE
S := S+1
CH := GETBYTE(STR,S)
// NOW DEAL WITH MATCH ITEMS
$( LET N = WP
WP, SUCCFLAG := 0, FALSE
FOR I = 1 TO N DO
$( LET P = WORK!I
LET Q = P
LET K = GETBYTE(PAT,P)
SWITCHON K INTO
$( CASE '#':
CASE '/':
CASE '%':
CASE '(': LOOP
CASE '*'':K := GETBYTE(PAT,Q+1)
Q := Q+1
DEFAULT: // A MATCH ITEM
$( LET K1 = K
IF GETBYTE(PAT,Q+1)='-' DO
$( K1 := GETBYTE(PAT,Q+2)
IF K1='*'' DO K1 := GETBYTE(PAT,Q+3)
$)
UNLESS K<=CH<=K1 LOOP // I.E. NO MATCH
$)
CASE '?': // SUCCESSFUL MATCH
PUT(GETBYTE(AUX,P))
LOOP
$)
$)
$)
$)2 REPEAT
$)1
AND PUT(N) BE TEST N=0
THEN SUCCFLAG := TRUE
ELSE $( FOR I = 1 TO WP IF WORK!I=N RETURN
WP := WP+1
WORK!WP := N
$)
// The Compiler
LET RCH() BE TEST PATP>=PATLEN
THEN CH := ENDSTREAMCH
ELSE $( PATP := PATP+1
CH := GETBYTE(PAT,PATP)
$)
AND NEXTITEM() BE SWITCHON CH INTO
$( CASE '#':
CASE '(':
CASE '/':
CASE ')':
CASE '%':
CASE '?': RCH()
RETURN
CASE '*'':RCH()
DEFAULT: RCH()
IF CH='-' DO $( RCH()
IF CH='*'' DO RCH()
RCH()
$)
$)
AND PRIM() = VALOF
$(1 LET A, OP = PATP, CH
NEXTITEM()
SWITCHON OP INTO
$( CASE ENDSTREAMCH:
CASE ')':
CASE '-':
CASE '/': ERRORFLAG := TRUE
DEFAULT: RESULTIS A
CASE '#': SETEXITS(PRIM(), A)
RESULTIS A
CASE '(': A := EXP(A)
UNLESS CH=')' DO ERRORFLAG := TRUE
NEXTITEM()
RESULTIS A
$)
$)1
AND EXP(ALTP) = VALOF
$(1 LET EXITS = 0
$(2 LET A = PRIM()
TEST CH='/' \/ CH=')' \/ CH=ENDSTREAMCH
THEN $( EXITS := JOIN(EXITS,A)
UNLESS CH='/' RESULTIS EXITS
PUTBYTE(AUX,ALTP,PATP)
ALTP := PATP
NEXTITEM()
$)
ELSE SETEXITS(A,PATP)
$)2 REPEAT
$)1
AND SETEXITS(LIST,VAL) BE UNTIL LIST=0 DO
$( LET A = GETBYTE(AUX,LIST)
PUTBYTE(AUX,LIST,VAL)
LIST := A $)
AND JOIN(A,B) = VALOF
$( LET T = A
IF A=0 RESULTIS B
UNTIL GETBYTE(AUX,A)=0 DO A := GETBYTE(AUX,A)
PUTBYTE(AUX,A,B)
RESULTIS T
$)
AND CMPLPAT(PATTERN, CMPLPATTERN) = VALOF
$(1 PAT, AUX := PATTERN, CMPLPATTERN
PATP, PATLEN := 0, GETBYTE(PAT,0)
ERRORFLAG := FALSE
FOR I = 0 TO PATLEN DO PUTBYTE(AUX,I,0)
RCH()
SETEXITS(EXP(0),0)
RESULTIS NOT ERRORFLAG
$)1