Regex Custom UDL Parser
-
Hey everyone, I’m setting Npp up for GECKScript (scripting language for Fallout New Vegas) I have made my own syntax highlight and autocomplete, now I’m setting up the Functionlist. The class block is working great, every line is in the interface between my class blocks… but no names yet.
I’m done writing my regex, it works without problems on a sample document but somehow Npp doesn’t want to accept it. Anyone care to take a look and have some advice?
Need 1 rep poing for posting links, guess I"ll post a sample instead of linking an interactive site. :)
commentExpr="(;.*?$)"
mainExpr="^[\t ]++|(?:Begin)"
<nameExpr expr="^[\t 0-9A-Za-z]+[]!"#$%&'()*+,.\/:;<=>?@[\\_`{|}~^-]+([A-Za-z]+)"
; Vault Level Variables: Short bPlayerSafe Short bPlayerBlocks Short bVaultOpen Short bTreasureFound Short bSecurityAltInfo Short bChristineHelp Short bDeanHelp Int iTurretsDown Int iSecurityState Int iElevatorState Int iMaintenanceState ; Elijah Variables: Short bElijahContacted Short bElijahTaunted Short bElijahInVault Short bElijahPaths Short bElijahTurnsSecurityOn Short bElijahEntersVault Short bElijahArrivesVault Short bElijahOpensVault Short bElijahFights Short bElijahDead Short bElijahTrapped Short bElijahTrapsPlayer Short bElijahTeamsWithPlayer short bPlayerTrapped Int iElijahState Int iChristineStrikes Float fAngle ; Operational Variables: Int iCount Float fTimer ; >>>>---------------- Begin Code; ; >>>>---------------- Begin GameMode If (bTreasureFound == 1) If (bVaultOpen == 1) ; If Players have opened the Vault previously. If (bElijahContacted == 1) ; If Players have contacted Elijah - start sequence. If (iElijahState == 0) ; If First Stage of Endgame. If (bElijahInVault == 0) ; If Elijah not yet teleported to Vault. NVDLC01ElijahREF.Disable; NVDLC01ElijahREF.MoveTo NVDLC01VaultStartMarkerREF; SetStage NVDLC01MQ03 48; Set bElijahInVault to 1; Return; Else NVDLC01ElijahREF.Enable; ; Enable Elijah once he's been moved to the Vault. Set iElijahState to 1; ; Ready Elijah for the next stage of events/AI behaviors. Set bElijahPaths to 1; ; Set variable to be checked by Elijah's AI package. Return; Endif Elseif (iElijahState == 1) If (iCount == 0) NVDLC01ElijahREF.AddScriptPackage NVDLC01VaultElijaIntroPathTravel;
Thanks!
-
Guess I can add the link now, I received a couple reputation points. :)
This is where I’m at now… “class” block regex added and all lines between the “class” block show up, but can’t get the function names to show up. I’m getting desperate, can anyone shed some light on why its not working?
Thanks!
This is a link to one of the regex’ I’m trying, has good visual representation and can play around with the regex and save a new version on top left of the website if you want. https://regex101.com/r/spMBF6/4
This is a link straight to the debugger, it shows you visually what its doing, and finishes the document without an issue.
https://regex101.com/r/spMBF6/4/debugger -
Regex101 uses a different flavor of regular expression than Notepad++ (which uses the Boost regex library) – so just because something works at that website doesn’t mean it will work in either Notepad++'s search or its Function List parsing.
If you want to test a regex for Notepad++'s Function List parsing, the best thing to do is test it inside Notepad++'s search dialog.
I am hoping that @MAPJe71 will be able to take a look at your definitions and see if he has any insight, because he’s our resident Function List expert.
I’m getting desperate
That is unfortunate for you, as this is a Community of fellow Notepad++ users, none of whom are paid to give you technical support on demand. If someone is able to give you insight, they will … when it is convenient for them.
[link to regex101]
For those who don’t want to follow that link, the current state of the regex appears to be
^(?>[\t\v]+(?<GECKScript>[]!#$%&()*+.\/0-9:;<=>A-Z[a-z{|}^-]+))+
-
This one doesn’t use a class, and I am quite certain it doesn’t meet all your needs, but it might give you a working starting point:
<?xml version="1.0" encoding="UTF-8" ?> <NotepadPlus> <functionList> <parser displayName="KT-UDL" id ="ktudl_fn" commentExpr="(;.*?$)" > <function mainExpr="(?-i:^\h*Begin \w+)|(?i:^\h*(If|Elseif).*?$)" displayMode="$functionName"> <functionName> <nameExpr expr="(?i:^\h*Begin \w+)|(?i:^\h*(If|Elseif).*?$)"/> </functionName> </function> </parser> </functionList> </NotepadPlus>
I basically had it find any
Begin NameHere
orIf blah
orElseif blah
and call those the “functions”Looking at your original
mainExpr
: it’s probably too short to accomplish anything. For function names, themainExpr
must match the entirety of the name (and possibly more). For class ranges, themainExpr
should match all the text from the beginning of the class to the end of the class. My guess is that’s where things were going wrong for you… but since you just gave us pieces of the XML rather than the full definition, I cannot be sure. -
@PeterJones
Thanks very much for posting Peter, I had resorted to using it in a hacky way. I just used the regex below in the main expression field and it worked. The regex’ I showed were created with RegexBuddy, Boost Regex version 1.76 and then checked online too.^[\t\v]+[^\n\r]+
But your solution is more inline with how the feature is supposed to be used. My result looks like this.
Since I wasn’t very hopeful to get some help on this I was already looking how I coould improve my hacky way, but thank you sir, you have given me a much better starting point!
-
I had a few more minutes, and was playing around trying to get the classRange to work as well.
- The “Begin
XXX
… End” will define a class namedXXX
- Things starting with “If” or “ElseIf” will be called “functions” inside that class, but the “if” or “elseif” will not be displayed in the functionList panel
Begin One If x a Elseif y b Else c Endif End Begin huh If something Elseif what Else Endif End
<?xml version="1.0" encoding="UTF-8" ?> <NotepadPlus> <functionList> <parser displayName="KT-UDL" id ="ktudl_fn" commentExpr="(;.*?$)" > <function mainExpr="(?i:^\h*(If|Elseif).*?$)" displayMode="$functionName"> <functionName> <nameExpr expr="(?i:^\h*(If|Elseif).*?$)"/> </functionName> </function> <classRange mainExpr ="(?s-i)^\h*Begin\b.*?^\h*End\b" > <className> <nameExpr expr="^\h*Begin\h*\K.*?$" /> </className> <function mainExpr="(?i:^\h*(If|Elseif).*?$)" > <functionName> <funcNameExpr expr="(?i:^\h*(If|Elseif)\h*\K.*?$)" /> </functionName> </function> </classRange> </parser> </functionList> </NotepadPlus>
… Essentially, when I’m trying to come up with a functionList definition, I pare it down to the absolute simplest I can, try to get just the function names to work, then try to wrap a classRange around that function name. Once I’ve got a minimum working functionList that’s got the main idea of the given language, then I start adding back in restrictions and edge cases one at a time, making sure I have the ability to go back if it stops matching correctly.
- The “Begin
-
You’re a star! That looks awesome!
If you’re ever in Belgium I owe you some beers! :)