![]() |
|
Главная Терминология Хоора 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 [ 114 ] 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 таг а,6: pointer; h: hpoinfer; begin if sym in [A.. Z, empty] then begin (смл/вол) new(a); if j);/ in[A..H]then begin [нетерминальный] find(sym,h); a.terminal:~ false; aMsym :~ h end else begin [терминальный] a\.terminal := true; a\.tsym := sym end ; p := a; q := a; getsym end else if sym = [tben begin term(p,a,b); b\.suc := p; new{b); b\.terminal := true; b\.tsym :== empty; --et-o?- *Т1Г-= -- if sym = ] then getsym else error end else error end [factor] ; beffnfactor(p,a); q := a; whUe sym in [A.. Z,[, ewpV] do begin./i)rrfor(flt yMC, b); b\.alt := nil; а;= 6 end; r := fl end {terwi} ; procedure expression (vatp,q: pointer); var a,b,c: pointer; begJM term(p,a,c): c\.suc := nil; while sym = , do Ъ(ф1 getsym; term(a\.alt, b, c): c\.suc := nil; ;= fr end ; q := f end [expression] ; рюседтеparse (goal: hpointer; yat match: boolean); var s: pointer; begin jT := goal[.entry; repeat If ,$./£гтша/then begin if .sf.jm sym thai begin match true; getsym end tlse match := (s\.tsyni = empty) еЫparsers].тут, match);. Щ Н match tbeh s := s].sue elses := s].alt until S -=401 0 [parse] ; jgin {порождающие правила} getsym; new{sentinel); list:- sentinel; TiMlesym Ф йо kbeginfind{sym,h); getsym; if sym = then getsym else error; , expression {h\.entry,p); p\.edt := nil; I if sym . fbea error; щ':- writeln; readln; getsym end ; h := list; ok := true; [проверка, все ли символы определены whiles Ф sentinel йо begin if Л^.еи/г^ = nil then begin wriielnQ UNDEFINED symbol h].sym); ok := false end ; h := h\.sup if-lofc then goto 99; [цель] getsyjn; find{symfi); readln; writeln; [предложения] while -neof (input) do begin writeC ); getsym; parse(h,ok); H if ofc Л (symJ) then writeln ( correct) else writeln ( incorrect); readln end ; : end . Программа 5,3. Транслятор для языка j(5.13). S.7. ЯЗЫК ПРОГРАММИРОВАНИЯ ПЛ/0 Оставшиеся разделы этой главы посвящены разработке транслятора для языка, который мы назовем ПЛ/0. При создании этого языка учитывались два условия: во-первых, транслятор не должен оказаться слишком громоздким ДЛЯ этой книги, во-вторых, желательно было продемонстрировать большинство основных принципов трансляции языков прО' граммировании высокого уровня. Несомненно, можно было выбрать как более простой, так и более сложный язык; 1 является одним из возможных компромиссов между языкам достаточно простыми для ясности изложения и достато-ш сложными, чтобы ими стоило заниматься. Значительно боЛ похожая разработка, состоящая из трех этапов, будет сматриваться в разд. 5.8-5.11. , Р^с Как видно из разработки программы 5.3, програм управляемые синтаксическими таблицами, или, вернее уп ляемые структурой данных, обеспечивают свободу и гибко' отсутствующие в специальных программах грамматически' разбора. Хотя такая дополнительная гибкость в принципе нужна, она оказывается весьма существенной в транслятоп для так называемых расширяемых языков. Расширяемы^ языки можно дополнять новыми синтаксическими конструк циями более или менее по усмотрению программиста. Так ж- как входной файл программы 5.3, входной файл для транс лятора с расширяемого языка содержит раздел, определяющий расширения языка, используемые в последующей про-л'рдмме. Более сложные, схемы позволяют даже изменять язык в процессе трансляции, чередуя части транслируемой программы с разделами новых определений языка. Однако, хотя эти идеи могут показаться весьма привлекательными, попытки реализовать подобные трансляторы оказались довольно неудачными. Дело в том, что синтаксический анализ - лишь часть всей задачи трансляции и на самом деле даже не самая существенная часть. Ее легче всего формализовать и, следовательно, представить с помощью систематизированной табличной структуры. Гораздо труднее формализовать смысл языка, т. е. выход, или результат трансляции. До сих пор эта задача не была сколько-нибудь удовлетворительно решена, и этим объясняется то, почему разработчики трансляторов относятся к расширяемым языкам с гораздо большим энтузиазмом до их реализации, чем после. Остальную часть этой главы мы посвятим разработке скромного транслятора для конкретного, небольшого языка программирования. |