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: ( BLOCK | NULL ) ( BLOCK | NULL ) // pop stack, if true, execute first block, otherwise execute second LOOP: BLOCK ( 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 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: ( SENDS | SEND | DISPATCH | RETURN | THIS | STATE | THROW | BREAK | CONTINUE | ALLOC_TUPLE | UNPACK_TUPLE | GET | SET | PUSH | POP | SWAP | NTH | PUT_NTH | REQUIRE ) SENDS: // synchronous send. Pops tuple, method selector, target from stack // sends to target, and pushes return tuple // NOTE: should method selector and/or target be in tuple? SEND: // asnynchrnous send. Pops tuple, method selector, target from stack // arranges for later send to target. // NOTE: should method selector and/or target be in tuple? DISPATCH: // 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: // pops tuple from stack and pushes it on caller's stack before returning // control to caller. async return should push a zero length tuple, or // perhaps null. THIS: // pushes current object onto stack. STATE: // pushes instance vars onto stack as array reference (mutable tuple) THROW: // pops an exception off the stack and throws it. BREAK: INTEGER // loop depth to break out of CONTINUE: INTEGER // loop depth to continue ALLOC_TUPLE: INTEGER // length of new tuple // pops N things from the stack and creates an N element tuple from them UNPACK_TUPLE: INTEGER // length of tuple // pops tuple from stack and pushes exactly N elements onto the stack // throws an exception if the tuple is not of length N GET: INTEGER // state slot to retrieve value from. // Contents of that slot are pushed. // pop tuple/array to get value from? SET: INTEGER // state slot to put value in. // pops value and sets slot to that value // pop array to set value in? PUSH: ( LITERAL | Literal ) POP: INTEGER // how many items to pop SWAP: // swap top two stack entries NTH: INTEGER // which stack element to push a copy of PUT_NTH: INTEGER // which stack element to replace with the popped top of stack REQUIRE: INTEGER // how deep must the stack be right now? // might be able to loose this one with tuple sending.