=== Описание === 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]] Позволяет визуализировать структуру кода