Как расширить модуль, расширив класс, который он использует? - PullRequest
0 голосов
/ 10 мая 2018

Немного предыстории: Я хотел бы расширить JSON::Tiny, чтобы обеспечить более удобный анализ списков.Это похоже на флаг relaxed для JSON::XS в Perl 5. В частности, я хотел бы иметь возможность поставить запятую в конце списков.Например, { "a" : 1, "b" : 2, }.Обратите внимание на запятую после 2, это не разрешено обычной спецификацией синтаксиса JSON (или JSON::Tiny).

При проверке исходного кода кажется, что это может быть так простокак расширение одного из модулей, JSON :: Tiny :: Grammar , который JSON::Tiny использует внутренне, а затем переопределяет два его правила:

grammar JSON::Relaxed::Grammar is JSON::Tiny::Grammar {
    rule pairlist   { <pair> * %% \,            } # override this rule
    rule arraylist  {  <value> * %% [ \, ]        } #overide this rule
}

Обратите внимание, что единственная модификацияJSON::Tiny::Grammar - это введение оператора %% вместо оператора % для правил pairlist и arraylist.

Такое расширение позволит повторно использовать код.(Альтернативой дублирования всего кода в JSON::Tiny является последнее средство.)

Вопрос : Теперь вопрос заключается в том, как мне создать свое расширение (называемое JSON::Relaxed) без измененияили дублирование кода JSON::Tiny?Вот эскиз модуля, который я хотел бы написать:

unit module JSON::Relaxed;
use v6;

use JSON::Tiny; # <-- since it is a module, I cannot extend it like a class

# a) export all the stuff that JSON::Tiny exports to the caller
# b) Somehow make JSON::Tiny use JSON::Relaxed::Grammar instead of JSON::Tiny::Grammar

Каков наилучший способ достижения а) и б) в комментариях выше?

1 Ответ

0 голосов
/ 10 мая 2018

Вы можете добавить грамматику и действия отдельно, как это:

use JSON::Tiny::Grammar;
use JSON::Tiny::Actions;

Затем выведите свою собственную грамматику, как в вопросе.

Используя полученную грамматику и существующий класс Actions, вы получите

JSON::Relaxed::Grammar.parse($input, :actions(JSON::Tiny::Actions)).ast

Обратите внимание, что в META6.json вы можете найти раздел снабжения , который точно сообщает вам, что вы можете use.

Поскольку вы хотите взять оригинал to-json из JSON::Tiny, вам придется экспортировать to-json, который пересылает оригинал. Вот код, который делает это:

sub to-json(|c) is export {
    use JSON::Tiny;
    to-json(|c);
}

Это сделает символы из JSON::Tiny доступными только внутри лексической области вашей функции to-json, которая просто примет все ее аргументы и вызовет с ними оригинальную функцию to-json.

...