geof@imagen.UUCP (02/17/87)
The following is a grammar for the language accepted by the SmallC compiler. The names used for nonterminals in the grammar are compatible with the names used for procedures in the smallc compiler, so the grammer presents a useful method of documenting the compiler. There are also some surprises, such as a lack of C-compatibility in the ?: operator. The notation is somewhat informal, and close to the usual extended BNF: [x] => 0 or 1 occurances of x [x]* => 0 or more occurances of x [x]+ => 1 or more occurances of x This "looping/option" syntax is used instead of the normal recursive BNF style where the compiler code has that form. The grammar is divided to indicate file boundaries. Apologies for any mistakes. We spent three hours deriving this, and figured it would save others the trouble. - Geof Cooper IMAGEN -------------------------------------------------------------- # FILE MAIN.C parse ::= "extern" dodclsEXTERN | "static" dodclsSTATIC | dodclsPUBLIC | "#asm" doasm | "#include" doinclude | "#define" dodefine | "#undef" doundef | newfunc dodcls ::= char declglb | int declglb | declglb # FILE FUNCTION.C newfunc::= symname ( symname [, symname]* ) _newfunc statementYES _newfunc::= [register] char/int getarg ns getarg ::= [*] symname [ "[]" ] [, [*] symname [ "[]" ]]* # FILE STMT.C statementYES ::= { compound statementNO ::= stst | { compound stdecl ::= "register" doldclsDEFAULT | "auto" doldclsDEFAUTO | "static" doldclsLSTATIC | doldclsAUTO stst ::= "if" doif | "while" dowhile | "switch" doswitch | "do" dodo | "for" dofor | "return" doreturn | "break" dobreak | "continue" docont | "case" docase | "default" dodefault | "#asm" doasm | expression compound ::= [ stdecl ns ]* [ stst ns ]* } # FILE EXPR.C expression ::= heir1 [, heir1]* heir1 ::= heir1a | heir1a = heir1 | heir1a -= heir1 | heir1a += heir1 | heir1a *= heir1 | heir1a /= heir1 | heir1a %= heir1 | heir1a >>= heir1 | heir1a <<= heir1 | heir1a ^= heir1 | heir1a |= heir1 heir1a ::= heir1b | heir1b [? heir1b : heir1b]+ heir1b ::= heir1c | heir1c [|| heir1c]+ heir1c ::= heir2 | heir2 [&& heir2]+ heir2 ::= heir3 | heir3 ["|" heir3]+ heir3 ::= heir4 | heir4 [^ heir4]+ heir4 ::= heir5 | heir5 [& heir5]+ heir5 ::= heir6 | heir6 [== heir6] | heir6 [!= heir6] heir6 ::= heir7 | heir7 [<= heir7]+ | heir7 [>= heir7]+ | heir7 [< heir7]+ | heir7 [> heir7]+ heir7 ::= heir8 | heir8 [>> heir8]+ | heir8 [<< heir8]+ heir8 ::= heir9 | heir9 [+ heir9]+ | heir9 [- heir9]+ heir9 ::= heir10 | heir10 [* heir10]+ | heir10 [/ heir10]+ | heir10 [% heir10]+ heir10 ::= ++ heir10 | -- heir10 | - heir10 | ~ heir10 | ! heir10 | * heir10 | & heir10 | heir11 ++ | heir11 -- | heir11 heir11 ::= primary | primary ( expression ) | primary [ expression ] # FILE PRIMARY.C primary::= ( heir1 ) | "sizeof" ( "int" ) | "sizeof" ( "char" ) | "sizeof" ( symname ) | symname[GLOBAL/LOCAL] | constant constant::= number | pstr | qstr number ::= [+] _number | [-] _number _number::= 0x DIGITS | 0X DIGITS | 0 DIGITS | DIGITS pstr ::= ' [char]* ' qstr ::= " [char]* " char ::= [^\] | \\ | \ spechar spechar::= n | t | r | f | b | 0 -- {decwrl,sun,saber}!imagen!geof