Хорошо, у меня очень похожие требования, у меня много строк с разным синтаксисом, в основном строки с пометками и строки с некоторыми кодами для использования в процессе формата смарт-карт, а также строки дескрипторов ключей и секретов. коды, в любом случае, я думаю, что «модель» шаблон / действие - это зверский подход для распознавания и обработки большого количества строк.
Я использую C++/CLI
для разработки моей сборки с именем LanguageProcessor.dll
, ядром этой библиотеки является класс lex_rule, который в основном содержит:
- член Regex
- участник события
Конструктор загружает строку регулярного выражения и вызывает необходимые коды для создания события на лету, используя DynamicMethod
, Emit
и Reflexion
... также в сборку существует другой класс, такой как мета и объект, который создает ans создает объекты с помощью простых имен издателя и класса-получателя, а класс-приемник предоставляет обработчики действий для каждого сопоставленного правила.
Поздно, у меня есть класс с именем fasterlex_engine
, который создает словарь <Regex, action_delegate>
которые загружают определения из массива для запуска.
Проект находится на продвинутой стадии, но я все еще строю, сегодня. Я попытаюсь повысить производительность выполнения, связанного с последовательным доступом к каждой паре ввода каждой строки, используя некоторый механизм поиска в словаре, непосредственно используя регулярное выражение, например:
map_rule[gcnew Regex("[a-zA-Z]")];
Вот некоторые сегменты моего кода:
public ref class lex_rule: ILexRule
{
private:
Exception ^m_exception;
Regex ^m_pattern;
//BACKSTORAGE delegates, esto me lo aprendi asiendo la huella.net de m*e*da JEJE
yy_lexical_action ^m_yy_lexical_action;
yy_user_action ^m_yy_user_action;
public:
virtual property String ^short_id;
private:
void init(String ^_short_id, String ^well_formed_regex);
public:
lex_rule();
lex_rule(String ^_short_id,String ^well_formed_regex);
virtual event yy_lexical_action ^YY_RULE_MATCHED
{
virtual void add(yy_lexical_action ^_delegateHandle)
{
if(nullptr==m_yy_lexical_action)
m_yy_lexical_action=_delegateHandle;
}
virtual void remove(yy_lexical_action ^)
{
m_yy_lexical_action=nullptr;
}
virtual long raise(String ^id_rule, String ^input_string, String ^match_string, int index)
{
long lReturn=-1L;
if(m_yy_lexical_action)
lReturn=m_yy_lexical_action(id_rule,input_string, match_string, index);
return lReturn;
}
}
};
Теперь класс fastlex_engine, который выполняет много пар шаблон / действие:
public ref class fasterlex_engine
{
private:
Dictionary<String^,ILexRule^> ^m_map_rules;
public:
fasterlex_engine();
fasterlex_engine(array<String ^,2>^defs);
Dictionary<String ^,Exception ^> ^load_definitions(array<String ^,2> ^defs);
void run();
};
И ДЛЯ УКРАШЕНИЯ ЭТОЙ ТЕМЫ. Некоторый код моего cpp-файла:
этот код создает вызов конструктора по знаку параметра
inline Exception ^object::builder(ConstructorInfo ^target, array<Type^> ^args)
{
try
{
DynamicMethod ^dm=gcnew DynamicMethod(
"dyna_method_by_totem_motorist",
Object::typeid,
args,
target->DeclaringType);
ILGenerator ^il=dm->GetILGenerator();
il->Emit(OpCodes::Ldarg_0);
il->Emit(OpCodes::Call,Object::typeid->GetConstructor(Type::EmptyTypes)); //invoca a constructor base
il->Emit(OpCodes::Ldarg_0);
il->Emit(OpCodes::Ldarg_1);
il->Emit(OpCodes::Newobj, target); //NewObj crea el objeto e invoca al constructor definido en target
il->Emit(OpCodes::Ret);
method_handler=(method_invoker ^) dm->CreateDelegate(method_invoker::typeid);
}
catch (Exception ^e)
{
return e;
}
return nullptr;
}
Этот код присоединяет любую функцию-обработчик (статическую или нет) для обработки обратного вызова, вызванного сопоставлением входной строки
Delegate ^connection_point::hook(String ^receiver_namespace,String ^receiver_class_name, String ^handler_name)
{
Delegate ^d=nullptr;
if(connection_point::waitfor_hook<=m_state) // si es 0,1,2 o mas => intenta hookear
{
try
{
Type ^tmp=meta::_class(receiver_namespace+"."+receiver_class_name);
m_handler=tmp->GetMethod(handler_name);
m_receiver_object=Activator::CreateInstance(tmp,false);
d=m_handler->IsStatic?
Delegate::CreateDelegate(m_tdelegate,m_handler):
Delegate::CreateDelegate(m_tdelegate,m_receiver_object,m_handler);
m_add_handler=m_connection_point->GetAddMethod();
array<Object^> ^add_handler_args={d};
m_add_handler->Invoke(m_publisher_object, add_handler_args);
++m_state;
m_exception_flag=false;
}
catch(Exception ^e)
{
m_exception_flag=true;
throw gcnew Exception(e->ToString()) ;
}
}
return d;
}
наконец код, который вызывает лексерский движок:
array<String ^,2> ^defs=gcnew array<String^,2> {/* shortID pattern namespc clase fun*/
{"LETRAS", "[A-Za-z]+" ,"prueba", "manejador", "procesa_directriz"},
{"INTS", "[0-9]+" ,"prueba", "manejador", "procesa_comentario"},
{"REM", "--[^\\n]*" ,"prueba", "manejador", "nullptr"}
}; //[3,5]
//USO EL IDENTIFICADOR ESPECIAL "nullptr" para que el sistema asigne el proceso del evento a un default que realice nada
fasterlex_engine ^lex=gcnew fasterlex_engine();
Dictionary<String ^,Exception ^> ^map_error_list=lex->load_definitions(defs);
lex->run();