/* Limitations: */ #include "CommonTools-C++.cws" function getParametersSignature(listOfParameters : node) { local sText; foreach i in listOfParameters { if !first(i) set sText += ','; set sText += getCppTargetType(i.type); } return sText; } translation_unit ::= #ignore(C++/Doxygen) => local myContext; [->remarkablePoint<"outside">(myContext)]* ->#empty; #include "CommonLanguage-Scanner.cwp" #include "CommonLanguage-Parser.cwp" remarkablePoint(myContext : node) ::= preprocessing(myContext) | doxygen:myContext.doxygen_comment | template_definition(myContext) | declare_type(myContext) | define(myContext) | #readCString ; preprocessing(myContext : node) ::= '#' #readIdentifier endOfLine; endOfLine : #!ignore ::= [!['\\' ['\r']? '\n'] ~'\n']* ['\n' | '\\' ['\r']? '\n' endOfLine] ; doxygen ::= "//!" #!ignore ->'\n' ["/*!" #!ignore ->"*/"]? | "/*!" #!ignore ->"*/" ; template_definition(myContext : node) ::= "template" #continue template_parameters_declaration(myContext) [ declare_type(myContext) | define(myContext) ] => removeLastElement(myContext.nested_template_parameters); ; template_parameters_declaration(myContext : node) ::= '<' #continue => pushItem myContext.nested_template_parameters; [ #readIdentifier:{"class", "typename"}:sType #continue #readIdentifier:sTemplateKey => insert myContext.nested_template_parameters#back.template_parameters[sTemplateKey] = sType; ['=' #continue target_language_type(myContext.nested_template_parameters#back.template_parameters[sTemplateKey])]? [ ',' #continue #readIdentifier:{"class", "typename"}:sType #readIdentifier:sTemplateKey => insert myContext.nested_template_parameters#back.template_parameters[sTemplateKey] = sType; ['=' #continue target_language_type(myContext.nested_template_parameters#back.template_parameters[sTemplateKey])]? ]* ]? '>' ; define<"outside">(myContext : node) ::= member<"structor_definition">(myContext) | member<"method_definition">(myContext) ; define<"class_declaration">(myContext : node) ::= member<"structor_definition">(myContext) | member<"method_definition">(myContext) | member<"attribute_definition">(myContext) ; keyword ::= #check(false); CLASS ::= #readIdentifier:"class"; keyword<"class"> ::= #check(true); member<"method_definition">(myContext : node) ::= => local listOfModifiers; [method_modifiers(listOfModifiers)]? => local myType; target_language_type(myType) => local sClassName; [ #readIdentifier:sClassName // template methods will have to be recognized! // [ // template_parameters_instantiation(myContext) // !!"::" // ]? "::" | #check(myContext) => set sClassName = myContext; | => set sClassName = false; ] => local listOfParameters; #readIdentifier:sMethodName => local bIsOperator = (sMethodName == "operator"); [ #check(bIsOperator) => set sMethodName = ""; #continue [ ~'(':cChar => set sMethodName += cChar; ]+ ]? ['(' #continue parameters(listOfParameters) ')'] [#readIdentifier:"const"]? [#readIdentifier:"throw" '(' ->')']? #continue => local bFunctionBody; => local bAbstractMethod; [ '{' => set bFunctionBody = true; | ';' | '=' '0' ['L']? ';' => set bAbstractMethod = true; ] => local myMemberObject; => { if sClassName { if !this.scan_only { if !project.classes.findElement(sClassName) { insert project.classes[sClassName] = sClassName; if !myContext.nested_names.empty() setall project.classes[sClassName].nested_names = myContext.nested_names; } localref myClassObject = project.classes[sClassName]; local sSignature = sMethodName + '(' + getParametersSignature(listOfParameters) + ')'; if bIsOperator set sSignature = "operator " + sSignature; if !myClassObject.methods.findElement(sSignature) { insert myClassObject.methods[sSignature] = sMethodName; } ref myMemberObject = myClassObject.methods[sSignature]; } else { set myMemberObject = sClassName; } if bIsOperator insert myMemberObject.is_operator = true; if !listOfModifiers.empty() setall myMemberObject.modifiers = listOfModifiers; setall myMemberObject.return_type = myType; if !listOfParameters.empty() setall myMemberObject.parameters = listOfParameters; if bAbstractMethod insert myMemberObject.is_abstract = true; if myContext.doxygen_comment { insert myMemberObject.comment = myContext.doxygen_comment; set myContext.doxygen_comment = false; } } } [ #check(bFunctionBody) #continue member<"function_body">(myMemberObject) '}' ]? ; template_parameters_specialization(theEntity : node) ::= '<' #continue => pushItem theEntity.template_parameters_specializations; target_language_type(theEntity.template_parameters_specializations#back) [ ',' #continue => pushItem theEntity.template_parameters_specializations; target_language_type(theEntity.template_parameters_specializations#back) ]* '>'; member<"structor_definition">(myContext : node) ::= => local listOfModifiers; [method_modifiers(listOfModifiers)]? => local sClassName; [ #readIdentifier:sClassName "::" | #check(myContext) => set sClassName = myContext; ] => local bDestructor; ['~' => set bDestructor = true;]? #readIdentifier:sMethodName #check(sMethodName == sClassName) => local listOfParameters; ['(' #continue parameters(listOfParameters) ')'] [ #readIdentifier:"throw" '(' ->')' ]? => local listOfInitializations; [ #check(!bDestructor) => insert listOfInitializations.class_name = sClassName; constructor_initializers(listOfInitializations) ]? '{' #continue => local myMemberObject; => if !this.scan_only { if !project.classes.findElement(sClassName) { insert project.classes[sClassName] = sClassName; if !myContext.nested_names.empty() setall project.classes[sClassName].nested_names = myContext.nested_names; } localref myClassObject = project.classes[sClassName]; if bDestructor { insert myClassObject.destructor = '~' + sClassName; ref myMemberObject = myClassObject.destructor; } else { local sSignature = sClassName + '(' + getParametersSignature(listOfParameters) + ')'; insert myClassObject.constructors[sSignature] = sClassName; ref myMemberObject = myClassObject.constructors[sSignature]; if !listOfParameters.empty() setall myMemberObject.parameters = listOfParameters; if !listOfInitializations.empty() setall myMemberObject.initializations = listOfInitializations; } } else { if bDestructor { set myMemberObject = '~' + sClassName; } else { set myMemberObject = sClassName; if !listOfParameters.empty() setall myMemberObject.parameters = listOfParameters; if !listOfInitializations.empty() setall myMemberObject.initializations = listOfInitializations; } } => { if !listOfModifiers.empty() setall myMemberObject.modifiers = listOfModifiers; if myContext.doxygen_comment { insert myMemberObject.comment = myContext.doxygen_comment; set myContext.doxygen_comment = false; } } member<"function_body">(myMemberObject) '}' ; constructor_initializers(listOfInitializations : node) ::= ':' #continue constructor_initializer(listOfInitializations) [',' #continue constructor_initializer(listOfInitializations)]* ; constructor_initializer(listOfInitializations : node) ::= #continue => pushItem listOfInitializations; #readIdentifier:listOfInitializations#back.attribute '(' expression(listOfInitializations#back.default_value) ')' ; method_modifiers(listOfModifiers : node) ::= [ #readIdentifier:{"virtual", "static", "inline", "explicit"}:sModifier => insert listOfModifiers[sModifier]; ]*; parameters(listOfParameters : node) ::= [ parameter(listOfParameters) [ ',' #continue [ parameter(listOfParameters) | "..." ] ]* ]? ; parameter(listOfParameters : node) ::= => local myType; target_language_type(myType) => pushItem listOfParameters; [ #readIdentifier:listOfParameters#back.name [ '[' #continue => pushItem myType.suffix = "array"; [#readIdentifier:myType.suffix#back.size | #readInteger:myType.suffix#back.size]? ']' ]* ]? => setall listOfParameters#back.type = myType; ['=' #continue expression(listOfParameters#back.default_value)]? ; member<"function_body">(myContext : node) ::= function_body(myContext) ; function_body(myContext : node) ::= [ '{' #continue function_body(myContext) '}' | ^'}' ]* ; member<"attribute_definition">(myContext : node) ::= => local listOfModifiers; [attribute_modifiers(listOfModifiers)]? => local myType; target_language_type(myType) #readIdentifier:sAttribute [ '[' #continue => pushItem myType.suffix = "array"; skipBrackets:myType.suffix#back.size ']' ]* ';' => if !this.scan_only { if myContext.attributes.findElement(sAttribute) error("attribute '" + sAttribute + "' already exists in class '" + myContext + "'"); insert myContext.attributes[sAttribute] = sAttribute; localref myAttribute = myContext.attributes[sAttribute]; if !listOfModifiers.empty() setall myAttribute.modifiers = listOfModifiers; setall myAttribute.type = myType; } ; attribute_modifiers(listOfModifiers : node) ::= #readIdentifier:"static":sModifier => insert listOfModifiers[sModifier]; ; declare_type(myContext : node) ::= declare_type<"class_definition">(myContext) | declare_type<"enum_definition">(myContext) | declare_type<"namespace_definition">(myContext) | declare_type<"typedef_definition">(myContext) | declare_type<"friend_definition">(myContext) | declare_type<"extern_definition">(myContext); declare_type<"friend_definition">(myContext : node) ::= #readIdentifier:"friend" #continue ->';' ; declare_type<"extern_definition">(myContext : node) ::= #readIdentifier:"extern" #continue ->';' ; declare_type<"enum_definition">(myContext : node) ::= #readIdentifier:"enum" #continue [#readIdentifier]? '{' ->'}' ->';' ; declare_type<"class_definition">(myContext : node) ::= => local theClassHeader; class_definition_header(theClassHeader) #continue => local myClassObject; => if !this.scan_only { if !theClassHeader.template_parameters_specializations.empty() { if !project.classes.findElement(theClassHeader) { insert project.classes[theClassHeader] = theClassHeader; } pushItem project.classes[theClassHeader].class_specializations; ref myClassObject = project.classes[theClassHeader].class_specializations#back; setall myClassObject = theClassHeader; } else { if project.classes.findElement(theClassHeader) { merge project.classes[theClassHeader] = theClassHeader; } else { setall project.classes[theClassHeader] = theClassHeader; } ref myClassObject = project.classes[theClassHeader]; } if !myContext.nested_template_parameters.empty() { merge myClassObject = myContext.nested_template_parameters#back; } } else { set myClassObject = theClassHeader; } => { if !myContext.nested_names.empty() setall myClassObject.nested_names = myContext.nested_names; if !myParents.inheritance.empty() setall myClassObject.inheritance = myParents.inheritance; if myContext.doxygen_comment { insert myClassObject.comment = myContext.doxygen_comment; set myContext.doxygen_comment = false; } } [remarkablePoint<"class_declaration">(myClassObject) | ^'}']* '}' ; class_definition_header(theClassHeader : node) ::= #readIdentifier:{"class", "struct"} #readIdentifier:theClassHeader [#readIdentifier:theClassHeader]? // under Windows, when 'class ...DECL ' [template_parameters_specialization(theClassHeader)]? [declare_type<"parent">(theClassHeader)]? '{' ; declare_type<"parent">(myContext : node) ::= [ ':' !':' #continue parent_declaration(myContext) [',' #continue parent_declaration(myContext)]* | !!'{' ] ; parent_declaration(theClassHeader : node) ::= #pushItem(theClassHeader.inheritance) [ #readIdentifier:{"public", "protected", "private", "virtual"}:sModifier => insert theClassHeader.inheritance#back.modifiers[sModifier]; ]* target_language_type(theClassHeader.inheritance#back) ; declare_type<"namespace_definition">(myContext : node) ::= #readIdentifier:"namespace" #readIdentifier:sNameSpace '{' #continue => pushItem myContext.nested_names = sNameSpace; [remarkablePoint<"outside">(myContext) | ^'}']* => removeLastElement(myContext.nested_names); '}' ; declare_type<"typedef_definition">(myContext : node) ::= #readIdentifier:"typedef" #continue ["typename"]? => local myType; target_language_type(myType) => local sTypedef = myType; [ #check(!myType.is_function) #continue #readIdentifier:sTypedef ]? ';' => setall project.typedefs[sTypedef] = myType; => if sTypedef == "Mutex" error("---------------------------"); ; expression(myExpr : node) ::= [ #readCString | '[' #continue expression(myExpr) ']' | '{' #continue expression(myExpr) '}' | '(' #continue expression(myExpr) ')' | ~[']' | '}' | ')'] ]*:myExpr ;