Hashtable/dictionary/map lookup with regular expressions

前端 未结 19 1285
难免孤独
难免孤独 2021-02-01 05:36

I\'m trying to figure out if there\'s a reasonably efficient way to perform a lookup in a dictionary (or a hash, or a map, or whatever your favorite language calls it) where the

19条回答
  •  孤街浪徒
    2021-02-01 06:15

    Ok, I have a very similar requirements, I have a lot of lines of different syntax, basically remark lines and lines with some codes for to use in a process of smart-card format, also, descriptor lines of keys and secret codes, in every case, I think that the "model" pattern/action is the beast approach for to recognize and to process a lot of lines.
    I'm using C++/CLI for to develop my assembly named LanguageProcessor.dll, the core of this library is a lex_rule class that basically contains :

    • a Regex member
    • an event member

    The constructor loads the regex string and call the necessary codes for to build the event on the fly using DynamicMethod, Emit and Reflexion... also into the assembly exists other class like meta and object that constructs ans instantiates the objects by the simple names of the publisher and the receiver class, receiver class provides the action handlers for each rule matched.

    Late, I have a class named fasterlex_engine that build a Dictionary that load the definitions from an array for to run.

    The project is in advanced point but I'm still building, today. I will try to enhance the performance of running surrounding the sequential access to every pair foreach line input, thru using some mechanism of lookup the dictionary directly using the regexp like:

    map_rule[gcnew Regex("[a-zA-Z]")];
    

    Here, some of segments of my code:

    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;
            }
        }
    };
    

    Now the fasterlex_engine class that execute a lot of pattern/action pair:

    public ref class fasterlex_engine 
    {
    private: 
        Dictionary ^m_map_rules;
    public:
        fasterlex_engine();
        fasterlex_engine(array^defs);
        Dictionary ^load_definitions(array ^defs);
        void run();
    };
    

    AND FOR TO DECORATE THIS TOPIC..some code of my cpp file:

    this code creates a constructor invoker by parameter sign

    inline Exception ^object::builder(ConstructorInfo ^target, array ^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;
    

    }

    This code attach an any handler function (static or not) for to deal with a callback raised by matching of a input string

    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 ^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;       
    }
    

    finally the code that call the lexer engine:

    array ^defs=gcnew array  {/*   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 ^map_error_list=lex->load_definitions(defs);
    lex->run();
    

提交回复
热议问题