Class Parser

java.lang.Object
org.openjdk.asmtools.jasm.ParseBase
org.openjdk.asmtools.jasm.Parser

class Parser extends ParseBase
This class is used to parse Jasm statements and expressions. The result is a parse tree.

This class implements an operator precedence parser. Errors are reported to the Environment object, if the error can't be resolved immediately, a SyntaxError exception is thrown.

Error recovery is implemented by catching Scanner.SyntaxError exceptions and discarding input scanner.tokens until an input token is reached that is possibly a legal continuation.

The parse tree that is constructed represents the input exactly (no rewrites to simpler forms). This is important if the resulting tree is to be used for code formatting in a programming environment. Currently, only documentation comments are retained.

A parser owns several components (scanner, constant-parser, instruction-parser, annotations-parser) to which it delegates certain parsing responsibilities. This parser contains functions to parse the overall form of a class, and any members (fields, methods, inner-classes).

Syntax errors should always be caught inside the parser for error recovery.

  • Field Details

  • Constructor Details

  • Method Details

    • setDebugFlags

      void setDebugFlags(boolean debugScanner, boolean debugMembers, boolean debugCP, boolean debugAnnot, boolean debugInstr, boolean debugAttribute)
    • encodeClassString

      String encodeClassString(String classname)
    • getPosition

      public long getPosition()
    • parseVersion

      private Pair<Integer,Integer> parseVersion()
    • parseIdent

      String parseIdent() throws SyntaxError
      Throws:
      SyntaxError
    • parseLocVarDef

      void parseLocVarDef(OpcodeTables.Opcode opcode) throws SyntaxError
      Parse a local variable (type) presented in the form (var) index #name_index:#descriptor_index; [ (var) index name:descriptor; ] or (type) index #name_index:#signature_index; [ (type) index name:signature; ]

      index - a valid index into the local variable array of the current frame. name - valid unqualified name denoting a local variable descriptor - a field descriptor which encodes the type or the signature of a local variable in the source program

      Throws:
      SyntaxError
    • parseLocVarRef

      Indexer parseLocVarRef() throws SyntaxError
      Parse The index (LOCAL_VARIABLE) into the local variable array of the instructions: [wide]aload, astore, fload, fstore, iload, istore, lload, lstore, dload, dstore LOCAL_VARIABLE; [wide]iinc LOCAL_VARIABLE, NUMBER;
      Throws:
      SyntaxError
    • parseLocVarEnd

      void parseLocVarEnd(OpcodeTables.Opcode opcode) throws SyntaxError
      Parse The index (LOCAL_VARIABLE) into the local variable array of the instructions: either endvar LOCAL_VARIABLE; or endtype LOCAL_VARIABLE;
      Throws:
      SyntaxError
    • parseNameAndType

      void parseNameAndType(DataVector fields) throws SyntaxError
      Parse a set of CONSTANT_NameAndType_info entries in the following forms: #id1, #id2, #idN; or fldS:"Ljava/lang/String;", fldS:"I", fldI:"I";
      Parameters:
      fields - is the list of fields that is populated with a newly scanned item
      Throws:
      SyntaxError - if any format error
      IOException - if any input error
    • parseMapItem

      void parseMapItem(DataVector map) throws SyntaxError, IOException
      Throws:
      SyntaxError
      IOException
    • parseName

      ConstCell parseName() throws SyntaxError
      Parse an external name: CPINDEX, string, or identifier.
      Throws:
      SyntaxError
    • parseMethodHandle

      ConstCell parseMethodHandle(ClassFileConst.SubTag subtag) throws SyntaxError
      Parses a field or method reference for a method handle.
      Throws:
      SyntaxError
    • checkReferenceIndex

      private void checkReferenceIndex(long position, ClassFileConst.ConstType defaultTag, ClassFileConst.ConstType defaultTag2)
      Check the pair reference_kind:reference_index where reference_kind is any from: REF_invokeVirtual, REF_newInvokeSpecial, REF_invokeStatic, REF_invokeSpecial, REF_invokeInterface and reference_index is one of [Empty], Method or InterfaceMethod There are possible entries: ldc Dynamic REF_newInvokeSpecial:InterfaceMethod LdcConDyTwice."": ldc Dynamic REF_invokeInterface:LdcConDyTwice."": ldc Dynamic REF_newInvokeSpecial:Method LdcConDyTwice."": ldc MethodHandle REF_newInvokeSpecial:InterfaceMethod LdcConDyTwice."": ldc MethodHandle REF_invokeInterface:LdcConDyTwice."": ldc MethodHandle REF_newInvokeSpecial:Method LdcConDyTwice."": invokedynamic MethodHandle REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants: invokedynamic MethodHandle REF_invokeStatic:java/lang/invoke/StringConcatFactory.makeConcatWithConstants ....
      Parameters:
      position - the position in a source file
      defaultTag - expected reference_index tag (Method or InterfaceMethod)
      defaultTag2 - 2nd expected reference_index tag (Method or InterfaceMethod)
    • parseSubtag

      ClassFileConst.SubTag parseSubtag() throws SyntaxError
      Parses a sub-tag value in a method handle.
      Throws:
      SyntaxError
    • parseConstantPackageInfo

      ConstCell parseConstantPackageInfo() throws SyntaxError
      Throws:
      SyntaxError
    • parseConstantModuleInfo

      ConstCell parseConstantModuleInfo() throws SyntaxError
      Throws:
      SyntaxError
    • parseConstantClassInfo

      ConstCell parseConstantClassInfo(boolean uncond) throws SyntaxError
      Throws:
      SyntaxError
    • throwSyntaxError

      private void throwSyntaxError(String msgId) throws SyntaxError
      Throws:
      SyntaxError
    • prependPackage

      private String prependPackage(String className, boolean uncond)
    • parseInt

      Indexer parseInt(String opCode, int size) throws SyntaxError
      Parse a signed integer of size bytes long. size = 1 or 2
      Throws:
      SyntaxError
    • parseUInt

      Indexer parseUInt(int size) throws SyntaxError
      Parse an unsigned integer of size bytes long. size = 1 or 2
      Throws:
      SyntaxError
    • parseConstDef

      private void parseConstDef()
      Parse constant declaration
    • scanModifier

      private int scanModifier(int mod) throws SyntaxError
      Parse the modifiers
      Throws:
      SyntaxError
    • scanModifiers

      int scanModifiers() throws SyntaxError
      Throws:
      SyntaxError
    • parseField

      private void parseField(int mod) throws SyntaxError
      Parse a field.
      Throws:
      SyntaxError
    • countParams

      private int countParams(ConstCell sigCell) throws SyntaxError
      Scan method's signature to determine the size of parameters.
      Throws:
      SyntaxError
    • parseMethod

      private void parseMethod(int mod) throws SyntaxError, IOException
      Parse a method.
      Throws:
      SyntaxError
      IOException
    • parseCodeAttribute

      private void parseCodeAttribute() throws IOException
      Throws:
      IOException
    • parseThrowsClause

      private ArrayList<ConstCell<?>> parseThrowsClause()
      Returns:
      list of the exception classes
    • parseBootstrapMethodGroup

      private void parseBootstrapMethodGroup() throws SyntaxError
      Parse a group of BootstrapMethod entries.

      BootstrapMethods { N: MethodHandle; ( Arguments: (ARG,)* ARG; )? }

      Throws:
      SyntaxError
    • parseBootstrapMethod

      private void parseBootstrapMethod() throws SyntaxError
      Parse a BootstrapMethod entry individually.

      Two formats are supported: BootstrapMethod #METHODHANDLE (#ARG)*; BootstrapMethod #MH; { (#ARG,)* (ARG)? }

      Throws:
      SyntaxError
    • parseMHCell

      private ConstCell<?> parseMHCell() throws SyntaxError
      Throws:
      SyntaxError
    • parseClassSignature

      private void parseClassSignature() throws SyntaxError
      Parse the class Signature entry.
      Throws:
      SyntaxError
    • parseClassRef

      private void parseClassRef(Consumer<ConstCell<?>> consumer)
      Parse class reference used by statements: this_class[:] (CPINDEX | STRING); super_class[:] (CPINDEX | STRING);
    • parseSourceFile

      private void parseSourceFile() throws SyntaxError
      Throws:
      SyntaxError
    • parseSourceDebugExtension

      private void parseSourceDebugExtension() throws SyntaxError
      Parse a SourceDebugExtension attribute
      Throws:
      SyntaxError
    • parseNestHost

      private void parseNestHost() throws SyntaxError
      Parse a NestHost entry
      Throws:
      SyntaxError
    • parseClasses

      private void parseClasses(Consumer<ArrayList<ConstCell>> classesConsumer) throws SyntaxError
      Parse a list of classes belonging to the [NestMembers | PermittedSubclasses] entry
      Throws:
      SyntaxError
    • parseUtf8List

      private void parseUtf8List(Consumer<ArrayList<ConstCell>> utf8Consumer) throws SyntaxError
      Valhalla specific Parse a list of Utf-8 belonging to the [LoadableDescriptors] entry
      Throws:
      SyntaxError
    • parseEnclosingMethod

      private void parseEnclosingMethod()
    • parseRecord

      private void parseRecord() throws SyntaxError
      Throws:
      SyntaxError
    • parseInnerClassGroup

      private void parseInnerClassGroup(int mod) throws SyntaxError, IOException
      Parse a group of InnerClasses.
      Parameters:
      mod - inner_class_access_flags is ignored for a group of inner classes.
      Throws:
      SyntaxError
      IOException
    • parseInnerClass

      private void parseInnerClass(int mod) throws SyntaxError, IOException
      Parse an inner class.
      Parameters:
      mod - inner_class_access_flags
      Throws:
      SyntaxError
      IOException
    • parseInnerClass_s1

      private void parseInnerClass_s1(int mod, ConstCell nameCell, ConstCell innerClass, ConstCell outerClass) throws IOException
      Throws:
      IOException
    • parseInnerClass_s2

      private void parseInnerClass_s2(int mod, ConstCell nameCell, ConstCell innerClass, ConstCell outerClass) throws IOException
      Throws:
      IOException
    • parseInnerClass_s3

      private void parseInnerClass_s3(int mod, ConstCell nameCell, ConstCell innerClass, ConstCell outerClass) throws IOException
      Throws:
      IOException
    • pic_tracecreate

      private void pic_tracecreate(int mod, ConstCell nameCell, ConstCell innerClass, ConstCell outerClass)
    • pic_error

      private void pic_error()
    • match

      private void match(JasmTokens.Token open, JasmTokens.Token close)
      The match() method is used to quickly match opening brackets (ie: '(', '{', or '[') with their closing counterpart. This is useful during error recovery.

      Scan to a matching '}', ']' or ')'. The current scanner.token must be a '{', '[' or '(';

    • recoverField

      private void recoverField() throws SyntaxError
      Recover after a syntax error in a field. This involves discarding scanner.tokens until an EOF or a possible legal continuation is encountered.
      Throws:
      SyntaxError
    • parseClass

      private void parseClass(int mod) throws IOException
      Parse a class or interface declaration.
      Throws:
      IOException
    • parseTypeName

      private NameInfo parseTypeName()
      Parses a package or type name in a module statement(s)
      Returns:
      Pair Either Package/Type name or CP Index for this Package/Type name.
    • parseModuleName

      private NameInfo parseModuleName()
      Parses a module name in a module statement(s)
      Returns:
      Pair Either Module name or CP Index for the module name.
    • parseModule

      private void parseModule(int mod) throws IOException
      Parse a module declaration.
      Throws:
      IOException
    • scanRequires

      private void scanRequires(Consumer<ModuleContent.Dependence> action)
      Scans ModuleStatement: requires [transitive|static|mandated|synthetic] ModuleName ; Scans ModuleStatement: requires [transitive|static|mandated|synthetic] #ref ;
    • scanStatement

      private <T extends ModuleContent.TargetType> void scanStatement(BiConsumer<T, Set<ModuleContent.TargetType>> action, Parser.NameSupplier source, Parser.NameSupplier target, JasmTokens.Token startList, boolean emptyListAllowed, String err) throws IOException
      Scans Module Statement(s): exports [mandated|synthetic] packageName [to ModuleName {, ModuleName}*] ; opens [mandated|synthetic] packageName [to ModuleName {, ModuleName}*] ; provides TypeName with TypeName {,typeName} ;
      Throws:
      IOException
    • scanStatement

      private void scanStatement(Consumer<ModuleContent.TargetType> action, String err) throws IOException
      Scans ModuleStatement: uses TypeName;
      Throws:
      IOException
    • scanList

      private HashSet<NameInfo> scanList(Parser.Method scanMethod, Parser.NameSupplier target, String err, boolean onlyOneElement) throws IOException
      Scans the "to" or "with" part of the following ModuleStatement: exports PackageName [to ModuleName {, ModuleName}] ;, opens PackageName [to ModuleName {, ModuleName}] ; provides TypeName with TypeName [,typeName] ; uses TypeName;

      : [ModuleName {, ModuleName}]; , [TypeName [,typeName]]; or TypeName;

      Throws:
      IOException
    • parseClassMembers

      private void parseClassMembers() throws IOException
      Throws:
      IOException
    • recoverFile

      private void recoverFile() throws IOException
      Recover after a syntax error in the file. This involves discarding scanner.tokens until an EOF or a possible legal continuation is encountered.
      Throws:
      IOException
    • endClass

      private void endClass()
      End class
    • endPackageInfo

      private void endPackageInfo()
      End package-info
    • endModule

      private void endModule()
      End module
    • getClassesData

      final ClassData[] getClassesData()
    • parseJasmPackages

      private void parseJasmPackages() throws IOException
      Determines whether the JASM file is for a package-info class or for a module-info class.

      creates the correct kind of ClassData accordingly.

      Throws:
      IOException - if any parse exception is met
    • parseFile

      void parseFile()
      Parse an Jasm file. 1. File FILENAME or class file CLASSNAME takes the highest priority. This filename cannot be overridden. 2. Public class CLASSNAME { }– class name is CLASSNAME, and this CLASSNAME will be used to generate the filename (i.e., CLASSNAME.class). 3. this_class – The filename will be CLASSNAME.class, but the class name will be this_class.
    • parseResultingFile

      private String parseResultingFile() throws IOException
      The source text file can be free form (newlines are considered blanks) and may contain Java-style commenting. The first line of a JASM file represents the name of the resulting file in the destination directory. This name does not affect the content of the resulting file. This line has two forms: file FILENAME; or classfile CLASSNAME; In the latter case, extension .class will be added to form FILENAME.
      Throws:
      IOException
    • initializeClassData

      private void initializeClassData()