# Grammar for Python 2.5.2 pyc files

# This grammar is the result of reverse engineering of marshal.c
# from sources of Python 2.5.2.

# Start symbol for the grammar is pyc.

# Being checked at the moment, but looks ok.
# Error with 'long' was corrected.
# Error with 'float' was corrected.

BYTE ::=     '\0' .. '\377'

WORD ::=     BYTE BYTE
 
DWORD ::=    WORD WORD

TUPLE ::=    '('

ELLIPSIS ::= '.'

NULL ::=     '0'

SET ::=      '<'

FROZENSET ::= 
             '>'

UNKNOWN ::=  '?'

FALSE ::=    'F'

INT64 ::=    'I'

NONE ::=     'N'

STRINGREF ::=
             'R'

STOPITER ::=
             'S'

TRUE ::=     'T'

LIST ::=     '['

CODE ::=     'c'

FLOAT ::=    'f'

BINARY_FLOAT ::= 
             'g'

INT ::=      'i'

LONG ::=     'l'

STRING ::=   's'

INTERNED ::= 't'

COMPLEX ::=  'x'

BINARY_COMPLEX ::=
             'y'

DICT ::=     '{'

UNICODE ::=  'u'

length ::=   DWORD

s_length ::= BYTE

index ::=    DWORD

operand ::=  WORD

# this is the start
pyc ::=
             magic
             object

magic ::=    DWORD DWORD

object ::=   simple_object | complex_object

simple_object ::=
             NULL
                | NONE
                | STOPITER
                | ELLIPSIS
                | FALSE
                | TRUE
                | UNKNOWN

complex_object ::=
             INT int
                | INT64 int64
                | LONG long
                | FLOAT float
                | BINARY_FLOAT binary_float
                | COMPLEX complex
                | BINARY_COMPLEX binary_complex
                | INTERNED interned
                | STRING string
                | STRINGREF stringref
                | UNICODE unicode
                | TUPLE tuple
                | LIST list
                | DICT dict
                | SET set
                | FROZENSET frozenset
                | CODE  code

# integer group
int ::=      DWORD

int64 ::=    lo4 hi4

lo4 ::=      int

hi4 ::=      int

# turned out to be a tricky thing, this type is for long arithmetics, don't confuse with C data type
long ::=     length WORD{abs(length)}

# other numbers
float ::=    s_length BYTE{s_length}

binary_float ::=
             DWORD DWORD

complex ::=  float float

binary_complex ::=
             binary_float binary_float

# string types
interned ::= string

string ::=   length BYTE{length}

stringref ::=
             index

unicode ::=  string

# complex types
tuple ::=    length object{length}

list ::=     tuple

dict ::=     (key val)* NULL

key ::=      object

val ::=      object

set ::=      tuple

frozenset ::=
             set

# code object
code ::=
             argcount
             nlocals
             stacksize
             flags
             code
             consts
             names
             varnames
             freevars
             cellvars
             filename
             name
             firstlineno
             lnotab

argcount ::= int

nlocals ::=  int

stacksize ::=
             int

flags ::=    int

code ::=     object

consts ::=   object

names ::=    object

varnames ::= object

freevars ::= object

cellvars ::= object

filename ::= object

name ::=     object

firstlineno ::=
             int

lnotab ::=   object