Анимация
JavaScript
|
Главная Библионтека OP1 -+x OP2--Примеры четверок: -a = 4 a + b = 7 6 + 3 = 11 Выражение (-a + b)*(c + d) будет соответствовать такой последовательности четверок: -a=4 1 + b=2 c + d=3 2 * 3=4 Целые числа с левой стороны от знаков равенства относятся к другим четверкам. Из сформированных четверок нетрудно генерировать машинный код, а многие компиляторы на основании четверок осуществляют трансляцию в промежуточный код. Цель настоящего раздела - показать, как включать в грамматику выражений действия для генерирования соответствующих четверок. Действия заключаются в угловые скобки <,> и обозначаются как Al, А2... . В данном случае требуются четыре различнтх действия. Алгоритм пользуется стеком, а номера четверок размещаются с помощью целочисленной переменной. Перечислим эти действия: А1 - поместить элемент в стек; А2 - взять три элемента из стека, напечатать их с последующим знаком «=» и номером следующей размещаемой четверки и поместить полученное целое число в стек; A3 - взять два элемента из стека, напечатать их с последующим знаком «=» и номером следующей размещаемой четверки и поместить полученное целое число в стек; А4 - взять один элемент из стека. Грамматика с учетом этих добавленных действий примет вид S -EXP<A4> EXP-TERM ЕХР + <А1>ТЕRМ<А2> TERM-FACT TERM *<A1>FACT<A2> FACT --<A1>FACT<A3> ID<A1> (EXP) ID-abcde Действие Al используется для помещения в стек всех идентификаторов и операторов, а действия А2 и A3 - для получения бинарнтх и унарнтх четверок соответственно. Можно написать код для этих действий на Алголе 68, допуская следующие описания: [1 : 20] union (int, char) stack; intptr : =0, quadno : = 0; char in Считается, что in принимает значение последней считанной литеры (или символа). Покажем действия А1-А4: <A1> stack [ptr plusab 1]:= in <A2> begin for i from ptr - 2 to ptr do print stack [i] print ((" = ", quadno plusab 1, newline)); stack [ptr minusab 2]: = quadno <A3> begin for i from ptr - 1 to ptr do print slack [i] print ((" = ", quadno plusab 1, newline) ); stack [ptr minusab 1] : = quadno <A4> ptr minusab 1 В качестве примера проследим за преобразованием выражения ( - a + b) * (c + d) в четверки. Действие A1 выполняется после распознавания каждого идентификатора и оператора, действие А2 - после второго операнд;: каждого знака бинарной операции, а действие A3 - после первого (и единственного) операнда каждого знака унарной операции. Действие же А4 выполняется только один раз после считывания всего выражения. Следует заметить, что: 1. в рассмотренном примере нам ни разу не пришлось сравнивать приоритеты двух знаков операций, поскольку эта информация содержалась в грамматике; 2. этот метод нетрудно распространить на языки с множеством различнтх приоритетов знаков операций, например Алгол 68; 3. приведенная выше грамматика рекурсивна влево, так как правила вида TERM-FACT x TERM подразумевают иной порядок вычисления: например, (А*(В*С)), а не ((А*В)*С). Тем не менее мы можем преобразовать леворекурсивные правила в праворекурсивные с помощью включения действий в соответствующие места путем введения новтх нетерминалов.
(минус) А1, поместить в стек « - » А1, поместить в стек а A3, удалить из стека 2 Элементы, поместить в стек «1» А1, поместить в стек «+» A1, поместить в стек b А2, удалить из стека 3 Элементы, поместить в стек «2» A1, поместить в стек «X» A1, поместить в стек c -а = 1 1+b=2 A1, поместить в стек «+ » A1, поместить в стек d А2, удалить из стека 3 C+d =3 ) Элементы, поместить в стек "3" А2, удалить из стека 3 2*3 = 4 Элементы, поместить в стек «4» А4, удалить из стека 1 Элемент Так, правила TERM-FACT TERM - TERM x<A1>FACT<A2> эквивалентны правилам TERM-FACT NEW-e X<A1>FACT<A2>NEW Более того, это преобразование можно выполнять автоматически, поэтому для простоты лучше придерживаться терминалов первоначальных (леворекурсивных) правил. Идею о генераторе синтаксического (LL)-анализатора нетрудно расширить включением действий в синтаксис. Точно так же, как «вызывается» правило из другого правила, можно «вызвать» действие, когда оно включено в грамматику. Объем «кода» в вышеприведенном примере весьма невелики, как мы увидим из других примеров, иллюстрирующих тот же метод, труднее всего определить, где в грамматике должны появляться действия, а не писать код для этих действий. 6.2. РАБОТА С ТАБЛИЦЕЙ СИМВОЛОВ Поскольку синтаксический анализатор обычно использует контекстно-свободную грамматику, необходимо найти метод определения контекстно-зависимых частей языка. Например, во многих языках идентификаторы не могут применяться, если они не описаны, и имеются ограничения в отношении способов употребления в программе значений различнтх типов. Для запоминания описанных идентификаторов и их типов большинство компиляторов пользуется таблицей символов. В Алголе 68 таблица символов требуется также для записи информации относительно специфицируемых пользователем видов и обозначений операций. Когда описывается идентификатор, например 0 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 |