Alternativ-labels in grammatik & neuen ast-generator auf basis von antlr visitor

This commit is contained in:
luca9913 2023-01-17 06:38:00 +01:00
parent cb564dc436
commit c78a148766
2 changed files with 183 additions and 39 deletions

View File

@ -34,8 +34,8 @@ parser grammar Java17Parser;
options { tokenVocab=Java17Lexer; }
sourceFile
: packageDeclaration? importDeclaration* classOrInterface*
| moduleDeclaration EOF
: packageDeclaration? importDeclaration* classOrInterface* # srcfile
| moduleDeclaration EOF # moduledecl
;
packageDeclaration
@ -48,16 +48,16 @@ importDeclaration
classOrInterface
: classOrInterfaceModifier*
(classDeclaration | enumDeclaration | interfaceDeclaration | annotationTypeDeclaration | recordDeclaration)
| ';'
(classDeclaration | enumDeclaration | interfaceDeclaration | annotationTypeDeclaration | recordDeclaration) # classorinterfacedecl
| ';' # noclassorinterface
;
modifier
: classOrInterfaceModifier
| NATIVE
| SYNCHRONIZED
| TRANSIENT
| VOLATILE
| NATIVE
| SYNCHRONIZED
| TRANSIENT
| VOLATILE
;
classOrInterfaceModifier
@ -67,15 +67,15 @@ classOrInterfaceModifier
| PRIVATE
| STATIC
| ABSTRACT
| FINAL // FINAL for class only -- does not apply to interfaces
| FINAL // FINAL for class only -- does not apply to interfaces
| STRICTFP
| SEALED // Java17
| NON_SEALED // Java17
| SEALED // Java17
| NON_SEALED // Java17
;
variableModifier
: FINAL
| annotation
: FINAL # finalvarmod
| annotation # annotationvarmod
;
classDeclaration
@ -127,21 +127,21 @@ interfaceBody
;
classBodyDeclaration
: ';'
| STATIC? block
| modifier* memberDeclaration
: ';' # emptyclassbody
| STATIC? block # classblock
| modifier* memberDeclaration # memberdecl
;
memberDeclaration
: classOrInterface
| fieldDeclaration
| method
| constructor
: classOrInterface # memberclassorinterface
| fieldDeclaration # memberfield
| method # membermethod
| constructor # memberconstructor
;
method
: methodDeclaration
| genericMethodDeclaration
: methodDeclaration # methoddecl
| genericMethodDeclaration # genericmethod
;
/* We use rule this even for void methods which cannot have [] after parameters.
@ -150,19 +150,23 @@ method
for invalid return type after parsing.
*/
methodDeclaration
: refType? identifier formalParameters ('[' ']')*
: methodHeader
(THROWS exceptionList)?
methodBody
;
methodHeader
: refType? identifier formalParameters ('[' ']')*
;
methodBody
: block
| ';'
: block # methodblock
| ';' # emptymethod
;
refType
: typeType
| VOID
: typeType # reftype
| VOID # refvoid
;
genericMethodDeclaration
@ -170,8 +174,8 @@ genericMethodDeclaration
;
constructor
: genericConstructorDeclaration
| constructorDeclaration
: genericConstructorDeclaration # genericconstructor
| constructorDeclaration # constructordecl
;
genericConstructorDeclaration
@ -187,19 +191,19 @@ fieldDeclaration
;
interfaceBodyDeclaration
: modifier* interfaceMemberDeclaration
| ';'
: modifier* interfaceMemberDeclaration # interfacemember
| ';' # emptyinterface
;
interfaceMemberDeclaration
: constDeclaration
| interfaceMethodDeclaration
| genericInterfaceMethodDeclaration
| interfaceDeclaration
| annotationTypeDeclaration
| classDeclaration
| enumDeclaration
| recordDeclaration // Java17
: constDeclaration # interfaceconst
| interfaceMethodDeclaration # interfacemethod
| genericInterfaceMethodDeclaration # genericinterfacemethod
| interfaceDeclaration # subinterface
| annotationTypeDeclaration # interfaceannotationtype
| classDeclaration # interfaceclass
| enumDeclaration # interfaceenum
| recordDeclaration # interfacerecord // Java17
;
constDeclaration

View File

@ -0,0 +1,140 @@
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.List;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import de.dhbwstuttgart.environment.PackageCrawler;
import de.dhbwstuttgart.parser.antlr.Java17Parser;
import de.dhbwstuttgart.parser.antlr.Java17ParserBaseVisitor;
import de.dhbwstuttgart.parser.antlr.Java17Parser.AnnotationclassmodContext;
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassOrInterfaceModifierContext;
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassorinterfacedeclContext;
import de.dhbwstuttgart.parser.antlr.Java17Parser.ClassorinterfacemodContext;
import de.dhbwstuttgart.parser.antlr.Java17Parser.ModifierContext;
import de.dhbwstuttgart.parser.antlr.Java17Parser.NoclassorinterfaceContext;
import de.dhbwstuttgart.parser.scope.GatherNames;
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
public class ASTGen extends Java17ParserBaseVisitor<Object> {
private JavaClassRegistry reg;
private final GenericsRegistry globalGenerics;
private String pkgName = "";
Set<JavaClassName> imports = new HashSet<>();
// PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH
// bekommen
private Map<String, RefTypeOrTPHOrWildcardOrGeneric> fields = new HashMap<>();
// PL 2019-10-23: Muss für jede Klasse neu initilisiert werden
List<Statement> fieldInitializations = new ArrayList<>();
public ASTGen(JavaClassRegistry reg, GenericsRegistry globalGenerics) {
// Die Generics müssen während des Bauens des AST erstellt werden,
// da diese mit der Methode oder Klasse, in welcher sie deklariert werden
// verknüpft sein müssen. Dennoch werden die Namen aller Generics in einer
// globalen Datenbank benötigt.
this.globalGenerics = globalGenerics;
this.reg = reg;
}
public JavaClassRegistry getReg() {
return this.reg;
}
public String convertQualifiedName(Java17Parser.QualifiedNameContext ctx) {
String ret = "";
for (Java17Parser.IdentifierContext ident : ctx.identifier()) {
ret += ident.getText();
if (ctx.identifier().iterator().hasNext()) {
ret += '.';
}
}
return ret;
}
public SourceFile generate(Java17Parser.SourceFileContext ctx, PackageCrawler packageCrawler, ClassLoader classLoader)
throws ClassNotFoundException {
List<ClassOrInterface> classes = new ArrayList<>();
Map<String, Integer> imports = GatherNames.getImports(ctx, packageCrawler, classLoader);
this.imports = imports.keySet().stream().map(name -> reg.getName(name)).collect(Collectors.toSet());
return (SourceFile) this.visit(ctx);
}
@Override
public SourceFile visitSrcfile(Java17Parser.SrcfileContext ctx) {
for (Java17Parser.ClassOrInterfaceContext member : ctx.classOrInterface()) {
ClassorinterfacedeclContext clsoif;
if (member instanceof NoclassorinterfaceContext) {
continue;
} else {
clsoif = new ClassorinterfacedeclContext(member);
}
ClassOrInterface newClass;
int modifiers = 0;
if (!clsoif.classOrInterfaceModifier().isEmpty()) {
for (Java17Parser.ClassOrInterfaceModifierContext mod : clsoif.classOrInterfaceModifier()) {
int newModifier = (Integer) visit(mod);
modifiers += newModifier;
}
}
fieldInitializations = new ArrayList<>(); // PL 2019-10-22: muss für jede Klasse neu initilisiert werden
if (clsoif.classDeclaration() != null) {
newClass = convertClass(clsoif.classDeclaration());
} else {
newClass = convertInterface(clsoif.interfaceDeclaration());
}
classes.add(newClass);
}
return new SourceFile(this.pkgName, classes, this.imports);
}
@Override
public Object visitModifier(ModifierContext ctx) {
if (ctx.classOrInterfaceModifier() != null) {
return visit(ctx.classOrInterfaceModifier());
} else {
return convertModifier(ctx.getText());
}
}
@Override
public Object visitClassOrInterfaceModifier(ClassOrInterfaceModifierContext ctx) {
if (ctx.annotation() != null)
return 0;
return convertModifier(ctx.getText());
}
public static int convertModifier(String modifier) {
HashMap<String, Integer> modifiers = new HashMap<>();
modifiers.put(Modifier.toString(Modifier.PUBLIC), Modifier.PUBLIC);
modifiers.put(Modifier.toString(Modifier.PRIVATE), Modifier.PRIVATE);
modifiers.put(Modifier.toString(Modifier.PROTECTED), Modifier.PROTECTED);
modifiers.put(Modifier.toString(Modifier.ABSTRACT), Modifier.ABSTRACT);
modifiers.put(Modifier.toString(Modifier.STATIC), Modifier.STATIC);
modifiers.put(Modifier.toString(Modifier.STRICT), Modifier.STRICT);
modifiers.put(Modifier.toString(Modifier.FINAL), Modifier.FINAL);
modifiers.put(Modifier.toString(Modifier.TRANSIENT), Modifier.TRANSIENT);
modifiers.put(Modifier.toString(Modifier.VOLATILE), Modifier.VOLATILE);
modifiers.put(Modifier.toString(Modifier.SYNCHRONIZED), Modifier.SYNCHRONIZED);
modifiers.put(Modifier.toString(Modifier.NATIVE), Modifier.NATIVE);
modifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE);
int ret = 0;
for (String m : modifiers.keySet()) {
if (modifier.contains(m))
ret += modifiers.get(m);
}
return ret;
}
}