FunctionList classrange question
-
ok, let me check if I have missed something.
Probably do a fresh install of NPP.Regards,
-
@MAPJe71
Removing the “commentExpr” attribute from the <parser> worked. Thx.I have started building the regex to add the other sections and have an additional question.
For instance, in the <classrange> known section names, if I want to check “before.<anyname>:” main section but should not check “before.choice:|before.checks:” sub section… can it be acheived?I tried with
| (?:before\.[^checks|choice|delete|display|field|form|group|input|layout|print|read|rewrite|write|zoom|display\.object|new\.object|program])(?:(?:\.)*\w+)+
This doesn’t seem to work. I also tried to create negative look ahead but failed.
Let me know if you have some suggestions.Regards,
-
@oirfeodent
Do you mean something like| before(?:\s*\.\s*(?!checks|choice|delete|display|field|form|group|input|layout|print|read|rewrite|write|zoom|display\.object|new\.object|program)\w+)+
-
@MAPJe71
The above is close to expected output.
In the sample file below, the “before.program:” main section gets listed as the sub section of “choice.test.123:” main section.
Sample file:choice.test.123: before.choice: funct1(10) on.choice: funct1(10) before.program: set.synchronized.dialog("fxinh0123s000") functions: function func1(long var1) { | Do Something 1. }
The expected output is
+--- filename.bc +--- choice.test.123: | +--- before.choice | \--- on.choice | \--- functions: \--- func1
But the “before.program:” also gets listed under “choice.test.123:” for the below <classrange> tag.
<classRange mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks (?'SECTION' ^\h* # optional leading whitespace at start-of-line (?: # known section names after\.(?:(?!choice:|delete:|display:|field:|form\.read:|form:|group:|input:|layout:|program:|read:|receive\.data:|rewrite:|skip\.delete:|skip\.rewrite:|skip\.write:|update\.db\.commit:|write:|zoom:)(?:\.)*\w+)+ | before\.(?:(?!checks:|choice:|delete:|display:|field:|form:|group:|input:|layout:|print:|read:|rewrite:|write:|zoom:|display\.object:|new\.object:|program:)(?:\.)*\w+)+ | (?:choice\.|field\.|zoom\.from\.)(?:(?:\.)*\w+)+ | (?:detail\.|footer\.|form\.|group\.|header\.)(?:\d+)+ | functions | main\.table\.io ) : # end-of-section-header indicator ) (?s:.*?) # whatever, up till (?=(?&SECTION)|\Z) # ...next section or end-of-text " > <className> <nameExpr expr="^\h*\K\w+(?:\.\w+)*:" /> </className> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks ^\h* # optional leading whitespace at start-of-line (?: \K # discard text matched so far \b(?!(?: # discard known section names after\.(?:(?!choice:|delete:|display:|field:|form\.read:|form:|group:|input:|layout:|program:|read:|receive\.data:|rewrite:|skip\.delete:|skip\.rewrite:|skip\.write:|update\.db\.commit:|write:|zoom:)(?:\.)*\w+)+ | before\.(?:(?!checks:|choice:|delete:|display:|field:|form:|group:|input:|layout:|print:|read:|rewrite:|write:|zoom:|display\.object:|new\.object:|program)(?:\.)*\w+)+ | (?:choice\.|field\.|zoom\.from\.)(?:(?:\.)*\w+)+ | (?:detail\.|footer\.|form\.|group\.|header\.)(?:\d+)+ | functions | main\.table\.io )\b) \w+(?:\s*\.\s*\w+)+ # sub-section name : # end-of-sub-section-header indicator | function\s+ \K # discard text matched so far (?:extern\s+)? (?:(?:boolean|double|long|string|void|domain\s+[A-Za-z_]\w*)\s+)? \w+(?:\s*\.\s*\w+)* # function name \s*\( # end-of-function-header indicator ) " > <functionName> <funcNameExpr expr="(?:extern\s+)?(?:(?:boolean|double|long|string|void|domain\s+[A-Za-z_]\w*)\s+)?\w+(?:\s*\.\s*\w+)*" /> </functionName> </function> </classRange>
Adding/removing the ‘:’ to the negative look ahead provides the same results.
Any possibilities?Regards,
-
@oirfeodent Could you provide a complete list of:
- valid section names i.e. invalid sub-sections names;
- valid sub-section names i.e. invalid section names.
-
Main Sections Sub Sections after.<charsDigitsPeriods>.<digitsOnly>: after.choice: after.form.read: after.delete: after.program: after.display: after.receive.data: after.field: after.report.<digitsOnly>: after.form: after.update.db.commit: after.group: before.<charsDigitsPeriods>.<digitsOnly>: after.input: before.display.object: after.layout: before.new.object: after.read: before.program: after.rewrite: before.report.<digitsOnly>: after.skip.delete: choice.<charsDigitsPeriods>: after.skip.rewrite: declaration: after.skip.write: detail.<digitsOnly>: after.write: field.<charsDigitsPeriods>: after.zoom: field.all: before.checks: field.other: before.choice: footer.<digitsOnly>: before.delete: form.<digitsOnly>: before.display: form.all: before.field: form.other: before.form: functions: before.group: group.<digitsOnly>: before.input: header.<digitsOnly>: before.layout: main.table.io: before.print: on.display.total.line: before.read: on.error: before.rewrite: zoom.from.<charsDigitsPeriods>: before.write: zoom.from.all: before.zoom: zoom.from.other: check.input: domain.error: init.field: init.form: init.group: on.choice: on.entry: on.exit: on.input: read.view: ref.display: ref.input: selection.filter: when.field.changes: -
List of Main Sections:
Main Sections Has SubSections? after.<charsDigitsPeriods>.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections after.form.read: No Subsection after.program: No Subsection after.receive.data: No Subsection after.report.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections after.update.db.commit: No Subsection before.<charsDigitsPeriods>.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections before.display.object: No Subsection before.new.object: No Subsection before.program: No Subsection before.report.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections choice.<charsDigitsPeriods>: Atlease one Sub-Section, can have multiple SubSections declaration: No Subsection detail.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections field.<charsDigitsPeriods>: Atlease one Sub-Section, can have multiple SubSections field.all: Atlease one Sub-Section, can have multiple SubSections field.other: Atlease one Sub-Section, can have multiple SubSections footer.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections form.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections form.all: Atlease one Sub-Section, can have multiple SubSections form.other: Atlease one Sub-Section, can have multiple SubSections functions: No Subsection, but functions are present group.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections header.<digitsOnly>: Atlease one Sub-Section, can have multiple SubSections main.table.io: Atlease one Sub-Section, can have multiple SubSections on.display.total.line: No Subsection on.error: No Subsection zoom.from.<charsDigitsPeriods>: Atlease one Sub-Section, can have multiple SubSections zoom.from.all: Atlease one Sub-Section, can have multiple SubSections zoom.from.other: Atlease one Sub-Section, can have multiple SubSections List of Sub Sections
Sub Sections after.choice: after.delete: after.display: after.field: after.form: after.group: after.input: after.layout: after.read: after.rewrite: after.skip.delete: after.skip.rewrite: after.skip.write: after.write: after.zoom: before.checks: before.choice: before.delete: before.display: before.field: before.form: before.group: before.input: before.layout: before.print: before.read: before.rewrite: before.write: before.zoom: check.input: domain.error: init.field: init.form: init.group: on.choice: on.entry: on.exit: on.input: read.view: ref.display: ref.input: selection.filter: when.field.changes: -
All the sub-sections are definite.
The main sections inside the <> can be anything based on the description; but has to exist.
So, “after.<charsDigitsPeriods>.<digitsOnly>:” should end with a “.<digit>:” to be a valid MainSection.
None of the main sections are mandatory (even functions: main section can be skipped).
None of the sub sections are mandatory (But atleast one sub-section would exist (Though not mandatory))Apart from this, there are two kinds of script.
- Regular Script… which will have atleast one of the above sections and optionally the “functions:” sections along with functions.
- dll script… which doesn’t have any of the sections, but only functions.
Sample dll script:
|This is a dll script, which does not have any sections. function extern long func1(long var1) { |do something } function void funct2(long var2) { |do something }
Sample regular script:
choice.test.123: before.choice: funct1(10) on.choice: funct1(10) before.program: func1(10) functions: function func1(long var1) { | Do Something 1. }
Regards,
-
@MAPJe71
The response is multiple replies, as I cant edit the original post. Thx.Regards,
-
@oirfeodent Please try the following parser:
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | Based on: | https://notepad-plus-plus.org/community/topic/14494/functionlist-classrange-question \--> <parser displayName="BaanC Sections v3" id ="baanc_section" > <classRange mainExpr ="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks (?(DEFINE) # definition of sub-routines (?'SECTION' ^\h* # optional leading whitespace at start-of-line (?: # known section names (?:after|before)\.(?:report\.\d+|\w+(?:\.\w+)*\.\d+) | (?:field|zoom\.from)\.(?:all|other|\w+(?:\.\w+)*) | (?:footer|group|header)\.\d+ | choice\.\w+(?:\.\w+)* | detail\.\d+ | form\.(?:all|other|\d+) | functions | main\.table\.io ) \h*: # end-of-section-header indicator ) (?'SECTION_EMPTY' ^\h* # optional leading whitespace at start-of-line (?: # known `empty` section names after\.(?:form\.read|program|receive\.data|update\.db\.commit) | before\.(?:(?:display|new)\.object|program) | declaration | on\.(?:display\.total\.line|error) ) \h*: # end-of-section-header indicator ) ) (?&SECTION) # section header (?s:.*?) # whatever, (?= # ...up till (?&SECTION) # ...next section header, | (?&SECTION_EMPTY) # ...next `empty` section header | \Z # ...or end-of-text ) " > <className> <nameExpr expr="^\h*\K\w+(?:\.\w+)*\h*:" /> </className> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks ^\h* # optional leading whitespace at start-of-line (?: \K # discard text matched so far (?: # known sub-section names after\.(?:choice|d(?:elete|isplay)|f(?:ield|orm)|group|input|layout|re(?:ad|write)|skip\.(?:delete|(?:re)?write)|write|zoom) | before\.(?:ch(?:ecks|oice)|d(?:elete|isplay)|f(?:ield|orm)|group|input|layout|print|re(?:ad|write)|write|zoom) | check\.input | domain\.error | init\.(?:f(?:ield|orm)|group) | on\.(?:choice|e(?:ntry|xit)|input) | read\.view | ref\.(?:display|input) | selection\.filter | when\.field\.changes ) \h*: # end-of-sub-section-header indicator | function\h+ (?:extern\h+)? (?:(?:boolean|double|long|string|void|domain\h+[A-Za-z_]\w*)\h+)? \K # discard text matched so far \w+(?:\.\w+)* # function name \s*\( # end-of-function-header indicator ) " > <functionName> <funcNameExpr expr="\w+(?:\.\w+)*(?:\h*:)?" /> </functionName> </function> </classRange> <!-- | Note: | Having the following `function`-node active will result in all branches | except the last branch to show their leaves twice in the tree. \--> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks ^\h* # optional leading whitespace at start-of-line (?: \K # discard text matched so far (?: # known `empty` section names after\.(?:form\.read|program|receive\.data|update\.db\.commit) | before\.(?:display\.object|new\.object|program) | declaration | on\.(?:display\.total\.line|error) ) \h*: # end-of-section-header indicator | (?i:function)\h+ (?:extern\h+)? (?:(?:boolean|double|long|string|void|domain\h+[A-Za-z_]\w*)\h+)? \K # discard text matched so far \w+(?:\.\w+)* \s*\( ) " > <functionName> <nameExpr expr="\w+(?:\.\w+)*(?:\h*:)?" /> </functionName> </function> </parser>
-
@MAPJe71 said:
(?i:function)\h+ (?:extern\h+)? (?:(?:boolean|double|long|string|void|domain\h+[A-Za-z_]\w*)\h+)? \K # discard text matched so far \w+(?:\.\w+)* \s*\(
I have changed the \h+ to \s+ so that functions spanning multi-lines are shown properly. Do you see any issues with that?
Another point is about embedded comments… for below sample
function extern |Test long test() { }
if I remove the “|Test” it is shown in the Function List panel… but, with the comment in place it doesn’t show this function.
So, is there a possibility to check for the presence of comments and ignore the same?@MAPJe71 Thx so far for your time and effort.
-
@oirfeodent comments “embedded” in the function/method header are not supported (see also parse steps in earlier post).
-
@MAPJe71
I thought with the <parser> “commentExpr” -attribute it is not possible to have embedded comments.
I was playing around with RegexBuddy with the simplest version of the function parser and used the following regex to have the function name highlighted with embedded comments.function\s+(\|\w*)*\s+\K\w+(?:\.\w+)*\s*\(
However it failed with the regular function without embedded comment.
function |TEST test() { |highlighted function name } function test() { | No highlight. (I guess regex is not correct to handle both) }
So, I thought there could be a better way for doing this which I am not aware.
Hence the question, as the “commentExpr” attribute is not defined.If no other way, then also fine. Thx.
Regards,
-
@oirfeodent new attempt:
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | Based on: | https://notepad-plus-plus.org/community/topic/14494/functionlist-classrange-question | | Note(s): | 1. Boost::Regex 1.58-1.59 do not correctly handle quantifiers on subroutine calls | therefore the additional non-capturing group i.e. "(?:(?&COMMENT))?" instead | of simply "(?&COMMENT)?" \--> <parser displayName="BaanC Sections v4.2" id ="baanc_section" > <classRange mainExpr ="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks (?(DEFINE) # definition of sub-routines (?'SECTION' ^\h* # optional leading whitespace at start-of-line (?: # known section names (?:after|before)\.(?:report\.\d+|\w+(?:\.\w+)*\.\d+) | (?:field|zoom\.from)\.(?:all|other|\w+(?:\.\w+)*) | (?:footer|group|header)\.\d+ | choice\.\w+(?:\.\w+)* | detail\.\d+ | form\.(?:all|other|\d+) | functions | main\.table\.io ) \h*: # end-of-section-header indicator ) (?'SECTION_EMPTY' ^\h* # optional leading whitespace at start-of-line (?: # known `empty` section names after\.(?:form\.read|program|receive\.data|update\.db\.commit) | before\.(?:(?:display|new)\.object|program) | declaration | on\.(?:display\.total\.line|error) ) \h*: # end-of-section-header indicator ) ) (?&SECTION) # section header (?s:.*?) # whatever, (?= # ...up till \s* (?: (?&SECTION) # ...next section header, | (?&SECTION_EMPTY) # ...next `empty` section header | \Z # ...or end-of-text ) ) " > <className> <nameExpr expr="^\h*\K\w+(?:\.\w+)*\h*:" /> </className> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks (?(DEFINE) # definition of sub-routines (?'COMMENT' \s*\x7C[^\r\n]* # trailing comment (?: # optional subsequent comment (?:\r?\n|\n?\r) # - mandatory line-break \s*\x7C[^\r\n]* # - `trailing` comment )* ) ) ^\h* # optional leading whitespace at start-of-line (?: \K # discard text matched so far (?: # known sub-section names after\.(?:choice|d(?:elete|isplay)|f(?:ield|orm)|group|input|layout|re(?:ad|write)|skip\.(?:delete|(?:re)?write)|write|zoom) | before\.(?:ch(?:ecks|oice)|d(?:elete|isplay)|f(?:ield|orm)|group|input|layout|print|re(?:ad|write)|write|zoom) | check\.input | domain\.error | init\.(?:f(?:ield|orm)|group) | on\.(?:choice|e(?:ntry|xit)|input) | read\.view | ref\.(?:display|input) | selection\.filter | when\.field\.changes ) \h*: # end-of-sub-section-header indicator | function # keyword, start-of-function-header indicator (?:(?&COMMENT))? # optional `embedded` comment (?: # optional storage-class specifier \s+extern (?:(?&COMMENT))? # ...with optional `embedded` comment )? (?: # optional function type specifier \s+(?:boolean|double|long|string|void|domain\h+[A-Za-z_]\w*) (?:(?&COMMENT))? # ...with optional `embedded` comment )? \s+ \K # discard text matched so far \w+(?:\.\w+)* # function identifier (?:(?&COMMENT)(?:\r?\n|\n?\r))? # optional `embedded` comment \s*\( # start-of-parameter-list indicator ) " > <functionName> <funcNameExpr expr="\w+(?:\.\w+)*(?:\h*:)?" /> </functionName> </function> </classRange> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?im) # case-insensitive, ^ and $ match at line breaks (?(DEFINE) # definition of sub-routines (?'COMMENT' \s*\x7C[^\r\n]* # trailing comment (?: # optional subsequent comment (?:\r?\n|\n?\r) # - mandatory line-break \s*\x7C[^\r\n]* # - `trailing` comment )* ) ) ^\h* # optional leading whitespace at start-of-line (?: \K # discard text matched so far (?: # known `empty` section names after\.(?:form\.read|program|receive\.data|update\.db\.commit) | before\.(?:display\.object|new\.object|program) | declaration | on\.(?:display\.total\.line|error) ) \h*: # end-of-section-header indicator | function # keyword, start-of-function-header indicator (?:(?&COMMENT))? # optional `embedded` comment (?: # optional storage-class specifier \s+extern (?:(?&COMMENT))? # ...with optional `embedded` comment )? (?: # optional function type specifier \s+(?:boolean|double|long|string|void|domain\h+[A-Za-z_]\w*) (?:(?&COMMENT))? # ...with optional `embedded` comment )? \s+ \K # discard text matched so far \w+(?:\.\w+)* # function identifier (?:(?&COMMENT)(?:\r?\n|\n?\r))? # optional `embedded` comment \s*\( # start-of-parameter-list indicator ) " > <functionName> <nameExpr expr="\w+(?:\.\w+)*(?:\h*:)?" /> </functionName> </function> </parser>
-
@MAPJe71
Thx. PR has been created based on above https://github.com/notepad-plus-plus/notepad-plus-plus/pull/3842
Only change is that domain keyword also checks for . (period) apart from \w class and also allow embedded comments. Can you have a look and approve the changes if you are ok.If not, let me know.
Regards, -
@oirfeodent see PR #3842 for my review.