Изменения

Перейти к: навигация, поиск

Атрибутные транслирующие грамматики

838 байт убрано, 16:29, 5 июня 2015
Атрибуты в ANTLR
Общедоступный генератора разборщиков ANTLR<ref>[http://www.antlr.org/ ANTLR {{---}} Parser generator]</ref> поддерживает синтаксически управляемое определение.
Рассмотрим для примера грамматику арифметических выражений с оператором операторами <tex>+</tex>, <tex>-\times\div</tex>, и выводом результата выражениая.
Вне продукций грамматики бывает нужно вставить в сгенерированный разборщик(для Java) package, import, а также некоторые поля и методы. Это делается с помощью <code>@header</code> и <code>@members</code>:
grammar Expr;
'''@header''' { package toolsru.ifmo.ctddev.wiki; import java.util.*; }
'''@parser::members''' {
Map<String, Integer> memory = new HashMap<String, Integer>();
int eval(int left, int op, int right) {
//...
}
}
Естественным образом можно добавлять действия в продукции, где это нужноСтартовый нетерминал печатает резульат: '''stats :''' '''e''' NEWLINE {System.out.println($e.valvalue);} | ID '=' '''e''' NEWLINE {memory.put($ID.text, $e.val); System.out.println($ID.text + "=" + $e.val);} | NEWLINE ;
Естественным образом можно добавлять действия в продукции, где это нужно. Действия выполняются после предыдущего элемента грамматики и до следующего. В данном примере действия добавлены на конце альтернативы, поэтому действие выполнится после того, как разборщик распознает все выражение. Когда разборщик встречает выражение, за которым идет символ новой строки, ему нужно напечатать результат. Когда он встречает присваивание - ему нужно записать имя и значение переменной в память.
Правило для e '''returns''' ['''eInteger''' теперь выглядит следующим образомvalue]: t {$value = $t.value;} ( '+' t {$value += $t.value;} | '-' t {$value -= $t.value;} )*;
t '''ereturns''' ['''returnsInteger''' [int valvalue]: : a=e op=('*') b=e f {$val value = eval($a.val, $opf.type, $b.val)value;} | a=e op= ('+*') b=e f {$val = eval($a.val, $op.type, $b.val);} | INT {$val value *= $INTf.intvalue;} | ID { String id = $ID.text; $v = memory.containsKey(id) ? memory.get(id) : 0; } | '(' '''e''' ')' {$val = $e.val;} *;
В первой строке здесь определяется возвращаемое значение f '''returns''' ['''Integer''' value]: '-' f {$value = $f.value;} | NUM {$value = Integer.parseInt($NUM.text);} | '(<code' e ')' {$value = $e.value;} ; Техническая деталь для ANTLR, правила для лексического анализатора: WS : [ \t \r \n]+ ->skip ; NUM : [int val0-9]</code>) + ;  В продукции для нетерминала '''e'''. Это именно тот атрибут, на который ссылается определяется возвращаемое значение (<code>$e.val[Integer value]</code> в примерах выше).Во второй строке, присваивания Обращение к этому атрибуту имеет вид <code>a=$e.value</code> и <code>b=e</code> иллюстрируют . В фигурных скобках записаны семантические правила, а действие <code>{$val = eval($a.val, $op.type, $b.val);}</code> {{---}} транслирующий символ из определений, которые мы рассматривали в начале статьи.
== Примечания ==
Анонимный участник

Навигация