$EXTRN OPEN, GET; $EXTRN PROUT; $EXTRN IMPLODE; $EXTRN BR, CP, DG; $EXTRN DI5; $ENTRY Go { = <Open 'r' 1 <Arg 1>> <Prout <DI5 (<DTD_REF <A <Get 1>>>) >>; } A { e.1 0 e.2 = e.1 e.2; e1 = e1 <A <Get 1>>; } $ENTRY DTD_REF { e.1 = <Obr <Ubkomm <Spar <Ubpr e.1>>>>; } $ENTRY DTD_REF1 { (e.1) = <Open 'r' 1 e.1> <DTD_REF <A <Get 1>>>; } * Парсер DTD в рефал-выражение, в тот вид, * который был в интерпретаторе * регулjaрных выражений (см. пособие по суперкомпилjaтору). /* Например, следующее DTD <!ELEMENT apply ( (minus, (cn | ci | apply) | ( (minus | divide | power), (cn | ci | apply), (cn | ci | apply)) | ( (plus | times), (cn | ci | apply)*) )> будет преобразовано в (Apply (ALT (CAT (ALT (CAT Minus (ALT Cn Ci Apply)) (CAT (ALT Minus Divide Power) (ALT Cn Ci Apply) (ALT Cn Ci Apply) ) (CAT (ALT Plus Times) (ITER (ALT Cn Ci Apply)) ) ) ))) */ * ----------------------------------- * Внимание. В этом варианте не обрабатываютсja * элементы ATTLIST. Obr { = <ElEnd >; ('!ENTITY' e.1 '%' e.2) e.3 = <Entity e.2> <Obr e.3>; ('!ELEMENT' e.1) e.3 = <Element e.1> <Obr e.3>; } Element { ' ' e.1 = <Element e.1>; e.1 = <Element1 ( ) e.1>; } Element1 { (e.a) ' ' e.2 = ( <ElPlus <IMPLODE e.a>> (ALT (CAT <Obr1 <Prob e.2>>)) ); (e.a) s.b e.2 = <Element1 (e.a s.b) e.2>; (e.a) (e.1) e.2 = ( <ElPlus <IMPLODE e.a>> (ALT (CAT <Obr1 <Prob (e.1) e.2>>)) ); } Obr1 { ' ' e.1 = <Obr1 e.1>; e.1 ' ' = <Obr1 e.1>; e.1 '|' e.2 = (ALT <Obr1 e.1> <Obr1 e.2> ); e.1 ',' e.2 = (CAT <Obr1 e.1> <Obr1 e.2> ); e.1 '*' = (ITER <Obr1 e.1> ); e.1 '+' = (ALT (CAT <Obr1 e.1>) (ITER <Obr1 e.1> )); e.1 '?' = (ALT (CAT ) (CAT <Obr1 e.1> )); * e.1 ',' e.2 = (CAT <Obr1 e.1> <Obr1 e.2> ); (e.1) = <Obr1 e.1>; = (CAT ); 'empty' = (CAT ); 'EMPTY' = (CAT ); '#PCDATA' = PCDATA ; * e.1 = (CAT <ElProv <IMPLODE e.1>> ); '%' e.1 ';' = <Obr1 <CP e.1>>; e.1 = <ElProv <IMPLODE e.1>>; } Entity { e.1 '"' e.2 '"' = <BR <Prob e.1> '=' e.2>; } Prob { ' ' e.1 = <Prob e.1>; e.1 ' ' = <Prob e.1>; e.1 = e.1; } * Замены < , > на ( , ) Ubpr { '<' e.1 = '(' <Ubpr e.1>; '>' e.1 = ')' <Ubpr e.1>; s.a e.1 = s.a <Ubpr e.1>; = ; } * Спаривание скобок. Spar { e.1 = <Spar1 ('*') e.1>; } Spar1 { (e.1) '('e.3 = <Spar1 ((e.1)) e.3>; ((e.1) e.2) ')' e.3 = <Spar1 (e.1 (e.2)) e.3>; ('*' e.1) ')' e.3 = 'error' e.1 ')' e.3; (e.1) s.A e.3 = <Spar1 (e.1 s.A) e.3>; ('*' e.1) = e.1; ((e.1) e.2) = 'error' e.1 '(' e.2; } * Убирание комментариев и пролога. * Пропуск ATTLIST. Ubkomm { ('?' e.a '?') e.1 = <Ubkomm e.1>; ('!--' e.a '--') e.1 = <Ubkomm e.1>; ('!ATTLIST' e.a) e.1 = <Ubkomm e.1>; (e.a) e.1 = (e.a) <Ubkomm e.1>; * ??? s.a s.a e.1 = <Ubkomm e.1>; = ; } * Проверки полноты списков тэгов в DTD ElPlus { s.a = s.a <ElPlus1 s.a <DG 'SPISOK__'>>; } ElPlus1 { s.a = <ElPlus1 s.a ( ) ( )>; s.a (e.1 s.a e.2) (e.3) = <PROUT 'REPEAT NAME ' s.a> <BR 'SPISOK__=' (e.1 s.a e.2) (e.3)>; s.a (e.1) (e.3 s.a e.4) = <BR 'SPISOK__=' (e.1 s.a) (e.3 e.4)>; s.a (e.1) (e.3) = <BR 'SPISOK__=' (e.1 s.a) (e.3)>; } ElProv { s.a = s.a <ElProv1 s.a <DG 'SPISOK__'>>; } ElProv1 { s.a = <ElProv1 s.a ( ) ( )>; s.a (e.1 s.a e.2) (e.3) = <BR 'SPISOK__=' (e.1 s.a e.2) (e.3)>; s.a (e.1) (e.3 s.a e.4) = <BR 'SPISOK__=' (e.1) (e.3 s.a e.4)>; s.a (e.1) (e.3) = <BR 'SPISOK__=' (e.1) (e.3 s.a)>; } ElEnd { = <ElEnd1 <DG 'SPISOK__'>>; } ElEnd1 { (e.1) ( ) = ; (e.1) (e.2) = <PROUT 'NO NAME TAG ' e.2>; }