Monday 11 July 2011

Grammar

Right. The time has come to, hopefully, determine a grammar. So far, I know what I want from the grammar, but as for whether it's genuinely feasible or not is another matter, and actually working through the EBNF for it is going to be tough, because I usually hate formally defining things. The plus side is that ditching templates will remove a trunk of ambiguity and the resulting grammar of C++ shouldn't be too bad to deal with, it's mostly C's easy-mode grammar. The down side is that having arbitrary expressions as types is probably going to hurt, and I'm still going to have to end up with a templates-esque grammar.

So far, I'm thinking of just using regular brackets for function arguments, regardless of which pass they're at. That would turn static_cast<float>(0) into static_cast(float, 0). The problem is defining the grammar for functions which make extensive use of computed types and all of the implicit auto that I've been thinking about adding.

// implicit auto
main() {
    // implicit auto
    DatabaseTableTypes = GetTypesForDatabaseTables("my_db", "admin", "password");
    DatabaseTableTypes["CustomerTable"] NewRecord;
}


So grammatically, a "DeadMG++" program is comprised of definitions. Namespaces, functions, classes, variables, whatever.





program := definitions
definitions := definition [definitions]


definition := type-creation
           := variable-definition
           := namespace-definition
           := function-definition


using-definition := 'using' identifier '=' type-definition


type-creation := type-literal
              := using-definition


pointer-modifier := '*' ['const']
array-modifier := '[' expression ']' [array-modifier] [pointer-modifier]
reference-modifier := '&'
                   := '&&'


type-modifiers := pointer-modifier
               := array-modifier
               := reference-modifier


type-base := ['const'] ['volatile'] identifier
                := expression
                := type-literal
                := 'auto'


type-definition := type-base [type-modifiers]
                
variable-definition := ['static'] [type-definition] identifier
                    := ['static'] [type-definition] identifier function-call
                    := ['static'] [type-definition] identifier '=' expression


namespace-definition := 'namespace' identifier '{' [definitions] '}'


function-definition := [type-definition] identifier function-arguments-list compound-statement


function-arguments-list := '(' function-arguments ')' [function-arguments-list]


function-arguments := [type-definition] identifier


variable-modifiers := ['static'] ['auto'] [type-definition]


type-definition-list := type-definition [',' type-definition-list]


function-call := '(' [expression-list] ')' [function-call]


function-call-expression := expression function-call


identifier := [_\w][_\w\d]*


cast-expression := 'static_cast' function-call
                := 'dynamic_cast' function-call
                := 'reinterpret_cast' function-call
                := 'const_cast' function-call


arithmetic-expression := expression '*' expression
                      := expression '+' expression
                      := expression '/' expression
                      := expression '-' expression
                      := '+' expression
                      := '-' expression


boolean-expression := expression '>' expression
                   := expression '<' expression
                   := expression '==' expression
                   := expression '!=' expression
                   := expression '<=' expression
                   := expression '>=' expression


member-expression := expression '.' identifier
                  := expression '->' identifier


return-statement := 'return' expression


type-literal := 'type' [':' type-definition-list] '{' [definitions] '}'


integral-literal := \d+
                 := '0x' [\dA-F]+


floating-point-literal := \d+ '.' \d+


literal-expression := type-literal
                   := integral-literal
                   := floating-point-literal


throw-statement := 'throw' expression
try-statement := 'try' compound-statement catch-statement
catch-statement := 'catch' '(' type-definition identifier ')' compound-statement [catch-statement]
                := 'catch' '(' '...' ')' compound-statement


access-expression := expression '[' expression ']'


assignment-expression := expression '=' expression


this-expression := 'this'


expression-list := [expression [',' expression-list]]

expression := member-expression
           := boolean-expression
           := arithmetic-expression
           := cast-expression
           := function-call-expression
           := access-expression
           := assignment-expression
           := type-definition
           := identifier
           := this-expression
           := literal-expression


if-statement := 'if' '(' expression ')' statement [else-statement]
else-statement := 'else' statement


label-statement := identifier ':'
goto-statement := 'goto' identifier


for-statement := 'for' '(' statement ';' expression ';' expression ')' compound-statement
while-statement := 'while' '(' expression ')' compound-statement
do-while-statement := 'do' compound-statement 'while' '(' expression ')'
case-statement := 'case' expression ':' statement-list [case-statement]
               := 'default' ':' statement-list
switch-statement := 'switch' '(' expression ')' '{' case-statement '}'


break-statement := 'break'
continue-statement := 'continue'


statement := expression
          := return-statement
          := if-statement
          := throw-statement
          := catch-statement
          := try-statement
          := compound-statement
          := label-statement
          := goto-statement
          := for-statement
          := while-statement
          := do-while-statement
          := switch-statement
          := break-statement
          := continue-statement


statement-list := statement [statement-list]


compound-statement := '{' [statement-list] '}'



Still missing

variadics
exception specifiers
lambdas
default arguments
enums

Likely, the grammar is flawed. I'm pretty sure that at the moment, you can grammatically do stupid things in many places, it's not tightly restricted enough. I need to work it again from the top down, some of the bottom stuff should be fine.

As correctly pointed out, string literals are missing, and catch statements aren't correctly limited to being after try statements.

No comments:

Post a Comment