GRAMMAR ======= ::= | empty ; ::= NUMBER | LABEL | ; ::= | ; ::= '\n' | ':' | EOF ; ::= | | ; ::= 'CONST' '=' | 'DIM' '(' ')' 'AS' | 'DIM' | 'TYPE' 'END TYPE' ; ::= 'AS' '*' NUMBER | 'AS' '=' | 'AS' ; ::= | | ; ::= 'LET' '=' | '=' ; ::= 'PRINT' ; ::= ';' | ',' | empty ; ::= '+' | '-' ; ::= '*' | '/' ; ::= '(' ')' | NUMBER | STRING | ; ::= | ; ::= '(' ')' '.' | '.' | ; ::= [a-zA-Z][a-zA-Z0-9_]* ; SOURCE FILE EXAMPLE =================== // Sample Program // TEST4.BAS // Type TStruct1 Name as String * 32 i as integer j(1 to 5) as integer End Type Const ARRAYSIZE = 3 Dim data(ARRAYSIZE) as TStruct1 Dim offset as integer = 2 data(offset).name = "Test" data(offset).i = 1 data(offset).j(offset) = 2 print data(offset).name, data(offset).j(offset); TREE OUTPUT =========== UDType ________/ | / _|____________ TStruct / \___ \ / \ \ Ident Ident Ident / | \ / \ / | \ String Name 32 Int i Int i 1-5 ________________________________________ ConstDecl / \ Ident Number | | ARRAYSIZE 3 ________________________________________ VarDecl | Ident / | \ data Ident TStruct / \ ARRAYSIZE Int ________________________________________ VarDecl / \ Ident Number / \ | offset Int 2 ________________________________________ Assign / \ Ident String ___/ / | | / / | "Test" data / Ident Ident | / \ name offset Int ________________________________________ Assign / \ Ident Number ___/ / | | / / | 1 data / Ident Ident | / \ i offset Int ________________________________________ Assign / \ Ident Number ___/ / | | / / | 2 data / Ident Ident | \ / \ j Ident offset Int / \ offset Int ________________________________________ Print ____/ | \____ / String \ Ident | Ident / | \ tab / | \ data | Ident data | Ident Ident | Ident | \ / | name / | j Ident offset Int offset Int / \ offset Int I also put this together this morning after getting some sleep. Here is what I propose on how I should structure my AST for type, const, and variable declaration statements: // CASTxxx - Represents an AST Node class // Other attributes represent member values of parent class // // ------------------------------------------------- // // Type TStruct1 // I as Integer // J as String * 32 // End Type // // CASTTypeDecl // / \ // CASTType CASTList // / / \ // TStruct1 CASTVarDecl CASTVarDecl // / | / \ // CASTIdent CASTType CASTIdent CASTType // | | | / \ // i Int j Str 32 // // ------------------------------------------------------ // // Type TStruct2 // K(1 to 5) As Integer // M as TStruct1 // End Type // // CASTTypeDecl // / \ // CASTType CASTList // / / \ // TStruct2 CASTVarDecl CASTVarDecl // / | / \ // CASTIdent CASTType CASTIdent CASTType // | / | \ | | // K 1 5 Int M TStruct1 // // ------------------------------------------------------ // // Const MEMSIZE = 512 // // CASTConstDecl // / \ // CASTIdent CASTNumLit // | | // MEMSIZE 512 // // ------------------------------------------------------ // // Dim v(1 to 15) as string * 25 // // CASTVarDecl // / | // CASTIdent CASTType // | / / \ \ // v Str 1 15 25 // // ------------------------------------------------------ // // Dim v as Integer = 25*2 // // CASTVarDecl // / | \ // CASTIdent CASTType CASTBinOp // | | / | \ // v Int CASTNum * CASTNum // | | // 25 2 // Now when we look at assignment statements, such as the following: // ------------------------------------------------------ // // rec(myrec(5).index).field = 6 // // = // / \ // . 6 // / \ // ( ) field // / \ // rec . // / \ // ( ) index // / \ // myrec 5 Since my CASTIdent object only really carries the name of the identifier that it represents, it really does 'not' lend itself well to the above left hand side because each identifier isn't just a simple name. as in previous examples. So I thought to extend CASTIdent to CASTQualIdent. This would handle the '.' parse node but still leaves how to handle the '( )' node. So I could then extend CASTIdent to another class called CASTArrayIdent. This would yield: // CASTAssign // / \ // CASTQualIdent CASTNum // / \ | // CASTArrayIdent CASTIdent 6 // / \ \ // CASTIdent CASTQualIdent field // | / \ // rec CASTArrayIdent CASTIdent // / \ \ // CASTIdent CASTNum index // | | // myrec 5 // More simplier examples: // ------------------------------------------------------ // // rec.field = 6 // // CASTAssign // / \ // CASTQualIdent CASTNum // / \ | // CASTIdent CASTIdent 6 // | | // rec field // // i = 5 // // CASTAssign // / \ // CASTIdent CASTNum // | | // i 5 // And by the way, drawing them out as trees, then labeling them with their properties and associating a class to them makes deriving the AST node classes much easier :-) Thanks graham! Chris