=== Описание ===
ParserClass осуществляет [[:СинтаксическийРазбор]] [[../XPlusPlus]]. При помощи этого класса можно узнать структуру кода, определить где находятся определения методов, операторы присваивания и другие синтакические конструкции
Если вам нужен [[:ЛексическийРазбор]] -- используйте ScannerClass
Перед чтением этой статьи рекомендуется изучить [[http://msdn.microsoft.com/library/en-us/Axapta/Appendix_about_EBNF/LANG_X++grammar.asp]] ~X++
{{toc}}
=== Возможные сферы применения ===
*[[:RefactoringBrowser]]
*[[:Obfuscator]]
*job для автоматизации вставки вызовов протоколирования работы программы
=== Использование ===
Основной сценарий использования следующий:
*создайте подкласс ParserClass
*перекройте методы обработки событий
*создайте экземпляр вашего подкласса, передав исходник для разбора в качестве параметра конструктора
*вызовите один из методов parseXXX
Поле этого вызываются методы обработки событий в порядке обнаружения этих событий
=== Методы ===
Методы можно разделить на несколько категорий
==== Методы разбора ====
Когда вызываются методы разбора (parseXXX) разбирает исходик, который ему передали в конструкторе и вызывает методы обрабтки событий в тот момент когда он обнаруживает ошибку или использование правила грамматики языка. Если метод обнаруживает ошитбку, он возвращает -1 иначе -- 0
Существует три метода разбора:
*parseClass -- разбор class declaration
*parseExpr - разбор выражения ~X++
*parseFunction - разбирает метод (но не конструктор 'new' -- эту пролему пока неизвестно как решать)
==== Методы обработки событий ====
Вы можете перекрывать методы обработки событий чтобы узнавать о событиях
===== Методы правил =====
Методы правил вызываются когда парсер обаруживает что код соответствует какому-нибудь правилу грамматики языка. Каждый метод требует несколько объектов в качестве аргуметов и возвращает объект.
Вот, например, как выглядит объявления метода ttsstmt_begin, который вызывается когда разборщик находит ttsbegin; в исходном тексте:
protected Object ttsstmt_begin(Object _ttsbegin_sym, Object _semicolon_sym)
Назначение параметров-объектов полностью определяется тем, кто реализует подкласс.
Каждый параметр соответствует части правила и может быть null или равняется результатом ранее вызванного метода-правила.
Вот, например метод-правило для присваивания:
protected Object asgstmt(Object _lval_fld, Object _assign, Object _if_expr)
это соответствует следующему правилу
asg_stmt ::= lval_fld assign if_expr
Что означеает "присваивание это lval (lval_fld) за которым следует знак присваивания (assign), за которым следует выражение (if_expr)". Если мы посмотрим в БНФ, что такое "assign", мы видим следующее:
ASSIGN ::= =
ASSIGN ::= +=
ASSIGN ::= -=
Что можно перевести как "assign может быть '=', '+=', '-='". Это правило отображается в ParserClass как метод:
protected Object assign(Object _asg_sym)
Но т.к. в ParserClass нет метода для '=', '+=', '-=', он передает null в качетстве значения параметра _asg_sym, а конкретный символ можно извлечь из стека:
Object assign(Object _p1)
{
// get concrete assign symbol, wrap it to object and return it
return new SysAnyType(this.name(0));
}
В качестве примера рассмотрим следующий код
ParserClass parser=new NewParserClass('void test(){a=b;}');
parser.parseFunction();
при разборе исходного текста, разборщик находит символ '=' после чего, он вызывает метод 'assign', идет дальше, обнаруживает конек конструкции присваивания и вызывает метод asgstmt передавая в качестве параметра _assign значение ранее вызванного метода 'assign'.
===== метод Error =====
protected void error(int _errorcode, str _token, int _line, int _col)
метод вызывается когда в исходнике обнаруживается ошибка
==== Моетоды для получения состояния ====
Эти методы можно вызывать при обработке методов-событий для того, чтобы получить информацию о состоянии парсера. Каждый такой метод требует одного параметра -- номер значения во внутреннем стеке разборщика. Каждый номер соответствует параметру метода-правила. Например, для правила
protected Object asgstmt(Object _lval_fld, Object _assign, Object _if_expr)
последнему параметру будет соответствовать номер 0, первому -- -3, второму -- -2
===== name =====
Этод метод возвращает идентификатор по номеру значения
===== startLine =====
Возвращает номер строки, в которой начинается часть правила.
===== startingCol =====
Возвращает номер символа в строке. Для второй и далее строк отнимите 1 от возвращаемого дначения чтобы получить настоящий номер строки (возможно, ошибка)
=== Примеры ===
*[[../GenerateParmMethodsExtension]] -- расширение IDE которое извлекает из класса структуру его полей и позволяет генерировать методы parm для этого класса
==== [[KOAN | ]] ====
скачать [[http://www.axaptapedia.com/images/6/6c/Koan.zip]]
[[.ParserClass:KoanShot]]
Позволяет визуализировать структуру кода