Короткий ответ
- В CriteriaValue.js измените
module.exports
в первой строке на parser
.
- В index.html поменяйте местами теги
<script>
, чтобы CriteriaValue.js стоял первым.
- (Необязательно) В script.js выведите результаты синтаксического анализа в виде отформатированной строки JSON, чтобы увидеть фактические значения.
Вот плункер: http://plnkr.co/edit/kiBp2Na9s4PXpenCzQjx?p=preview
Длинный ответ
Запустите свой оригинальный плункер и проверьте журналы консоли; вы заметите 2 ошибки:
ReferenceError: Can't find variable: parser (script.js:3)
ReferenceError: Can't find variable: error (CriteriaValue.js:1)
Первая ошибка связана с тем, что объект parser
никогда не создается в глобальной области видимости с помощью script.js или CriteriaValue.js.
Глядя на CriteriaValue.js, вы можете увидеть, что он фактически присваивает сгенерированный объект парсера несуществующему modules.export
. Это поведение PEG.js по умолчанию, так как предполагается, что вы собираетесь использовать свой синтаксический анализатор с node.js. Причина, по которой вы видите ошибку, заключается в том, что объекта module
нет, поэтому мы не можем присвоить этому несуществующему объекту свойство export
. Изменение назначения на parser
, которому мы можем назначить (поскольку PEG.js не использует строгий режим), позволяет избежать этой ошибки и делает parser
доступным для использования в script.js.
Наконец, синтаксический анализатор должен быть создан до того, как script.js сможет его использовать; отсюда и причина свопа <script>
.
Для будущего создания CriteriaValue.js сделайте это следующим образом:
pegjs --export-var parser CriteriaValue.pegjs
Это сгенерирует файл так, что объект будет назначен переменной parser
вместо module.exports
.
Где появляется AngularJS
Как сказал @dirkk в комментариях, определение синтаксического анализатора как глобальной переменной является плохой практикой и, конечно же, не способом AngularJS, который заключается в реализации вашего синтаксического анализатора как службы.
Самый быстрый (но не обязательно лучший) способ сделать это — взять уже сгенерированный код CriteriaValue.js и обернуть вокруг него сервис. например.:
angular.module('yourApp.services', [])
.factory('Parser', function() {
// The generated code, except replace "parser = " with "return "
});
Другой вариант — получить файл .pegjs и сгенерировать парсер на клиенте, используя PEG.buildParser()
:
angular.module('yourApp.services', [])
.factory('Parser', ['$http', '$q', function($http, $q) {
var deferred = $q.defer();
$http.get('path/to/CriteriaValue.pegjs')
.success(function(grammar) {
try {
deferred.resolve(PEG.buildParser(grammar));
} catch (e) {
deferred.reject(e);
}
})
.error(function(message) {
deferred.reject('Unable to load grammar: ' + message);
});
return deferred.promise;
}]);
Это упрощает обновление вашей грамматики, так как вам не придется каждый раз переписывать свой сервис, но добавляет задержку при загрузке вашего приложения. Осуществимость этого зависит от того, насколько сложна ваша грамматика и как часто ее действительно нужно менять.
Несмотря на то, как вы строите свой парсер, вам не обязательно предоставлять сгенерированный объект парсера непосредственно остальной части вашего приложения Angular. Вместо этого вы можете реализовать API более высокого уровня для того, что ваше приложение на самом деле будет делать с этим парсером (например, validate(input)
, getAST(input)
и т. д.). Таким образом, если вы решите в будущем переключиться на другой парсер (например, Jison), у вас будет гораздо меньше кода для изменения.
person
tavnab
schedule
12.06.2015