Community
    • Login

    FunctionList Confused

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    82 Posts 5 Posters 20.4k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Lycan ThropeL
      Lycan Thrope @Lycan Thrope
      last edited by

      @lycan-thrope One more time…with the whole thing. :)

      These are the regexs I built leading up to the final ones (4,5,6,7) that work with the complete line in some or fashion. Still need to watch the word wrap.

      1: ^(class)\s([a-zA-Z0-9]+)\s([a-zA-Z0-9+]+)\s([a-zA-Z0-9+]+)
      2: ^(class)\s(\w*)\s(\w*)\s(\w*)
      3: (?x)^[\t\x20]*(class)[\t\x20]+((\w+)|(\w+)[\x20]+(\((\w+)(,\w+)?\))?)?((\w+|[^\r\n]*)[\t\x20]+)*(custom)?
      4: (class)[\t\x20]*(\w+)([\t\x20]*?\(\w*(,[\t\x20]?\w*)*?\))?([\t\x20]of[\t\x20]\w*(\(\w*(,[\t\x20]?\w*)*?\))?([\t\x20]custom)?([\t\x20]from[\t\x20](:\w*:\w*\.\w*|"\w*\.\w*"))?)?
      5: (class)[\t\x20]*(\w+)([\t\x20]*?\(\w*(,[\t\x20]?\w*)*?\))?(([\t(\x20]of)[\t\x20]\w*(\(\w*(,[\t\x20]?\w*)*?\))?([\t\x20]custom)?([\t\x20]from[\t\x20](:\w*:\w*\.\w*|"\w*\.\w*"))?)?
      6: (class)[\t\x20]*(\w+)([\t\x20]*?\(\w*(,[\t\x20]?\w*)*?\))?([\t(\x20]of[\t\x20](\w*))?(\(\w*(,[\t\x20]?\w*)*?\))?([\t\x20]custom)?([\t\x20]from[\t\x20]((:\w*:\w*\.\w*)|("\w*\.\w*")))?
      7: (?:class)[\t\x20]*(?'Classname'\w+)([\t\x20]*?\(\w*(,[\t\x20]?\w*)*?\))?(([\t(\x20]of)[\t\x20](?'Superclass'\w*)(\(\w*(,[\t\x20]?\w*)*?\))?([\t\x20](?'Custom'custom))?([\t\x20]from[\t\x20](:\w*:\w*\.\w*|"\w*\.\w*"))?)?

      1 Reply Last reply Reply Quote 0
      • PeterJonesP
        PeterJones @Lycan Thrope
        last edited by

        @lycan-thrope said in FunctionList Confused:

        I highlighted the character to see if these old eyes could make out what it was, and as you see, the little pop up that “says” what it is, is mistaken.

        The word “QUOTE” shows up like that if you select any text:
        06af42e0-fa33-4141-8b23-02bd2b5ae55b-image.png

        It is not telling you what character that is. It is the Forum asking you if you would like to use the selected text as the QUOTE portion in your reply.

        If you have multiple lines of example text, use the LITERAL TEXT BOXES , not the RED TYPEWRITER TEXT.

        But this is getting off the point, and you have shown your regexes. So unless you have more about FunctionList, I think we’ve spent enough on forum formatting.

        Lycan ThropeL 1 Reply Last reply Reply Quote 1
        • Lycan ThropeL
          Lycan Thrope @Michael Vincent
          last edited by

          @michael-vincent
          Thanks Michael, that’s where some of the understanding is coming from, with the ability to read english via the Java.xml versus the cpp.xml, but since I’m not completely familar with java’s syntax and variations, it’s still clear as mud, but getting clearer. :-)

          1 Reply Last reply Reply Quote 0
          • Lycan ThropeL
            Lycan Thrope @PeterJones
            last edited by

            @peterjones
            I do appreciate your help, in this regard. I’ve been around awhile, but have to admit, posting in here, is a little different that what I’m used to, even after reading the FAQ…thanks for that clarification, though. Hate to look dumber than I am. :)

            Lee

            Lycan ThropeL 1 Reply Last reply Reply Quote 0
            • Lycan ThropeL
              Lycan Thrope @Lycan Thrope
              last edited by

              @lycan-thrope
              Okay, so no after beating the keyboard and my head all day, I figured it was time to present what I have tried and still doesn’t work…but to be fair, all I’m trying to do is get FunctionList to see my class first. Baby steps.

              This is my functionlist file:

              <?xml version="1.0" encoding="UTF-8" ?>
              <!-- ==========================================================================\
              |
              |   To learn how to make your own language parser, please check the following
              |   link:
              |       https://npp-user-manual.org/docs/function-list/
              |
              \=========================================================================== -->
              <NotepadPlus>
              	<functionList>
              		<!-- ========================================================= [ dBASEPlus ] -->
              		<parser
              			displayName="dBASEPlus"
              			id         ="dbaseplus"
              			commentExpr="(?s:/\*.*?\*/)|(?m-s://.*?$)"
              		>
              			<classRange
              				mainExpr="(?x)                                                                 # use inline comments
              					^[\t\x20]*                                                                 # leading whitespace
                                  class							# class keyword
              					[\t\x20]*(\w+)							# class name
              										# Following the class name there is the option of parameters, and if so
              										# the first entry inside the parens is required, whether there is other 
              										# parameters or not, once the parens go up, the first is required. ie:
              										# class FrameCtrl(frameObj)
              					([\t\x20]*?\(\w*	# first and required parameter
              					((,[\t\x20]?\w*)*)?\))?			# the following optional/additional	parameters
              													# For the rest of the class declaration, after the class name
              													# all other options are part of one big optional set, that 
              													# follows 'of' and can be populated by one of several 
              													# options. The first and most prevalent is the Superclass
              													# name that the class is being subclassed from, and it's
              													# options of parameters and again, if it has parameters at
              													# least the first one is required ie.:
              													# class class ToolButtonFx(oParent) of Toolbutton(oParent)
              					(([\t(\x20]of)[\t\x20]\w*(\(\w*((,[\t\x20]?\w*)*)?\))?
              													# The next possible option is that it is a custom object and
              													# needs to be in this line so if the object or form is opened
              													# up in the dBASE IDE, the designers in it won't mess up
              													# the object by streaming out missing parts or overriding 
              													# properties or objects and functions.
              					([\t\x20]custom)?
              													# The next option is that the class is being subclassed from
              													# another object that is contained elsewhere and the compiler
              													# needs to know this reference.  There are two options for 
              													# pointing to the file. The first is an Alias path in the IDE
              													# that can be accessed by the compiler in the environment, or 
              													# second, it is in the current directory and only the name is
              													# needed...or it has a path that can be listed here, but this
              													# is bad practice, and an Alias is recommended if the file is in
              													# a place other than the current directory. If it is, the name
              													# can be used in quotes as a string that gets passed to the 
              													# compiler. Both follow the word 'From'. The Alias directory
              													# is a name that is enclosed in two colons, one immediately
              													# before the Alias name and one immediately after, no spaces.
              					([\t\x20]from[\t\x20](:\w*:\w*\.\w*| \x22 \w*\.\w* \x22))?)?   # end of class declaration line
              					
              				"
              				
              				closeSymbole="endclass"
              			>
              				<className>
              					<nameExpr
              						expr="(?x)
              						[\t\x20]*?
              						^class					# class  keyword
              						[\t\x20]*
              						\K(\w+)                   # Class name
              						"
              					/>
              					
              				</className>
              				<function
              					mainExpr="                                                                     # function body
              					"
              				>
              					<functionName>
              						<funcNameExpr
              							expr="                                                            # function parameters
              							"
              						/>
              						<funcNameExpr
              							expr="
              							"
              						/>
              					</functionName>
              				</function>
              			</classRange>
              			<function
              				mainExpr="                                                                         # function body
              				"
              			>
              				<functionName>
              					<nameExpr
              						expr="                                                                # function parameters
              						"
              					/>
              					<nameExpr
              						expr="
              						"
              					/>
              				</functionName>
              				<className>
              					<nameExpr expr="
              					" />
              				</className>
              			</function>
              		</parser>
              	</functionList>
              </NotepadPlus>		
              

              This is a basic file to be searched by the FunctionList dbaseplus.xml:

              ** END HEADER -- do not remove this line
              //
              // Generated on 10/13/2021
              //
              parameter bModal
              local f
              f = new PlainObjectListForm()
              if (bModal)
                 f.mdi = false // ensure not MDI
                 f.readModal()
              else
                 f.open()
              endif
              
              class PlainObjectListForm of FORM
                 with (this)
                    onOpen = class::FORM_ONOPEN
                    doublebuffered = true
                    metric = 6	// Pixels
                    colorNormal = "Gray"
                    height = 529.0
                    left = 110.0
                    top = 29.0
                    width = 1092.0
                    sizeable = false
                    refreshAlways = false
                    pageno = 0
                 endwith
              
                 function form_onOpen()
              
                    form.testcontainer.vscrollbar1.currentValue = ;
                                             form.testcontainer.vscrollbar1.value
                    form.testContainer.aContainers = new array()
                    form.testContainer.ncontainers = 0
                    form.testContainer.nSpacing = 2
                    return
              
              endclass
              
              
              

              I hope the fact that I don’t have a function search in it yet won’t be the problem, as all I want to do is verify I have the regex, the .xml file correct, and the settings and files in the right place. If it’s my regex and .xml, I won’t feel bad, as it’s new…what can I say, but I think I did it right. ::shrug::

              Sorry if the .xml file is a bit long, but I copied it and emptied the C++ code figuring I was going to do this quick and left all the mixed parser stuff in it. ;-( Anyone see, off hand what I’m doing wrong or what’s wrong? I get no acknowledgement of even the file existence in the FunctionList head…that can’t be a good sign. :-(

              Lee

              PeterJonesP 1 Reply Last reply Reply Quote 0
              • PeterJonesP
                PeterJones @Lycan Thrope
                last edited by

                @lycan-thrope ,

                Without any functions defined, the classes don’t show up in the list, even if they do match your text, so you aren’t going to be able to see it work without a function (even if it’s the simplest possible function).

                If you want to individually test the regex, you can use the FIND or MARK dialogs with the same expression, which makes it easier to try variants.

                If I try your class expression in the FIND dialog, it says that it’s an invalid expression.

                When defining a new parser, I generally skip the openSymbole and closeSymbole expressions, and just deal with the mainExpr.

                Next, the way I do it, the mainExpr needs to match all of the text in the class – so the whole class … endclass – not just the introductory line, because it only finds class-functions (ie, methods) if they exist inside. If I’m reading your expression right, it’s only matching the single class line. (Maybe with the closeSymbole, you no longer need mainExpr to match as much… but I wouldn’t trust that without more experimentation.)

                And when debugging, I try to make the main expression as simple as possible, especially at first; if it needs more complexity later on, I add it… but for helping you get something tot; when debugging it, I start with the simplest form. Which, I think for yours, would be "match from class to endclass. So I’d be tempted to start with mainExpr="(?xms) ^ \h* class \h+.* ^ \h* endclass" – when I use that in a FIND in your document, it finds from class to endclass as I think I expect.

                Your class name expression looks reasonable, and does match the class name.

                For simple testing, I would then define the function mainExpr="(?x) \h* function \h+ (\w+)"

                But, as always, something goes wrong when I try things starting too complex. So I comment out the classRange, and just start with a simple function section:

                			<function
                				mainExpr="(?x) \h* function \h+ (\w+)"
                			>
                				<functionName>
                					<nameExpr expr="(?x) \h* function \h+ \K (\w+)"
                					/>
                				</functionName>
                			</function>
                

                If I do that, and add a block before your class

                function outsideAnything()
                   here
                   return
                

                (might not be valid, just using it for the parser), then reload when the dbaseplus.xml parser is properly linked in the overrideMap.xml, and the existing file is associated with the dBASEPlus UDL, I get:
                b1ca8da1-164d-4c99-bac9-baa4549ba3f2-image.png
                … so that means I am doing something right so far.

                But when I try to use that same <function> block inside the <classRange> block, it won’t find the class (and no longer shows the form_onOpen)…

                Unfortunately, while I’m usually able to get it eventually, it takes time for me. And I’ve spent as much as I can on this for now. maybe I’ll have spare time later today to work on it. But, if nothing else, this will give you a good starting point, because with the classRange commented out as here, it finds two functions, which is at least a starting point for debug:

                <?xml version="1.0" encoding="UTF-8" ?>
                <!-- ==========================================================================\
                |
                |   To learn how to make your own language parser, please check the following
                |   link:
                |       https://npp-user-manual.org/docs/function-list/
                |
                \=========================================================================== -->
                <NotepadPlus>
                	<functionList>
                		<!-- ========================================================= [ dBASEPlus ] -->
                		<parser
                			displayName="dBASEPlus"
                			id         ="dbaseplus"
                			commentExpr="(?s:/\*.*?\*/)|(?m-s://.*?$)"
                		>
                			<!--classRange
                				mainExpr="(?xms) ^ \h* class \h+.* ^ \h* endclass"
                			>
                				<className>
                					<nameExpr
                						expr="(?x) [\t\x20]*? ^class [\t\x20]* \K(\w+)"
                					/>
                					
                				</className>
                				<function
                					mainExpr="(?x) \h* function \h+ (\w+)"
                				>
                					<functionName>
                						<nameExpr expr="(?x) \h* function \h+ \K (\w+)"
                						/>
                					</functionName>
                				</function>
                			</classRange-->
                			<function
                				mainExpr="(?x) \h* function \h+ (\w+)"
                			>
                				<functionName>
                					<nameExpr expr="(?x) \h* function \h+ \K (\w+)"
                					/>
                				</functionName>
                			</function>
                		</parser>
                	</functionList>
                </NotepadPlus>	
                

                and

                ** END HEADER -- do not remove this line
                //
                // Generated on 10/13/2021
                //
                parameter bModal
                local f
                f = new PlainObjectListForm()
                if (bModal)
                   f.mdi = false // ensure not MDI
                   f.readModal()
                else
                   f.open()
                endif
                
                function outsideAnything()
                   here
                   return
                
                
                class PlainObjectListForm of FORM
                   with (this)
                      onOpen = class::FORM_ONOPEN
                      doublebuffered = true
                      metric = 6	// Pixels
                      colorNormal = "Gray"
                      height = 529.0
                      left = 110.0
                      top = 29.0
                      width = 1092.0
                      sizeable = false
                      refreshAlways = false
                      pageno = 0
                   endwith
                
                   function form_onOpen()
                
                      form.testcontainer.vscrollbar1.currentValue = ;
                                               form.testcontainer.vscrollbar1.value
                      form.testContainer.aContainers = new array()
                      form.testContainer.ncontainers = 0
                      form.testContainer.nSpacing = 2
                      return
                
                endclass
                
                

                Sorry I couldn’t get more working yet…

                Lycan ThropeL 1 Reply Last reply Reply Quote 1
                • Lycan ThropeL
                  Lycan Thrope @PeterJones
                  last edited by

                  @peterjones
                  Thank you very much, Peter. As I said, any help from another pair of eyeballs is appreciated, especially from someone who has done one before. At the least, you’ve confirmed some of what I wanted to know, that at least I might be getting the conceptualization of what to do to extract the names. I know that dBASE, as much as I like it, is somewhat of a loosely typed and ambiguously structured language, certainly nothing like C that I learned long ago, but it does still have stucture and trying to extrapolate from that to make it work in NPP is my problem to solve, I just wanted to know if I was doing something right or wandering in a far off land.

                  Thanks for the tips and I’ll work on what you’ve provided to see if I can’t get a better result. I know I read in the FAQ about the Function issue, which is why I was hoping it wouldn’t be the stopping issue for this, but apparently, it might be the classrange/class/function combination that I neeed to work right since that is the area you point out. Thanks for getting it to provide something, so I have a start.

                  Lee

                  Michael VincentM 1 Reply Last reply Reply Quote 0
                  • Michael VincentM
                    Michael Vincent @Lycan Thrope
                    last edited by

                    @lycan-thrope said in FunctionList Confused:

                    @peterjones
                    Thank you very much, Peter.

                    Note I think there is an error in @PeterJones functionName block in the classRange tags. I think it should be :

                    					<functionName>
                    						<funcNameExpr expr="(?x) \h* function \h+ \K (\w+)"
                    						/>
                    					</functionName>
                    

                    Notice funcNameExpr instead of just nameExpr.

                    Cheers.

                    PeterJonesP Lycan ThropeL 2 Replies Last reply Reply Quote 2
                    • PeterJonesP
                      PeterJones @Michael Vincent
                      last edited by PeterJones

                      @michael-vincent said in FunctionList Confused:

                      Note I think there is an error in @PeterJones functionName block in the classRange tags.

                      And when I fix that, I now see the function in the class.
                      15362293-e02a-4c35-8993-3458a3ed2cbb-image.png

                      So @Lycan-Thrope , that’s what you need to fix, and my simple mixed parser now works with your example code.

                      <?xml version="1.0" encoding="UTF-8" ?>
                      <!-- ==========================================================================\
                      |
                      |   To learn how to make your own language parser, please check the following
                      |   link:
                      |       https://npp-user-manual.org/docs/function-list/
                      |
                      \=========================================================================== -->
                      <NotepadPlus>
                      	<functionList>
                      		<!-- ========================================================= [ dBASEPlus ] -->
                      		<parser
                      			displayName="dBASEPlus"
                      			id         ="dbaseplus"
                      			commentExpr="(?s:/\*.*?\*/)|(?m-s://.*?$)"
                      		>
                      			<classRange
                      				mainExpr="(?xms) ^ \h* class \h+.* ^ \h* endclass"
                      			>
                      				<className>
                      					<nameExpr
                      						expr="(?x) [\t\x20]*? ^class [\t\x20]* \K(\w+)"
                      					/>
                      					
                      				</className>
                      				<function
                      					mainExpr="(?x) \h* function \h+ (\w+)"
                      				>
                      					<functionName>
                      						<funcNameExpr expr="(?x) \h* function \h+ \K (\w+)"
                      						/>
                      					</functionName>
                      				</function>
                      			</classRange>
                      			<function
                      				mainExpr="(?x) \h* function \h+ (\w+)"
                      			>
                      				<functionName>
                      					<nameExpr expr="(?x) \h* function \h+ \K (\w+)"
                      					/>
                      				</functionName>
                      			</function>
                      		</parser>
                      	</functionList>
                      </NotepadPlus>	
                      

                      (Since I used the (?x), you can go back and add newlines and comments to document the regex again; I just collapsed them because it’s easier to copy/paste into FIND dialog that way)

                      Lycan ThropeL 1 Reply Last reply Reply Quote 2
                      • Lycan ThropeL
                        Lycan Thrope @Michael Vincent
                        last edited by

                        @michael-vincent
                        Thank you Michael for that catch. I wouldn’t have seen that while following instructions. :-)

                        Lee

                        1 Reply Last reply Reply Quote 1
                        • Lycan ThropeL
                          Lycan Thrope @PeterJones
                          last edited by

                          @peterjones
                          Thank you so much also Peter. I can now feel somewhat elated at banging my head all day yesterday. :-)

                          Now to get back to work…had to take sometime for house chores since I neglected them yesterday beating my head on the keyboard. :-)

                          Lee

                          Lycan ThropeL 1 Reply Last reply Reply Quote 0
                          • Lycan ThropeL
                            Lycan Thrope @Lycan Thrope
                            last edited by

                            @lycan-thrope
                            Argh…sigh…I must be setup wrong or something. I just tried it with it in both the Appdata directory NPP FunctionList directory and the Program(x86) FunctionList directory and it’s not showing anything…so back to reading the docs, since I know yours works. :-(

                            PeterJonesP Lycan ThropeL 2 Replies Last reply Reply Quote 0
                            • PeterJonesP
                              PeterJones @Lycan Thrope
                              last edited by

                              @lycan-thrope ,

                              Can you show the relevant portion of overrideMap.xml, and compare that to the name in the User Defined Language list / definition?

                              in my working version (which is a portable, so no %AppData%):

                              			<!-- ==================== User Defined Languages ============================ -->
                              			<association id= "krl.xml"				userDefinedLangName="KRL"/>
                              			<association id= "sinumerik.xml"		userDefinedLangName="Sinumerik"/>
                              			<association id= "universe_basic.xml"	userDefinedLangName="UniVerse BASIC"/>
                              			<association id= "dbaseplus.xml"		userDefinedLangName="dBASEPlus"/>
                              			<!-- ======================================================================== -->
                              

                              and from the UDL definition:

                                  <UserLang name="dBASEPlus" ext="dbp" udlVersion="2.1">
                              

                              Notice that the userDefinedLangName in overrideMap and name in UDL definition match exactly.

                              And the active file must have selected the dBASEPlus UDL as its syntax highlighter – either through automatic extension (.dbp in my example), or by manually selecting Language > dBASEPlus, where the dBASEPlus will be down below the User Defined Language… submenu:

                              021bd061-2af6-4c48-b92a-5789bb888390-image.png

                              Also remember that for any change in functionList settings to take effect, you have to completely exit Notepad++ and restart it.

                              1 Reply Last reply Reply Quote 1
                              • Lycan ThropeL
                                Lycan Thrope @Lycan Thrope
                                last edited by

                                @lycan-thrope
                                Well, kind of at a loss to explain this. I’ve gone over the installations again, made sure the Appdata directories had the right files, even went into Admin mode to make sure it wasn’t rejected. The folowing screenshot shows the overrideMap.xml at the end where the UDL association is stored.
                                overridexmlAppData.PNG
                                Mind you, this was while I only had the UDL in the dialog box, not stored in the UDL folder in AppData area.

                                When I thought, hmm…maybe the file needs to be in the UDL Appdata folder I took an exported version I’ve made, renamed it appropriately “dBASEPlus.xml” and now I have this:

                                DoubleUDL.PNG

                                I wasn’t able to get it to work without the duplicate there or not. I’m going to delete the UDL file contents to see if that does the trick, either way, all the file extension needed were listed in that UDL and the pasted and copied version of Peter’s code still wasn’t working, so it must be me. :-(

                                File extensions in UDL file:
                                UDLFileAssoc.PNG

                                I guess I’ll need to retrace my steps.

                                Lee

                                Lycan ThropeL 1 Reply Last reply Reply Quote 0
                                • Lycan ThropeL
                                  Lycan Thrope @Lycan Thrope
                                  last edited by

                                  @lycan-thrope
                                  Smacking self vigorously about the face and head. :-(

                                  I’m glad I was re-reading out posts, and noticed that I had NOT exactly put the right name in the associations I had spelled it “dBasePlus” in the non-working file and after changing it to the proper “dBASEPlus”, it worked on reboot…so thank you very much Peter for saving me from myself. Maybe now I can get to some productive work of finishing this UDL for use for the community and of course, if it’s of use to this NPP community, it’s of course usable…just need to check how to add it to the UDL’s. Of course, I need to make sure the rest of the keywords are put in, don’t collide with each other and other delimiters etc…and make sure I can fully flesh out as much as I can without having to actually write a lexer for the language, because…let’s face, I don’t think I’m qualified for that extensive bit of work. :-)

                                  Lee

                                  Lycan ThropeL 1 Reply Last reply Reply Quote 2
                                  • Lycan ThropeL
                                    Lycan Thrope @Lycan Thrope
                                    last edited by Lycan Thrope

                                    @lycan-thrope
                                    Next hurdle, I need to addess and ask about. Does the parser only handle one class and multiple functions per file? Or does it require for a class to be listed that it has a function in it?

                                    I tried using my original code with some of Peter’s and found it messing up on the class not showing up, and the functions acting a little erratic. I’ve put it back to the way he wrote it now, with one or two changes that don’t seem to affect the end result, but I’m checking the different kinds of files we use, and one in particular, our .cc file which usually are Custom Component files include more than one class.

                                    In the one I was testing of my own creation, of the multiple classes I have in it, only one of them has a function, and it was the only one that showed up in FunctionList panel, which is what prompted this question coming up. If I just need to work further to get it to function listing classes, that is one thing, but if it’s not built to that, I wanted to check, as I don’t seem to have any multiple class code files available right now for any of the languages available in NPP…I will but just don’t have them right now…and it’s getting late time to stop beating the keyboard. :) Thanks in advance.

                                    Here’s two screenshots of the one class, multiple functions and one of the multiple classes but one function in the FunctionList panel.

                                    Lee

                                    classallfunctions.PNG

                                    OnlyOneClasswithfunctionbutnotallclasses.PNG

                                    Michael VincentM 1 Reply Last reply Reply Quote 0
                                    • Michael VincentM
                                      Michael Vincent @Lycan Thrope
                                      last edited by

                                      @lycan-thrope said in FunctionList Confused:

                                      Does the parser only handle one class and multiple functions per file? Or does it require for a class to be listed that it has a function in it?

                                      It can handle multiple classes, but for a class to be listed, it must have at least 1 function in it. It can also handle “main” functions - that is, functions not in a class.

                                      Cheers.

                                      1 Reply Last reply Reply Quote 2
                                      • guy038G
                                        guy038
                                        last edited by

                                        Hello, @lycan-thrope @peterjones, @michael-vincent and All,

                                        @lycan-thrope :

                                        Sorry to be late ! From your functionList file, provided in this specific post, I tried to re-build and simplify your regexes which allow to detect all the syntaxes of DBasePlus classes, as well as the class names !

                                        • I added, at beginning, the (?-i) in-line modifier for a search sensitive to the case

                                        • I mainly used the \h syntax, instead of [\t\x20], as it’s equivalent to [\t\x20\x85]

                                        • I replaced any \w* syntax by \w+, as we don’t search for empty words ! Don’t we ?

                                        • I suppressed some useless groups

                                        • I changed some complex multi-lines groups (•••••) in the non_capturing equivalent groups (?:•••••)

                                        • I kept the first optional parameter(s) part as group 1, which is re-used, with the same syntax, in the optional ‘of’ part


                                        Leading to the following class part of the dBasePlus parser :

                                        <NotepadPlus>
                                        	<functionList>
                                        		<!-- ========================================================= [ dBASEPlus ] -->
                                        		<parser
                                        			displayName="dBASEPlus"
                                        			id         ="dbaseplus"
                                        			commentExpr="/\*.*?\*/|(?-s://.*)"
                                        		>
                                        			<classRange
                                        				mainExpr="(?x-i)                        #  Free-spacing mode and inline comments + search sensitive to case
                                        
                                        						  ^\h*                          #  Optional leading whitespace chars
                                        						  class                         #  'class' keyword
                                        						  \h?                           #  Optional whitepace char
                                        						  \w+                           #  Class name
                                        
                                        														#  Following the class name there is the option of parameters, and if so the first entry inside the parens is required, whether there is other 
                                        														#  parameters or not, once the parens go up, the first is required. ie: class FrameCtrl(frameObj)
                                        
                                        						  (                             #  Beginning of the optional parameter(s) part  ( Group 1 )
                                        							\h? \(                      #    Opening parenthesis
                                        							\w+                         #    First and required parameter
                                        							( , \h? \w+)*               #    Following optional/additional parameters
                                        							\)                          #    Closing  parenthesis
                                        						  )?                            #  End of the optional parameter(s) part
                                        
                                        														#  For the rest of the class declaration, after the class name, all other options are part of one big optional set, that follows 'of'
                                        														#  and can be populated by one of several options.
                                        
                                        						  (?:                           #  Beginning of the main optional part, in a non-capturing group
                                        
                                        														#    The first and most prevalent is the Superclass name that the class is being subclassed from, and it's options of parameters and again, 
                                        														#    if it has parameters, at least the first one is required ie.: class class ToolButtonFx(oParent) of Toolbutton(oParent).
                                        
                                        							\h of \h                    #    Optional 'of' keyword, surrounded by 1 horizontal whitespace char
                                        							\w+                         #    Superclass name
                                        
                                        							(?1)?                       #    Optional parameter(s) part ( Subroutine call to Group 1 )
                                        
                                        														#    The next possible option is that it is a custom object and needs to be in this line so if the object or form is opened up in the dBASE IDE,
                                        														#    the designers in it won't mess up the object by streaming out missing parts or overriding properties or objects and functions.
                                        
                                        							( \h custom )?              #    Optional 'custom' keyword 
                                        
                                        														#    The next possible option is that the class is being subclassed from another object that is contained elsewhere and the compiler needs to know
                                        														#    this reference. There are two options for pointing to the file. The first is an Alias path in the IDE that can be accessed by the compiler
                                        														#    in the environment, or second, it is in the current directory and only the name is needed...or it has a path that can be listed here,
                                        														#    but this is bad practice, and an Alias is recommended if the file is in a place other than the current directory. If it is, the name can be
                                        														#    used in quotes as a string that gets passed to the compiler. Both follow the word 'From'. The Alias directory is a name that is enclosed
                                        														#    in two colons, one immediately before the Alias name and one immediately after, no spaces.
                                        
                                        							(?:                         #    Beginning of the optional part, in a non-capturing group
                                        							  \h from \h                #      Optional 'from' keyword, surrounded by 1 horizontal whitespace char
                                        
                                        							  (?:                       #    Beginning of a non-capturing group
                                        								  : \w+ : \w+ \. \w+    #        First pointing file case
                                        								|                       #      OR
                                        								  \x22 \w+ \. \w+ \x22  #        Second pointing file case
                                        							  )                         #    End of a non-capturing group
                                        
                                        							)?                          #    End of the optional part
                                        
                                        						  )?                            #  End of the main optional part
                                        
                                        						  $                             #  End of current line and end of the class declaration
                                        
                                        						 "
                                        
                                        				closeSymbole="endclass"
                                        			>
                                        				<className>
                                        					<nameExpr
                                        						expr="(?x-i)                    #  Free-spacing mode and inline comments and search sensible to case
                                        						      \h*                       #  Optional leading whitespace chars
                                        						      class                     #  'class' keyword
                                        						      \h?                       #  Optional whitepace char
                                        						      \K\w+                     #  Pure class name
                                        						     "
                                        					/>
                                        				</className>
                                        ...
                                        ...
                                        ...
                                        ...
                                        		</parser>
                                        	</functionList>
                                        </NotepadPlus>
                                        

                                        Best Regards,

                                        guy038

                                        PeterJonesP Lycan ThropeL 2 Replies Last reply Reply Quote 2
                                        • PeterJonesP
                                          PeterJones @guy038
                                          last edited by PeterJones

                                          @guy038 ,

                                          I tried replacing my simple class detection with yours, and it doesn’t show the classes – even when I keep my function definitions. When I put your expression into FIND, it’s back to matching only a single line, not the whole class – so that means, it can never find a function inside that class, and it thus won’t display anything in the function list (which is the second problem I pointed out here: “mainExpr needs to match all of the text in the class…”)

                                          If we use the function blocks from my “my simple mixed parser now works”, and incorporate your regex (unaltered), then I get

                                          3035d3ef-25b2-4ab5-9bf2-a0b5e601c7ea-image.png

                                          … which is not finding it as a class, and is instead finding it as a top-level function (which isn’t what it really is).

                                          This does confirm that defining closeSymbole isn’t enough to get it to extend the class to endclass even when not in the mainExpr.

                                          Thus, if I add

                                          						  (?s:.*?^\h*endclass)          #  must match all the way to 'endclass'
                                          

                                          after your $ line in the mainExpr, which will then find

                                          382051d7-c624-4a7e-b844-b5898ad9dab8-image.png

                                          @Lycan-Thrope , That last line I added defines a non-capturing group where .-matches-newline, and finds as few characters as possible between the end of the class-starting-line, and the first instance of the word endclass at the beginning of a line (with potential whitespace before) – thus making the mainExpr match the whole class, not just the first line of the class.

                                          <?xml version="1.0" encoding="UTF-8" ?>
                                          <!-- ==========================================================================\
                                          |
                                          |   To learn how to make your own language parser, please check the following
                                          |   link:
                                          |       https://npp-user-manual.org/docs/function-list/
                                          |
                                          \=========================================================================== -->
                                          <NotepadPlus>
                                          	<functionList>
                                          		<!-- ========================================================= [ dBASEPlus ] -->
                                          		<parser
                                          			displayName="dBASEPlus"
                                          			id         ="dbaseplus"
                                          			commentExpr="(?s:/\*.*?\*/)|(?m-s://.*?$)"
                                          		>
                                          			<classRange
                                          				mainExpr="(?x-i)                        #  Free-spacing mode and inline comments + search sensitive to case
                                          
                                          						  ^\h*                          #  Optional leading whitespace chars
                                          						  class                         #  'class' keyword
                                          						  \h?                           #  Optional whitepace char
                                          						  \w+                           #  Class name
                                          
                                          														#  Following the class name there is the option of parameters, and if so the first entry inside the parens is required, whether there is other 
                                          														#  parameters or not, once the parens go up, the first is required. ie: class FrameCtrl(frameObj)
                                          
                                          						  (                             #  Beginning of the optional parameter(s) part  ( Group 1 )
                                          							\h? \(                      #    Opening parenthesis
                                          							\w+                         #    First and required parameter
                                          							( , \h? \w+)*               #    Following optional/additional parameters
                                          							\)                          #    Closing  parenthesis
                                          						  )?                            #  End of the optional parameter(s) part
                                          
                                          														#  For the rest of the class declaration, after the class name, all other options are part of one big optional set, that follows 'of'
                                          														#  and can be populated by one of several options.
                                          
                                          						  (?:                           #  Beginning of the main optional part, in a non-capturing group
                                          
                                          														#    The first and most prevalent is the Superclass name that the class is being subclassed from, and it's options of parameters and again, 
                                          														#    if it has parameters, at least the first one is required ie.: class class ToolButtonFx(oParent) of Toolbutton(oParent).
                                          
                                          							\h of \h                    #    Optional 'of' keyword, surrounded by 1 horizontal whitespace char
                                          							\w+                         #    Superclass name
                                          
                                          							(?1)?                       #    Optional parameter(s) part ( Subroutine call to Group 1 )
                                          
                                          														#    The next possible option is that it is a custom object and needs to be in this line so if the object or form is opened up in the dBASE IDE,
                                          														#    the designers in it won't mess up the object by streaming out missing parts or overriding properties or objects and functions.
                                          
                                          							( \h custom )?              #    Optional 'custom' keyword 
                                          
                                          														#    The next possible option is that the class is being subclassed from another object that is contained elsewhere and the compiler needs to know
                                          														#    this reference. There are two options for pointing to the file. The first is an Alias path in the IDE that can be accessed by the compiler
                                          														#    in the environment, or second, it is in the current directory and only the name is needed...or it has a path that can be listed here,
                                          														#    but this is bad practice, and an Alias is recommended if the file is in a place other than the current directory. If it is, the name can be
                                          														#    used in quotes as a string that gets passed to the compiler. Both follow the word 'From'. The Alias directory is a name that is enclosed
                                          														#    in two colons, one immediately before the Alias name and one immediately after, no spaces.
                                          
                                          							(?:                         #    Beginning of the optional part, in a non-capturing group
                                          							  \h from \h                #      Optional 'from' keyword, surrounded by 1 horizontal whitespace char
                                          
                                          							  (?:                       #    Beginning of a non-capturing group
                                          								  : \w+ : \w+ \. \w+    #        First pointing file case
                                          								|                       #      OR
                                          								  \x22 \w+ \. \w+ \x22  #        Second pointing file case
                                          							  )                         #    End of a non-capturing group
                                          
                                          							)?                          #    End of the optional part
                                          
                                          						  )?                            #  End of the main optional part
                                          
                                          						  $                             #  End of current line and end of the class declaration
                                          
                                          						  (?s:.*?^\h*endclass)           #  must match all the way to 'endclass'
                                          
                                          
                                          						 "
                                          
                                          				 closeSymbole="endclass"
                                          						 
                                          			>
                                          				<className>
                                          					<nameExpr
                                          						expr="(?x-i)                    #  Free-spacing mode and inline comments and search sensible to case
                                          						      \h*                       #  Optional leading whitespace chars
                                          						      class                     #  'class' keyword
                                          						      \h?                       #  Optional whitepace char
                                          						      \K\w+                     #  Pure class name
                                          						     "
                                          					/>
                                          					
                                          				</className>
                                          				<function
                                          					mainExpr="(?x) \h* function \h+ (\w+)"
                                          				>
                                          					<functionName>
                                          						<funcNameExpr expr="(?x)			# multiline/comments
                                          								\h*							# allow leading spaces
                                          								function 					# must have word 'function' as first word
                                          								\h+ 						# must have at least one horizontal space after function
                                          								\K 							# don't keep 'function' in the name of the function in the panel
                                          								(\w+)						# the name of the function is the first whole word after 'function'
                                          							"
                                          						/>
                                          					</functionName>
                                          				</function>
                                          			</classRange>
                                          			<function
                                          				mainExpr="(?x) \h* function \h+ (\w+)"
                                          			>
                                          				<functionName>
                                          						<nameExpr     expr="(?x)			# multiline/comments
                                          								\h*							# allow leading spaces
                                          								function 					# must have word 'function' as first word
                                          								\h+ 						# must have at least one horizontal space after function
                                          								\K 							# don't keep 'function' in the name of the function in the panel
                                          								(\w+)						# the name of the function is the first whole word after 'function'
                                          							"
                                          						/>
                                          				</functionName>
                                          			</function>
                                          		</parser>
                                          	</functionList>
                                          </NotepadPlus>
                                          
                                          Lycan ThropeL 1 Reply Last reply Reply Quote 2
                                          • Lycan ThropeL
                                            Lycan Thrope @guy038
                                            last edited by

                                            @guy038
                                            Thanks guy038, for this lesson in regex construction. I was curious if I was being overly verbose in my regex for that line, but it does work correctly the way I wrote it in regex101.com, so I presumed it would work here. So far, although it works in the sandbox over there, and it does work in the find in NPP, I was still, as Peter points out next, not able to capture all the way to endclass, so this version still did what mine was doing. :-)…but I did pick up, because I understand my syntax, where I need to use capturing and non-capturing groups, as I was a bit lost as what meant what and where. So thanks. Here’s a screenshot, that shows the same thing I discovered last night…err early this morning before I called it quits that shows what I messed up, and Peter’s new version corrects. Mine, which you duplicate less verbosely, shows that the first class in the list gets listed with the function that actually belongs to a class further down in the code.
                                            guyversion.PNG

                                            So thanks for the education, though. :)

                                            Lee

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            The Community of users of the Notepad++ text editor.
                                            Powered by NodeBB | Contributors