ALL_CAPS means there is a corrosponding nodeType, which is a compound node for a non-terminal, and a primitive node for a terminal. MidCaps means the non-terminal describes a pattern of acceptable nodes. CLASS: CLASS_REQUIRED [ COMPILATION_DATE ] [ COMPILER_NAME COMPILER_VERSION ] [ DEBUGGING_SYMBOLS ] [ SOURCE_CODE ] COMPILATION_DATE: INTEGER COMPILER_NAME: STRING COMPILER_VERSION: INTEGER // major INTEGER // minor INTEGER // patch DEBUGGING_SYMBOLS: ? SOURCE_CODE: STRING CLASS_REQUIRED: MAGIC FORMAT_VERSION SYSTEM_VERSION CLASS_NAME [ PRIVATE ] LITERALS CODE CRYPTOHASH // of SOURCE_CODE (is this good for anything?) CRYPTOHASH // of CLASS_REQUIRED MAGIC: INTEGER FORMAT_VERSION: INTEGER // major INTEGER // minor INTEGER // patch SYSTEM_VERSION: INTEGER // major INTEGER // minor INTEGER // patch CLASS_NAME: STRING PRIVATE: // if present, loader does not add to global symbols // but instead drops reference to class object when it leaves scope CRYPTOHASH: INTEGER // need to specify hash algorythm LITERALS: ( Literal )* Literal: ( PrimitiveValue | SYMBOL ) // may want some way to include an object graph, perhaps as a // byte array to be fed to a standard decoder. PrimitiveValue: ( NULL | INTEGER | FLOAT | DOUBLE | BYTE_ARRAY | STRING | METHOD_SELECTOR ) SYMBOL: // candidate for being a primitive STRING // name of symbol in loader's symbol table CRYPTOHASH // of class referenced CODE: // could be subsumed into CLASS_REQUIRED STATE_LENGTH DISPATCH_DEPTH DISPATCHER METHOD_TABLE VERB_TABLE DISPATCHER: BLOCK // invoked with at least a method selector on the stack STATE_LENGTH: INTEGER // how many instance variables? DISPATCH_DEPTH: INTEGER // blocks in the method table are invoked with at least // this many stack elements METHOD_TABLE: ( BLOCK )* VERB_TABLE: ( LITERAL INTEGER )* // LITERAL must refer to a METHOD_SELECTOR // when DISPATCH sees METHOD_SELECTOR, METHOD_TABLE[INTEGER] is invoked BLOCK: ( Statement )* Statement: ( CompoundStatement | SimpleStatement ) CompoundStatement: ( BLOCK | IF | LOOP | CATCH | ALWAYS ) IF: RValue ( BLOCK | NULL ) ( BLOCK | NULL ) // pop stack, if true, execute first block, otherwise execute second LOOP: BLOCK RValue ( BLOCK | NULL ) ( BLOCK | NULL ) // execute first block, pop stack, if false, transfer to after loop // if true, execute second block, then third block // a continue during second block continues to third CATCH: BLOCK LValue BLOCK // execute the first block, if it throws an exception, push it // and execute the second block ALWAYS: BLOCK BLOCK // execute the first block, then the second block, even if the first // threw an exception. if the second block is entered during exception // processing, continue exception processing after finishing the second // block SimpleStatement: ( SEND | SENDV | SENDS | SENDSV | DISPATCH | RETURN | THROW | BREAK | CONTINUE | COPY ) SEND: RValue // method selector RValue // target ( RValue )* // args SENDV: RValue // must be a tuple SENDS: INTEGER // number of args RValue // method selector RValue // target ( RValue )* // args ( LValue )* // return values SENDSV: RValue // must be a tuple ( LValue )* // return values DISPATCH: RValue // method selector // pops method selector from stack and invokes the // corrosponding entry from the verb table. If no entry matches, // execution continues, and the method selector remains on the stack RETURN: ( RValue )* THROW: RValue BREAK: INTEGER // loop depth to break out of CONTINUE: INTEGER // loop depth to continue COPY: LValue RValue LValue: SLOT RValue: ( SLOT | LITERAL | Literal | THIS | STATE )