module languages/ansi-c/syntax/Declarations

%% The syntax of abstract declarators and declarators is so similar, that
%% we could make a parameterized module for them:
imports languages/ansi-c/syntax/Declarators[Declarator Identifier]
imports languages/ansi-c/syntax/Declarators[AbstractDeclarator AnonymousIdentifier]
imports languages/ansi-c/syntax/Identifiers
imports languages/ansi-c/syntax/Expressions

exports

sorts Declaration InitDeclarator Specifier StructDeclaration StructDeclarator Parameters  MoreParameters
sorts Initializer TypeName Pointer Enumerator AbstractDeclarator Declarator Parameter

context-free syntax
Specifier+ {InitDeclarator ","}+ ";" -> Declaration
Specifier+ ";"                       -> Declaration {avoid}

context-free syntax
Declarator                 -> InitDeclarator
Declarator "=" Initializer -> InitDeclarator

context-free syntax
Identifier		-> Specifier 

"typedef"		-> Specifier
"extern"			-> Specifier
"static"			-> Specifier
"auto"			-> Specifier
"register"		-> Specifier
"void"			-> Specifier
"char" 			-> Specifier
"short" 			-> Specifier
"int" 			-> Specifier
"long"			-> Specifier
"float" 			-> Specifier
"double"			-> Specifier
"signed"			-> Specifier
"unsigned" 		-> Specifier
"const"    		-> Specifier
"volatile" 		-> Specifier

context-free syntax
"struct"|"union" Identifier "{" StructDeclaration+ "}" -> Specifier
"struct"|"union"            "{" StructDeclaration+ "}" -> Specifier
"struct"|"union" Identifier                            -> Specifier

context-free syntax
"enum"            "{" {Enumerator ","}+  "}"	 -> Specifier
"enum" Identifier "{" {Enumerator ","}+  "}"	 -> Specifier
"enum" Identifier                                -> Specifier

lexical restrictions
	"return" -/- [0-9a-zA-Z\_]
	"enum" -/- [0-9a-zA-Z\_]
	"struct" | "union" -/- [0-9a-zA-Z\_]

context-free syntax
Specifier+ {StructDeclarator ","}+ ";" -> StructDeclaration

context-free syntax
Declarator                -> StructDeclarator
           ":" Expression -> StructDeclarator
Declarator ":" Expression -> StructDeclarator

context-free syntax
Identifier 		-> Enumerator
Identifier "=" Expression 	-> Enumerator

context-free syntax
("*" Specifier*)+ -> Pointer

context-free syntax
{Parameter ","}+ MoreParameters? -> Parameters

context-free syntax
"," "..." -> MoreParameters

context-free syntax
Specifier+ Declarator 		-> Parameter
Specifier+ AbstractDeclarator 	-> Parameter

context-free syntax
Specifier+ AbstractDeclarator	-> TypeName

context-free syntax
Expression 		  -> Initializer
"{" {Initializer ","}+ ","?  "}"  -> Initializer

%% The , needs some extra attention, in order to give the initializer
%% separator and actual argument separator a higher priority than the
%% left associative comma expression.

context-free syntax 
%% for documentation purposes we repeat here a production that is 
%% otherwise also generated by the normalizer from {Expression ","}+
Expression                -> {Expression ","}+ 

context-free priorities
Expression                -> Initializer >
Expression "," Expression -> Expression,

Expression                -> {Expression ","}+ >
Expression "," Expression -> Expression,

Identifier "=" Expression -> Enumerator >
Expression "," Expression -> Expression