Avatar billede mxs Nybegynder
19. januar 2008 - 16:56 Der er 35 kommentarer og
1 løsning

Elisp og regex

Hej

Jeg er ved at lave en form for bibliotek til STL i elisp til emacs. Her bruger jeg regexp til at finde tekst af typen:
object.member();
object.member;
object->member();
object->member;

Jeg har makket en regexp sammen:
\s*([a-z]+)(->|\.)([a-z]+)((\([a-z,\"]+\);)|(\(\);)|;)\s*
Jeg ved udemærket godt at den måske kunne være bedre. Jeg er nybegynder indenfor regexp, men jeg har testen denne regexp via http://www.fileformat.info/tool/regex.htm og den fortæller mig at den virker, så det er jeg tilfreds med.
Nu vil jeg gerne have den oversat så jeg kan bruge den i emacs, men jeg bliver forvirret af syntaksen. Jeg har fundet følgende side http://www.gnu.org/software/emacs/elisp-manual/html_mono/elisp.html#Syntax-of-Regexps som jeg bruger til at oversætte. Jeg er nået frem til noget, som ikke virker, og jeg er overbevist om at det er mig der ikke kan finde ud af at lave en elisp regexp. Her er hvad jeg er kommet op med:
[[:blank:]]*([[:alpha:]]+)\(->\|\s.\)([[:alpha:]]+)(\(\s([[:alpha:],\"]+\s);\)\|\(\s(\s);\)\|;\)[[:blank:]]*
Det jeg roder mest rundt i er escape karakteren. \ og dens virkemåde i nogen sammenhæng.
En eller anden der kan hjælpe mig? Er nemlig meget tæt på at være i mål med denne extension til emacs.

Mvh. Martin Slot
Avatar billede nielle Nybegynder
19. januar 2008 - 17:49 #1
Har du prøvet simpelthen at bruge den første version som den er?
Avatar billede mxs Nybegynder
19. januar 2008 - 17:54 #2
Ja. Og der fejler den. Det er den escape karakter jeg ikke fatter.
Avatar billede nielle Nybegynder
19. januar 2008 - 17:57 #3
Siger den ikke noget mere specifikt om fejlen?
Avatar billede mxs Nybegynder
19. januar 2008 - 17:59 #4
Den siger "lookup: Search failed: "[[:blank:]]*([[:alpha:]]+)( ->| .)([[:alpha:]]+)(( ([[:alpha:],\"]+ );)|( ( );)|;)[[:blank:]]*""
Avatar billede nielle Nybegynder
19. januar 2008 - 18:03 #5
Det er jo ikke det originale mønster, og det siger da heller ikke noget om escape-karakteren?
Avatar billede mxs Nybegynder
19. januar 2008 - 18:15 #6
Samme med det originale mønster
"lookup: Search failed: " *([a-z]+)(->|.)([a-z]+)((([a-z,\"]+);)|(();)|;) *""
Avatar billede mxs Nybegynder
19. januar 2008 - 18:17 #7
Jeg kan bare ikke tolke, udfra http://www.gnu.org/software/emacs/elisp-manual/html_mono/elisp.html#Syntax-of-Regexps, hvordan jeg skal oversætte det originale mønster.
Elisp er fra før Perl standardiserede regular expressions, så derfor den ikke godtager mit originale mønster.
Avatar billede nielle Nybegynder
19. januar 2008 - 18:29 #8
Helt så oldnordisk ser syntaksen nu ikke ud til at være.

Jeg tror at det største problem er at '(', ')', '|' og '\' hver i sær skal escapes fordi at det foregår i en LISP kontekst. Dit originale møsnter burde blive noget i stil med:

[:blank:]*\([a-z]+\)\(->\|\\.\)\([a-z]+\)\(\(\\\([a-z,\\"]+\\\);\)\|\(\\\(\\\);\)\|;\)[:blank:]*
Avatar billede mxs Nybegynder
19. januar 2008 - 18:40 #9
Det er da stadig irriterende at en editor som emacs ikke understøtter en standard som Perl syntaksen.
Avatar billede nielle Nybegynder
19. januar 2008 - 18:44 #10
Så vidt jeg kan se er det kun \s som den ikke forstår.

Det med at visse tegn skal escapes når de indgår i en streng er et problem i mange andre sprog. Lige her er det vist mere LISP du skal være irriteret på. :^)
Avatar billede mxs Nybegynder
19. januar 2008 - 18:45 #11
emacs er lisp :) Er irriteret på det hele. Nu kan jeg godt kalde regexp'en med en interaktiv funktion, men når jeg prøver at lave min egen funktion med regexp'en, så fejler den.
Avatar billede nielle Nybegynder
19. januar 2008 - 18:51 #12
Emacs er ikke LISP - den er måske lavet i LISP, men LISP er nu et helt programmeringssprog i egen ret og har specielt anvendelse inden for AI (Ateficial Intelligence).

Som programmerinssprog har LISP nogle krav til sin syntaks. Og da f.eks. '(' og ')' indgår temmeligt cebtralt i syntaksen skal de escapes i tekststrenge.
Avatar billede mxs Nybegynder
19. januar 2008 - 18:56 #13
Ja okay :) Bare en talemåde jeg har fået påført mig. Ved godt at det ikke er sandt. Synes bare at det er grimt med alle de \\\. Altså hvis jeg bare vil vise en (, så skal den escapes med tre \?
Avatar billede nielle Nybegynder
19. januar 2008 - 19:01 #14
Ja.

Hvis '(' skal matche en parantes - i modsætning til f.eks. at indgå i en gruppe - så kræver regexp at den skal escapes:

\(

LIST kræver selv at både '\' og '(' skal escapes:

\\\(

Det kunne dog blive værre. F.eks. hvsi det var et '\' der skal matches. Den bliver til:

\\\\

Det er rigtigt "dejligt" når både regexp og programerinsgsprog begge to kræver escaping - det kan blive til nogle temmeligt ulæselige udtryk. Det ville dog være forkert at sige at det var noget unikt for LISP...
Avatar billede nielle Nybegynder
19. januar 2008 - 19:04 #15
Har du fået afprøvet 19/01-2008 18:29:10 endnu?
Avatar billede mxs Nybegynder
19. januar 2008 - 19:11 #16
Ja.
Når jeg prøver at evaluere denne funktion:
(defun lookup ()
  "Funktionen finder strenge af typerne, object.member();, object->member() osv."
  (interactive)
  (re-search-backward "[:blank:]*\([a-z]+\)\(->\|\\.\)\([a-z]+\)\(\(\\\([a-z,\\"]+\\\);\)\|\(\\\(\\\);\)\|;\)[:blank:]*")
)

Får jeg følgende fejl:
Debugger entered--Lisp error: (invalid-read-syntax "]" in al list")


Men kalder jeg re-search-backward interaktivt med M-x, så kan den godt evaluere regexp'en.
Det ser ud til at den godt kan klare object->member; men alt andet fejler den ved. Altså,
object->member("string",arg,);
object.member("string",arg,);
object.member();
object.member;
object->member()
Avatar billede mxs Nybegynder
19. januar 2008 - 19:14 #17
Ser ud til at alle \ skal escapes igen.
For at evaluere funktionen skal de escapes igen, så den kommer til at se sådan her ud,
"[:blank:]*\\([a-z]+\\)\\(->\\|\\\\.\\)\\([a-z]+\\)\\(\\(\\\\\\([a-z,\\\\\"]+\\\\\\);\\)\\|\\(\\\\\\(\\\\\\);\\)\\|;\\)[:blank:]*
Avatar billede mxs Nybegynder
19. januar 2008 - 19:16 #18
Den kan dog stadig ikke finde tekst af følgende form:
object->member("string",arg,);
object.member("string",arg,);
object.member();
object.member;
object->member()
Den kan kun finde:
object.member;
Avatar billede nielle Nybegynder
19. januar 2008 - 19:20 #19
Hvoir mange arkumenter kan der maks være i dine member() ? Og skal der altis være et komma efter det sidste argument?
Avatar billede mxs Nybegynder
19. januar 2008 - 19:23 #20
Det jeg skal bruge regexp'en til er at skaffe object og member. Det der er mellem () er jeg ligeglad med. Det kan være gyldig eller ugyldig C++ kode. Jeg skal bruge object til at finde typen af object og derefter skal jeg bruge member til at finde en fil på ala ~/stl-reference/type-member.
hvor type er typen på objektet.
Er ved at lave en lille STL reference :) Som skal kunne virke ved at trykke på en F tast.
Avatar billede mxs Nybegynder
19. januar 2008 - 19:26 #21
Måske bare mig der er ringe til at sætte formen op :) min regexp skal kunne fx kunne finde

vector v;
v.assign("hej");

Her skal den kunne finde v og assign. Derefter laver jeg en ny regexp som via v finder vector, og derfter åbner filen "vector-assign", som så indholder info omkring assign.
Avatar billede nielle Nybegynder
19. januar 2008 - 19:29 #22
Jeg ville menet at det kunne gøres med denne:

\s*([a-z]+)(?:\.|->)([a-z]+)(?:\(.*?\))?;

Escapet LISP-style bliver det til:

\\s*\([a-z]+\)\(?:\\.\|->\)\([a-z]+\)\(?:\\\(.*?\\\)\)?;

... eller måske fungere \s ikke:

[:blank:]*\([a-z]+\)\(?:\\.\|->\)\([a-z]+\)\(?:\\\(.*?\\\)\)?;
Avatar billede mxs Nybegynder
19. januar 2008 - 19:36 #23
Din version er næsten rigtig, i følge fileformat.info/tool/regex.htm :) Men elisps re-search-backward kan stadig kun finde object->member;
Kan se du bruger (?:) er det anonyme klasser? Eller hvad det nu hedder. Det er smart!!
Avatar billede nielle Nybegynder
19. januar 2008 - 19:37 #24
(?: ... ) er blot en gruppe som ikke fanger noget til senere. Jeg bruger den fordi at du kun ønsker at få fat på det to første.
Avatar billede nielle Nybegynder
19. januar 2008 - 19:44 #25
re-search-backward vil jeg ikke normalt anbefale at man bruger - regexp'er er nu engang beregnet til at blive brugt fra venstre til højre.

Forsøg at udvide motoren til også at kunne matche højre til venstre har ikke ubetinget succesfulde. Og jeg tør i hvert fald ikke gætte på hvad der egentlig sker internt i regexp-motoren i netop dette her tilfælde.
Avatar billede mxs Nybegynder
19. januar 2008 - 19:54 #26
Bruger jeg re-search-forward, får jeg samme resultat. Den finder object->member; og ingen andre.
Avatar billede nielle Nybegynder
19. januar 2008 - 19:58 #27
Kan den finde alle rækkerne hvis der er flere med:

object->member;

?
Avatar billede mxs Nybegynder
19. januar 2008 - 20:01 #28
Jeg har en fil med som ser sådan her ud:
object->member(string,arg, ...);
object.member(string,arg, ...);
object.member();
object.member;
object->member();
object->member;
object->member;

Når jeg afprøver regex'en, evaluere jeg min loopup funktion og kalder funktionen via M-x lookup [RET]. Derefter finder den kun object->member;. Ikke nogen af de andre.
Avatar billede mxs Nybegynder
19. januar 2008 - 20:03 #29
Men ja. Den kan finde samtlige object->member; linjer, hvis det er det som du mener.
Avatar billede nielle Nybegynder
19. januar 2008 - 20:04 #30
Finder den begge rækkerne, eller finder den kun den første af de to?
Avatar billede nielle Nybegynder
19. januar 2008 - 20:04 #31
Tak :^)
Avatar billede nielle Nybegynder
19. januar 2008 - 20:05 #32
Det er lidt interessant at de heller ikke finder:

object.member;
Avatar billede mxs Nybegynder
19. januar 2008 - 20:15 #33
Synes jeg også. Har lige forhørt mig på emacs kanalen på irc.freenod.org. De har givet mig en anden tilgang. En macro der hedder rx, skulle vist være en anden måde at opfatte regexps på i LISP (sikkert lavet fordi det er usansynlig svært at overskue denne ødelagte syntaks :P). rx, har en lisp orienteret tilgang til at lave regexps på. Emacs har desuden en re-builder også, som jeg også lige vil kigge på. Jeg skal lige spise, og vender defter tilbage til regexp'et. Jeg giver lige besked fra mig når jeg har afprøvet rx.
Avatar billede nielle Nybegynder
19. januar 2008 - 20:17 #34
Velbekomme :^)
Avatar billede mxs Nybegynder
20. januar 2008 - 12:03 #35
Jeg sad og legede med noget der hedder regexp-builder i emacs, og fandt hurtig ind i rytmen!! Jeg har nu følgende regexp som virker

\\([[:word:]]+\\)\\(\\.\\|\\->\\)\\([[:word:]]+\\)\\(\([A-Za-z,\"]+\);\\|\(\);\\|;\\)

Tak for hjælpen. Smidt et svar og få point.
Avatar billede nielle Nybegynder
20. januar 2008 - 12:10 #36
Svar :^)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester