Avatar billede repsak Nybegynder
26. december 2003 - 02:05 Der er 21 kommentarer og
1 løsning

Program logik

Jeg sidder og prøver at lave en lille javadoc, men mangler nogle råd. Jeg har lavet et klassehierarki som består af klasserne: pagkage, class, method, field. (interface hører pt. under class - ved ikke om det er smart) fx. består Class af en liste som kan indeholde fields og en liste til metoder.

Jeg skal nu lave en metode som læser en kildefil og kan 'forstå' hvad der er hvad. Således at når den støder på en metode så skal den adderes i den aktuelle klases metodeliste. Min grundidé er at benytte reg.ex. og har også allerede lavet en skabelon, men jeg ville meget gerne have input til hvordan jeg laver denne readSource-metode.
Avatar billede arne_v Ekspert
26. december 2003 - 11:28 #1
På jævnt dansk: du skal lave en parser som forstår Java syntax ?

Jeg ville finde det meget fristende at finde en parse generator
med en java grammatik, hvor der bare skulle sættes udførsels kode ind,
i.s.f. ar skrive en parse fra bunden af.

Det er ikke helt simpelt at håndtere alle mulige sære special
tilfælde (inner anonymous classes og den slags).
Avatar billede repsak Nybegynder
26. december 2003 - 12:27 #2
Jeps jeg skal lave en parser som forstår Javasyntaks...
...og jeg er instillet på at prøve kræfter med at skrive den fra bunden af. Såå svært tror jeg nu heller ikke det er. Det gør heller ikke noget hvis den ikke kan forstå ALT, men den skal kunne finde metoder, fields, classes og packages. Har du evt. nogle idéer til min read? :-)
Avatar billede arne_v Ekspert
26. december 2003 - 16:16 #3
Måske noget a la:

* class X * => klasse
* interface X * => interface
antal('{')-antal('}')==1 og * X ( * => metode
antal('{')-antal('}')==1 og * X ikke('(') * => attribut
Avatar billede repsak Nybegynder
26. december 2003 - 18:08 #4
hmm kan ikke lige følge din "antal('{')-antal('}')==1 og * X ( * => metode
" teori...
Kan man ikke bare indlæse sourcen én gang til en string(buffer) og så med reg.ex matche hhv. metode, field, class mm.?
Avatar billede arne_v Ekspert
26. december 2003 - 18:48 #5
Problem stillingen er:

class X {
  int a;
  void b() {
      int c;
      d();
  }
}

hvor du skal have a og b men ikke c og d.

Mit forslag var at bruge antal('{')-antal('}') til at teste
for niveauet (den er 0 for X, 1 for a og b, 2 for c og d).
Avatar billede arne_v Ekspert
26. december 2003 - 18:49 #6
Om du læser det hele ind eller ej er bare en detalje.

Men du får en uhyggelig kompliceret reg exp, hvis den kal tage højde
for niveauet.
Avatar billede repsak Nybegynder
26. december 2003 - 18:52 #7
ahhh that makes sense :-) Jeg prøver mig lige frem med den
Avatar billede repsak Nybegynder
27. december 2003 - 12:45 #8
giver dette mening? (jeg spørger da det ikke er testet, men kun er på teoretisk plan endnu)

1) Regular Experssion til at finde fx en metode
2) Finde indexet på match
3) BracketLevel(int index) til finde ud af om der er tale om b eller d (ref dit eksampel)

og er det smart at søge efter denne for med reg.Ex istedet for? :
\s*.*\(.*\){.*} (altså søge efter en metode MED indhold)
Avatar billede arne_v Ekspert
27. december 2003 - 16:10 #9
Jeg tror at jeg vil prøve at bixe lidt illustrativ kode.
Avatar billede arne_v Ekspert
27. december 2003 - 16:55 #10
import java.io.*;
import java.util.regex.*;

public class JavaParse {
    private static String load(String filename) throws Exception {
        StringBuffer sb = new StringBuffer("");
        InputStream is = new FileInputStream(filename);
        int c;
        while((c = is.read()) >= 0) {
            sb.append((char)c);
        }
        return sb.toString();
    }
    private static final String classpat = "class [A-Za-z][A-Za-z0-9]*";
    private static final String methodpat = "[A-Za-z][A-Za-z0-9]*\\(";
    private static final String attr1pat = "[A-Za-z][A-Za-z0-9]*;";
    private static final String attr2pat = "[A-Za-z][A-Za-z0-9]* =";
    private static final String startbracket = "\\{";
    private static final String endbracket = "\\}";
    private static final String allpat = classpat + "|" + methodpat + "|" +
                                        attr1pat + "|" + attr2pat + "|" +
                                        startbracket + "|" + endbracket;
    private static final Pattern pall = Pattern.compile(allpat);   
    private static final Pattern pclass = Pattern.compile(classpat);
    private static final Pattern pmethod = Pattern.compile(methodpat);
    private static final Pattern pattr1 = Pattern.compile(attr1pat);
    private static final Pattern pattr2 = Pattern.compile(attr2pat);
    private static void parse(String code) {
        Matcher m = pall.matcher(code);
        int ind = 0;
        while(m.find()) {
            String s = m.group();
            if(pclass.matcher(s).matches()) {
                System.out.println("class=" + s.substring(6));
            } else if(ind==1 && pmethod.matcher(s).matches()) {
                System.out.println("method=" + s.substring(0, s.length() - 1));
            } else if(ind==1 && pattr1.matcher(s).matches()) {
                System.out.println("attribute=" + s.substring(0, s.length() - 1));
            } else if(ind==1 && pattr2.matcher(s).matches()) {
                System.out.println("attribute=" + s.substring(0, s.length() - 2));
            } else if(s.equals("{")) {
                ind++;
            } else if(s.equals("}")) {
                ind--;
            }
        }       
    }
    public static void main(String[] args) throws Exception {
        String code = load("C:\\GUI.java");
        parse(code);
    }
}
Avatar billede arne_v Ekspert
27. december 2003 - 16:56 #11
Jeg kan lave en meget lang liste over hvad ovenstående kode ikke kan klare.

Men den kan nu klare en del.

Og du kunne forbedre den lidt ved at tillade variabelt mængde whitespace
forskellige steder (så skal "pil ud" forbedres lidt, men det kan også gøres).
Avatar billede arne_v Ekspert
27. december 2003 - 16:56 #12
og et svar
Avatar billede repsak Nybegynder
27. december 2003 - 17:04 #13
Nice - det ser skam godt ud. Jeg er opmærksom på dine problemstillinger - hvilke jeg har forsøgt at løse i min egen lille programdemo. Jeg skal ud af døren nu så jeg vender tilbage imorgen :-)
Avatar billede repsak Nybegynder
28. december 2003 - 17:04 #14
gider du ikke lige forklare denne? (jeg kan ikke følge din reg.Exp)
private static final String methodpat = "[A-Za-z][A-Za-z0-9]*\\(";
Avatar billede repsak Nybegynder
28. december 2003 - 17:10 #15
men ellers har jeg lige testet din demo. Den var ikke så glad for
private final static int MASK_A = 0x01;
men det kan jeg sagtens selv løse. Jeg siger tusinde tak for inspirationen+eksemplet
Avatar billede arne_v Ekspert
28. december 2003 - 17:44 #16
methodpat = "[A-Za-z][A-Za-z0-9]*\\("

siger metodenavn = 1 bogstav + 0 til mange bogstaver eller tal
Avatar billede arne_v Ekspert
28. december 2003 - 17:44 #17
Måske skulle underscore tilføjes !

:-)
Avatar billede arne_v Ekspert
28. december 2003 - 17:45 #18
\\( betyder efterfugt af parentes
Avatar billede repsak Nybegynder
28. december 2003 - 17:52 #19
argh havde lige glemt at ( skal skrives som \( som jo så bliver til \\(
Tak :-)
Avatar billede repsak Nybegynder
28. december 2003 - 17:54 #20
methodpat = "[A-Za-z][A-Za-z0-9]*\\("
=
methodpat = "[[\D][\w]*\\("
?
Avatar billede arne_v Ekspert
28. december 2003 - 17:56 #21
Så skrap er jeg ikke til regular expressions.

Men udfra docs: ja.

Eneste jeg er lidt i tvivl om er om non-digits tillader ikke-bogstaver
(punktum, komma etc.).
Avatar billede repsak Nybegynder
28. december 2003 - 17:59 #22
fair nok - jeg prøver mig frem...
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