Search code examples
pythonpython-3.xclipsclipspy

Clips Beginner: Add regular exp or any alternative to select * in clips rule in python and clipspy


I have a clips rule that matches the path given in the fact of a template and if path matches it assert the id and the text associated with that path into another template. The path is just a text entry in a dictionary. The path is "//Document/Sect[2]/P[2]". I want to make a rule which says something like this:

Pfad "//Document/Sect[*]/P[*]"

So that it can match with //Document/Sect[any number here]/P[any number here]. I could not find anything related to this so if this is possible or not or is there any alternative? Any help would be appreciated. Thank you! Following is my rule code:

rule3= """ 
        (defrule createpara
        (ROW (counter ?A) 
             (ID ?id)                  
             (Text ?text)
             (Path "//Document/Sect/P"))
        
        =>
        (assert (WordPR (counter ?A) 
                        (structure ?id) 
                        (tag "PAR") 
                        (style "Paragraph") 
                        (text ?text))))
        """

Solution

  • CLIPS does not support regular expressions but you can add support to them yourself via the define_function method.

    import re
    import clips
    
    
    RULE = """
    (defrule example-regex-test
      ; An example rule using the Python function within a test
      (path ?path)
      ; You need to double escape (\\\\) special characters such as []
      (test (regex-match "//Document/Sect\\\\[[0-9]\\\\]/P\\\\[[0-9]\\\\]" ?path))
      =>
      (printout t "Path " ?path " matches the regular expression." crlf))
    """
    
    
    def regex_match(pattern: str, string: str) -> bool:
        """Match pattern against string returning a boolean True/False."""
        match = re.match(pattern, string)
    
        return match is not None
    
    
    env = clips.Environment()
    env.define_function(regex_match, name='regex-match')
    env.build(RULE)
    
    env.assert_string('(path "//Document/Sect[2]/P[2]")')
    
    env.run()
    
    $ python3 test.py 
    Path //Document/Sect[2]/P[2] matches the regular expression.