четверг, 18 апреля 2013 г.

Ещё о DSL

Вот так выглядит наш кодогенератор "изнутри":


// Выводит объявление класса
%f _pas_OutClassInterface
//#UC START# *494B7197025Afor470F151302FD*
[{%S#f_IsMixIn()=true}\
%f_set_var(POS,"%f_string_find(%S{ifndef},DesignTimeLibrary)")\
[{%{POS}N!=-1}\
\n\{$IfDef DesignTimeLibrary\}
%f_pas_TypeName(%S) = %f_pas_ImpurityParentName(%S);
\{$EndIf DesignTimeLibrary\}
]\
]\

[\n%S%f_open_ifdef()]\
<{}{%t_interface(%R)=true}%R<{}{%CS=impurity value}%f_set_var(%CN,"%f_pas_TypeName(%C%T)")>>\
// - устанавливаем типы параметров реализуемых методов
[{%S#f_IsMixIn()=true}%f_set_var(WAS_TYPE,"1")]\
// - чтобы лишнее ключевое слово не выводить
%f_shift_intend(-1)\

<{}{%CV!=PrivateAccess&%C%f_IsClassInner()!=true&"%CO"=""}\
[{%CS!=Typedef|%C%GU!=%SU|%C{isClassRef}=true}\
[{"%C{ifdef}"!=""|"%C{ifndef}"!=""}\
%f_pas_OpenType(%S)\
]\
[%CX\n]]\
>\

%f_shift_intend(+1)\
%f_pas_OpenType(%S)\
[{%S{need UC}=true}%U[{ci}\n]\n]\
%S%f_pas_OutMixInValues()\
<{}{"%CS"="impurity value"}\
[{%SU=%C%TU}%SF]\
#_%CN_ = %f_pas_TypeName(%C%T);\n\
>\
<{}{%C#f_IsDefine()=true&%CV=PublicAccess}%CX>\
//
[{%S#f_IsMixIn()=true}{\
%f_set_var(PARENT,"%f_pas_MainParentName(%S)")}\
[{<{}{%G#f_IsMixIn()!=true}{C}>=0}{\
%f_set_var(PARENT,"%f_pas_TypeName(%G)")}\
%f_set_var(PARENT,"%f_pas_ImpurityParentName(%S)")\
]\
]\
//
%f_set_var(WAS_PROLOGUE,"false")\
<{}{%G#f_IsMixIn()=true}\
// [{"%{PARENT}N"!=""}#%f_pas_ImpurityParentName(%G) = %{PARENT}N;\n]\
[{%G<{}{%g#f_IsMixIn()!=true}{C}>=0&"%{PARENT}N"!=""}#%f_pas_ImpurityParentName(%G) = %{PARENT}N;\n]\
%f_set_var(PARENT,"%f_pas_TypeName(%G)")\
%S%f_OutL3ItemsPrologue(%G,"WAS_PROLOGUE")\
%f_OutIncludePrim(%G)\n\
>\
//
<{}{%R#f_IsMixIn()=true}\
#%f_pas_ImpurityParentName(%R) = %{PARENT}N;\n\
%f_set_var(PARENT,"%f_pas_TypeName(%R)")\
%S%f_OutL3ItemsPrologue(%R,"WAS_PROLOGUE")\
%f_OutIncludePrim(%R)\n\
>\
//
#%f_pas_TypeName(%S) = \

[{%Sa=abstract}{\
[{%Sa=final}{\
%f_set_var(CLASS_MARK_PREFIX,"")\
}\
%f_set_var(CLASS_MARK_PREFIX,"final")\
]}\
%f_set_var(CLASS_MARK_PREFIX,"abstract")\
]\
[{"%S%f_pas_OutClassMark()"!=""}{\
[{"%{CLASS_MARK_PREFIX}N"!=""}\{%{CLASS_MARK_PREFIX}N\} ]\
}\
\{\
[{"%{CLASS_MARK_PREFIX}N"!=""}%{CLASS_MARK_PREFIX}N ]\
%S%f_pas_OutClassMark()\} ]\
class[(%S%f_pas_OutAncestor()\
[<{}{%R#f_ClassImplementable()=true&%S%f_SomeAncestorImplements(%R)!=true}\
[ %R#f_open_ifdef()]\
, %f_pas_TypeName(%R)\

[%R<{}{%R#f_ClassImplementable()=true&%1#f_Implements(%R)!=true}\
, %f_pas_TypeName(%R) \{from %f_pas_TypeName(%S)\}\
>\
]\

[%R#f_close_ifdef()\n#]\

>\

])\
]\
[\n# \{* %f_Doc(%S) \}]\
%S%f_pas_OutBeforeFields()
[#private
#// private fields
<{}{%CV=PrivateAccess&%C#f_IsAttribute()=true&%C#f_IsProp()!=true&%CS!=static}[%CX\n]>]\
\

// [{%S%f_HasAnyVCMAreaLink()=true}\
//// #private
//// #// auto fields
////// %f_with_gen_id(intf3.pas,<%R<{}{%CC=Class&%C#f_IsVCMAreaLink()=true}[%CX\n]>>)\
//// %f_with_gen_id(intf3.pas,<{}{%o#f_IsVCMAreaLink()=true}[%oX\n]>)\

// #protected
// #  procedure ClearRefs; override;
// ]\

[#protected
%S%f_pas_OutOverridesIntf()\
]\
\
// [#private
// #// property fields
// %f_with_gen_id(intf3.pas,<{}{%C#f_IsStaticObject()!=true&%C#f_IsStruct()!=true}[%CX\n]>)]\
\
[#private
#// private methods
<{}{%CV=PrivateAccess&%C#f_IsAttribute()!=true&%C%f_IsClassInner()=true}[%CX\n]>]\
\
[#protected
#// property methods
<{}{%C#f_IsProp()=true}[%CX\n]>]\
\

%f_clear_list(REALIZED_METHODS)\
[#protected
#// realized methods\

// Генерируем интерфейс методов "квадратиком", вложенных в фасеты/интерфейсы:
<\

%R<{}{%CC=Class&%C#f_IsClassImplementableElement()=true&%C#f_IsRealizedBySomeClassElement(%1)!=true}\
[\n%C%f_pas_MethodInterface(%1,"r")]\
>\

%R<{}{%1#f_Implements(%G)!=true}{%G}\
%G<{}{%CC=Class&%C#f_IsClassImplementableElement()=true&%C#f_IsRealizedBySomeClassElement(%2)!=true}\
[\n%C%f_pas_MethodInterface(%2,"r")]\
>\
>\

>\
// end Генерируем интерфейс методов "квадратиком"...

<{}{%oS!=inline}\
[{%o#f_IsAttribute()=true|%S%f_IsPublicRealizedMethod(%o)!=true}\
[\n%o%f_pas_MethodInterface(%S,"r")]\
]\
>\n\
]\
// #protected

[#public
#// realized methods
<{\n}{%oS!=inline}\
[{%o#f_IsAttribute()!=true&%S%f_IsPublicRealizedMethod(%o)=true}\
%o%f_pas_MethodInterface(%S,"r")\
]\
>\n\
]\
// #public

[#protected
#// overridden property methods
<{\n}{%O#f_IsAttribute()=true}%O%f_pas_MethodInterface(%S,"o")>\n]\
[#protected
#// overridden protected methods
<{\n}{%OV=ProtectedAccess&%O#f_IsAttribute()!=true&%OS!=inline}\
%O%f_pas_MethodInterface(%S,"o")\
>\n\
]\
// #protected

[#public
#// overridden public methods
<{\n}{%OV=PublicAccess&%O#f_IsAttribute()!=true&%OS!=inline}\
%O%f_pas_MethodInterface(%S,"o")\
>\n\
]\
// #public

[#protected
#// protected fields
<{}{%CV=ProtectedAccess&%C#f_IsAttribute()=true&%C#f_IsProp()!=true&%CS!=static}[%CX\n]>\
]\

[#public
#// public fields
<{}{%CV=PublicAccess&%C#f_IsAttribute()=true&%C#f_IsProp()!=true&%CS!=static}[%CX\n]>\
]\

\
[#protected
#// protected methods
<{}{%CV=ProtectedAccess&%C#f_IsAttribute()!=true&%C%f_IsClassInner()=true&%C#f_IsPublishedAccess()!=true}[%CX\n]>]\
[#public
#// public methods
<{}{%CV=PublicAccess&%C#f_IsAttribute()!=true&%C%f_IsClassInner()=true&%C#f_IsPublishedAccess()!=true}[%CX\n]>]\
\
[#private
#// private properties
%f_with_gen_id(intf2.pas,<{}{%CV=PrivateAccess}[%CX\n]>)]\
[#protected
#// protected properties
%f_with_gen_id(intf2.pas,<{}{%CV=ProtectedAccess}[%CX\n]>)]\

[#public
#// public properties
%f_with_gen_id(intf2.pas,<{}{%CV=PublicAccess}[%CX\n]>)\
%f_with_gen_id(intf2.pas,<{}{%o#f_IsProp()=true&%o%P#f_IsContract()=true}[%oX\n]>)\
]\

[{%S{need UC}=true}%U[{publ}\n]\n]\
[{%S{singleton}=true&<{}{%C#f_IsFactory()=true}{C}>=0}\
#public
#// singleton factory method
#  class function Instance: %f_pas_TypeName(%S);
#   {- возвращает экземпляр синглетона. }
]\

%f_clear_list(CAST_METHODS)\
[#protected
#// Методы преобразования к реализуемым интерфейсам
<{}{%t_interface(%R)=true&%R%f_InTie()!=true}\
%R<{\n}{%R#f_IsPureMixIn()!=true&%t_interface(%R)=true&%f_exists_in_list(CAST_METHODS,R)!=true}\
%f_add_to_list(CAST_METHODS,R)\
%f_pas_OutCastMethodInterface(%R,%1)\
>\
>
]\
%f_clear_list(CAST_METHODS)\

[#published
#// published methods
<{}{%CV=PublicAccess&%C#f_IsAttribute()!=true&%C%f_IsClassInner()=true&%C#f_IsPublishedAccess()=true&%C{isPublishedAccess}!=true}\
[%CX\n]\
>\
]\

%S%f_pas_BeforeClassEnd()\
#end;//%f_pas_TypeName(%S)\
%S%f_pas_AfterClassEnd()\
<{}{%t_interface(%R)=true}%R<{}{%CS=impurity value}%f_set_var(%CN,"")>>\
%f_shift_intend(-1)\

<{}{%CV!=PrivateAccess&%C%f_IsClassInner()!=true&"%CO"=""}\
[{%CS=Typedef&%C%GU=%SU&%C{isClassRef}!=true}[%CX\n]]\
>\

%f_shift_intend(+1)\
%S%f_pas_BeforeClassCloseIfDef()\
[\n%S%f_close_ifdef()]\
%f_shift_intend(-1)\
// %f_warning(%SN)\
%f_with_gen_id(intf3.pas,<{}{%C#f_IsStaticObject()=true|%C#f_IsStruct()=true}\
// %f_warning(%CN)\
[\n%CX]>)\
// - генерируем псевдо-конструкторы записей и StaticObject'ов
%f_shift_intend(+1)\
[\n\
<{}{%CV=PublicAccess&%C#f_IsAttribute()=true&%C#f_IsProp()!=true&%CS=static}\
[\n%CX]\
>\
]\

%f_clear_list(REALIZED_METHODS)
//#UC END# *494B7197025Afor470F151302FD*

или так:


// перекрытие базового стереотипа Delphi интерфейсы и реализация::MDAGenerator
%f _DoSpell
//#UC START# *4B2A19E3038Bfor4B386A11030E*
%S%[inherited]\
[{"%{Tl3StringIDEx}N"=""}%f_find_element(Tl3StringIDEx,Tl3StringIDEx)]\
[{"%{Tl3MessageID}N"=""}%f_find_element(Tl3MessageID,Tl3MessageID)]\
[{"%{Dialogs}N"=""}%f_find_element(4AB0EE02004E,Dialogs)]\

// <{}{%C#f_IsMessage()=true}\
// %C<{}{%C#f_IsChoices()=true}\
// %C%f_DoSpell()>\
// >\

%f_set_var(FOUND,"false")\
%f_set_var(PARENT,"")\
<{}{%P#f_IsClassBase()=true|%P#f_IsUtilityPack()=true}{%P}\
[{%{FOUND}N=false}\
%f_set_var(FOUND,"true")\
%f_set_var(PARENT,P)\
]\
>\

%{PARENT}%f_make_accessable(%{Tl3StringIDEx}U)\
%{PARENT}%f_make_accessable(%{Tl3MessageID}U)\
[{%{PARENT}C=Class}\
%{PARENT}%f_add_dependency(%SU_%{Tl3StringIDEx}U_uses,%{Tl3StringIDEx}U,uses,,USES_Inst)\
%{PARENT}%f_add_dependency(%SU_%{Tl3MessageID}U_uses,%{Tl3MessageID}U,uses,,USES_Inst)\
]\
%{PARENT}%f_add_class(%SU_%{Tl3StringIDEx}U_LCImpl,Constants,LCImpl[{%S#f_IsChoices()=true}_%PN_]%SN,LocalConst_Inst)\
%{LocalConst_Inst}%f_set_visibility_type(%SV)\

[{%S#f_IsChoices()=true}{\
%{LocalConst_Inst}%f_set_documentation(Локализуемые строки %SN)\
}\
%{LocalConst_Inst}%f_set_documentation(Варианты выбора для диалога %PN)\
]\

%{LocalConst_Inst}%f_set_up(TreatAsVars,true)\
// - шаманство, чтобы превратить константы в переменные
%{LocalConst_Inst}%f_set_up(ifdef,%S{ifdef})\
%{LocalConst_Inst}%f_set_up(ifndef,%S{ifndef})\
%{LocalConst_Inst}%f_set_up(children prefix,%S{children prefix})\
%{LocalConst_Inst}%f_set_up(elements prefix,str[_%S{elements prefix}])\

%f_set_var(WAS_USES_TO_DIALOGS,"false")\

<{}{}{%C}\

[{%C#f_IsMessage()=true}{\
%f_set_var(CONST_TYPE,{Tl3StringIDEx})\
}\
[{%{WAS_USES_TO_DIALOGS}N!=true}\
%{PARENT}%f_make_accessable(%{Dialogs}U)\
%f_set_var(WAS_USES_TO_DIALOGS,"true")\
%{PARENT}%f_add_dependency(%SU_%{Tl3MessageID}U_uses_Dialogs,%{Dialogs}U,uses,,USES_Inst)\
]\
%f_set_var(CONST_TYPE,{Tl3MessageID})\
]\

%{LocalConst_Inst}%f_add_attribute(%{LocalConst_Inst}U_%CU_Impl,,%C#f_AdditionalPrefix()%f_N(%C) :\
%{CONST_TYPE}U = (rS : -1; rLocalized : false;\
rKey : '%C%f_pas_Prefix()%C#f_AdditionalPrefix()%f_N(%C)';\
rValue : \

[{"%CD"=""|%C#f_CanUseDocAsValue()!=true}{\
//                 ^ - ибо UserType'ы неправильно выливаются
%CD\
}\
[{"%C{Value}"=""}{\
%C{Value}\
}\
%C%VN\
]\
]\

),Attr_Inst)\

%{Attr_Inst}%f_set_visibility_type(%CV)\
%{Attr_Inst}%f_set_documentation([{}{%C{Value}}[{}{%C%VN}%CD]])\
%{Attr_Inst}%f_set_up(ifdef,%C{ifdef})\
%{Attr_Inst}%f_set_up(ifndef,%C{ifndef})\
%{PARENT}%f_add_operation(%CU_Init,ini,Init_%f_N(%{Attr_Inst}) (),Op_Instance)\
%{Op_Instance}%f_set_documentation(Инициализация %{Attr_Inst}%f_pas_Prefix()%f_N(%{Attr_Inst}))\
%{Op_Instance}%f_set_abstraction_type(final)\
%{Op_Instance}%f_set_visibility_type(PrivateAccess)\

[{"%S{ifdef}"!=""}{\
%f_set_var(IFDEF_VALUE,"%C{ifdef}")\
}\
[{"%C{ifdef}"!=""}{\
%f_set_var(IFDEF_VALUE,"%S{ifdef}")\
}\
%f_set_var(IFDEF_VALUE,"%S{ifdef},%C{ifdef}")\
]\
]\

%{Op_Instance}%f_set_up(ifdef,%{IFDEF_VALUE}N)\

[{"%S{ifndef}"!=""}{\
%f_set_var(IFDEF_VALUE,"%C{ifndef}")\
}\
[{"%C{ifndef}"!=""}{\
%f_set_var(IFDEF_VALUE,"%S{ifndef}")\
}\
%f_set_var(IFDEF_VALUE,"%S{ifndef},%C{ifndef}")\
]\
]\

%{Op_Instance}%f_set_up(ifndef,%{IFDEF_VALUE}N)\
%{Op_Instance}%f_set_uc_content(intf.pas,,\
%{Attr_Inst}%f_pas_Prefix()%f_N(%{Attr_Inst}).Init;\
%C%f_AdditionalInitCode("%{Attr_Inst}%f_pas_Prefix()%f_N(%{Attr_Inst})")\
)\
>\

[{%Gx=true}\
%{PARENT}%f_add_class(%SU_%{CONST_TYPE}U_LCConstArr,ConstantArray,%SNMap,LocalConstArray_Inst)\
[{"%{Pl3StringIDEx}N"=""}%f_find_element(Pl3StringIDEx,Pl3StringIDEx)]\
%{LocalConstArray_Inst}%f_add_inheritable(%{Pl3StringIDEx}U)\
%{LocalConstArray_Inst}%f_add_realized(%GU)\
%{LocalConstArray_Inst}%f_set_up(ifdef,%S{ifdef})\
%{LocalConstArray_Inst}%f_set_up(ifndef,%S{ifndef})\
%{LocalConstArray_Inst}%f_set_visibility_type(%SV)\
%{LocalConstArray_Inst}%f_set_documentation(Карта преобразования локализованных строк %SN)\
%{LocalConstArray_Inst}%f_set_up(Need mapping support,%S{Need mapping support})\
%{LocalConstArray_Inst}%f_set_up(Need map interface,%S{Need map interface})\

%{LocalConst_Inst}<{}{}{%C}\
%{LocalConstArray_Inst}%f_add_attribute(%CU_Arr,,%f_N(%C) :\
%{Pl3StringIDEx}U = %{LocalConst_Inst}N::%CN,Attr_Inst)\
>\

]

//#UC END# *4B2A19E3038Bfor4B386A11030E*

2 комментария:

  1. NameRec: Интересно, как часто приходится вносить изменения в текст, аналогичный приведённому Вами?

    ОтветитьУдалить