| William.Waite@Colorado.edu |
This specification can be processed by the Eli system to yield a ``lint''
program, a browsable HTML version of the document, or a PostScript version.
The specification can also be used as one component of a larger
specification from which a C compiler or special-purpose analyzer could be
generated, or it could form the basis for a specification of an extension to C.
2 Normative references
The description here implements a portion of ANSI/ISO 9899-1990.
It is organized in parallel with that document, for easy verification of
the description.
This specification was developed and tested using Eli 4.0.
A complete description of Eli, including the current public-domain source
code, can be found at URL http://eli-project.sorceforge.net/.
3 Definitions and Conventions
3.1 c.gla
A type-gla file contains the declarative specifications
of the character strings to be recognized in the input text.
c.gla[1]==This macro is attached to a product file.Lexical elements[15] $# (auxEOL) $\f
c.con[2]==This macro is attached to a product file.Constants[43] Enumeration constants[51] String sequence[54] Primary expressions[70] Postfix operators[71] Unary operators[79] Cast operators[84] Multiplicative operators[87] Additive operators[89] Bitwise shift operators[92] Relational operators[94] Equality operators[97] Bitwise AND operator[100] Bitwise exclusive OR operator[102] Bitwise inclusive OR operator[104] Logical AND operator[106] Logical OR operator[109] Conditional operator[112] Assignment operators[115] Comma operator[125] Constant Expressions[126] Declarations[127] Statements[170] External definitions[177] Function definitions[178] Optional symbols[14] root: source . source: / file . file: translation_unit .
c.map[3]==This macro is attached to a product file.MAPSYM Expressions[69] Map the assignment operator symbol[116] Declaration_specifier equivalence class[133] Direct_declarator equivalence class[154] Member_declarator equivalence class[139] Parameter_part equivalence class[157] Abstract_declarator equivalence class[166]
c.lido[4]==This macro is attached to a product file.Function scope[18] File scope[19] Block scope[20] Tag scope[24] Function prototype scope[23] Disambiguation of member names[28] Semantics of declarations[129] Semantics of structure and union specifiers[141] Semantics of enumeration specifiers[143] Semantics of declarators[159] Access to the key attribute for ordinary identifiers[182] Tags[144] Use of an enumerated type tag[148] Check for multiply-declared tags[145] Tag that may or may not be a declaration[147] Forward definition of a tag[149] Anonymous structure, union or enumerated type[150] Pointer declarators[161] Array declarators[163] Function declarators (including prototypes)[164] Semantics of type names[167] Semantics of function definitions[179] Semantics of identifiers[180]
c.oil[5]==This macro is attached to a product file.Types[30] Implicit conversions[56] Array subscripting[72] Function calls[75] Postfix increment and decrement operators[77] Address and indirection operators[80] Unary arithmetic operators[82] Cast operator semantics[85] Multiplicative operator semantics[88] Additive operator semantics[90] Bitwise shift operator semantics[93] Relational operator semantics[95] Equality operator semantics[98] Bitwise AND operator semantics[101] Bitwise exclusive OR operator semantics[103] Bitwise inclusive OR operator semantics[105] Logical AND operator semantics[107] Logical OR operator semantics[110] Conditional operator semantics[113] Simple assignment[117] Compound assignment[123]
c.c[6]==This macro is attached to a product file.#include "eliproto.h" #include "err.h" #include "envmod.h" #include "termcode.h" #include "pdl_gen.h" #include "c.h" State variable definitions[199] Initial classification of identifier terminals[220] Re-classify an identifier terminal to fit the context[221] Bind a defining occurrence of an ordinary identifier[225] void InitOrdinary() { Initialize the array of definition table keys[209] Initialize the set of bindings having file scope[185] }
c.h[7]==Initialization of the scanner must include initialization of the environment for ordinary identifiers.This macro is attached to a product file.#ifndef C_H #define C_H #include "eliproto.h" #include "envmod.h" #include "RegionStack.h" #include "OrdinaryIdStack.h" #include "reparatur.h" State variable declarations[204] Operation interfaces[226] extern void InitOrdinary(); #endif
scanops.h[8]==This macro is attached to a product file.#ifndef SCANOPS_H #define SCANOPS_H #define SCANPTR \ { InitOrdinary(); TokenEnd = TEXTSTART; StartLine = TokenEnd - 1; } #endif
c.pdl[9]==This macro is attached to a product file.Properties of ordinary identifiers used during parsing[211] Function conversion operator[63] Property characterizing multiply-declared tags[146]
c.specs[10]==This macro is attached to a product file.Name analysis modules for label identifiers[17] Name analysis modules for member identifiers[140] Name analysis module for ordinary identifiers[128] Name spaces of identifiers[27] Create a module to stack Environment values[184] Create a module to stack DefTableKey values[206] Create a module to stack identifier state values[214]
c.head[11]==This macro is attached to a product file.#include "c.h" #include "termcode.h" #include "IdStateStack.h" Computations for obtaining the tag environment from a declarator[22]
c.init[12]==This macro is attached to a product file.Initialize the class of ordinary identifiers[215]
c.ctl[13]==This macro is attached to a product file.Do not allow attribution during tree construction[183]
Optional symbols are defined implicitly in the standard, but explicit definitions are required in order to generate a parser:
Optional symbols[14]==The symbol empty is used only in those cases where the attribution rules require a tree node with a nonterminal child.This macro is invoked in definition 2.abstract_declarator_opt: / abstract_declarator . constant_exp_opt: / constant_expression . declaration_list_opt: empty / declaration_list . member_declarator_opt: / member_declarator . expression_opt: / expression . identifier_list_opt: / identifier_list . init_declarator_list_opt: / init_declarator_list . parameter_type_list_opt: / Prototype begin[186] Begin a parameter_type_list[194] parameter_type_list End a parameter_type_list[195] Prototype end[187] . statement_list_opt: / statement_list . empty: .
Lexical elements[15]==This macro is invoked in definition 1.Identifiers[16] Floating constants[44] Integer constants[48] Character constants[52] String literals[53] Comments[55]
Identifiers[16]==The ambiguity resolution rules of Eli guarantee that every character sequence satisfying this definition will be initially classified as an identifier, and that the token processor IdnOrType will be invoked after the character sequence has been recognized. IdnOrType may then re-classify the sequence if that is appropriate.This macro is invoked in definition 15.identifier: $[_a-zA-Z][_a-zA-Z0-9]* [IdnOrType] Type definitions[168] Additional terminal symbols representing identifiers[205]
A label name is the only kind of identifier that has function scope. It can be used (in a goto statement) anywhere in the function in which it appears, and is declared implicitly by its syntactic appearance followed by a :. Label names shall be unique within a function.
An instantiation of Eli's Unique module is used to verify that label names must be unique within a function.
Name analysis modules for label identifiers[17]==The Unique module exports two symbols: LabelUnique marks the nodes representing the occurrences of the identifiers to be tested for uniqueness, while LabelRangeUnique marks the subtree containing all of those nodes.This macro is invoked in definition 10.$/Prop/Unique.gnrc +instance=Label +referto=Label :inst
Function scope[18]==Every other identifier has a scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit.This macro is invoked in definition 4.SYMBOL file INHERITS LabelRootScope, LabelRangeUnique END; SYMBOL function_definition INHERITS LabelRangeScope END; RULE: jump_statement ::= 'goto' LabelUse ';' END; SYMBOL LabelUse INHERITS LabelIdUseEnv COMPUTE IF(EQ(THIS.LabelKey,NoKey), message(ERROR, "Label identifier is not defined", 0, COORDREF)); END; RULE: labeled_statement ::= LabelDef ':' statement END; SYMBOL LabelDef INHERITS LabelIdDefScope, LabelUnique COMPUTE IF(NOT(THIS.LabelUnique), message(ERROR, "Label identifier is multiply defined", 0, COORDREF)); END;
File scope[19]==If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the } that closes the associated block.This macro is invoked in definition 4.SYMBOL file INHERITS TagRootScope END;
Block scope[20]==In a function_definition, the declaration_list_opt and compound_statement are parts of the same scope. If a prototype is given for the function, that prototype is also part of the scope.This macro is invoked in definition 4.SYMBOL declaration_list_opt INHERITS TagRangeScope END; SYMBOL compound_statement INHERITS TagRangeScope END; ATTR TagEnv: Environment; RULE: function_definition ::= declaration_specifiers declarator declaration_list_opt compound_statement COMPUTE Block scope tag environment for a function definition[21] END; RULE: function_definition ::= declarator declaration_list_opt compound_statement COMPUTE Block scope tag environment for a function definition[21] END;
Block scope tag environment for a function definition[21]==A parameter_part phrase may contain nested parameter_part phrases, which could not be the prototype of the function being called. Thus the CONSTITUENTS process must be prevented from examining components of parameter_part phrases. On the other hand, it must examine nested declarator phrases because the function and its prototype may be enclosed in parentheses. The SHIELD clause has this effect, and also prevents the examination of array size specifications (which cannot contain the function's prototype).This macro is invoked in definition 20..TagEnv= declarator CONSTITUENTS parameter_part.TagEnv SHIELD (parameter_part, constant_exp_opt) WITH (Environment, Leftmost, IDENTICAL, NOENV); declaration_list_opt.TagEnv=IF(EQ(.TagEnv, NoEnv), NewEnv(), .TagEnv); compound_statement.TagEnv=declaration_list_opt.TagEnv;
Even at the top level, however, a declarator may contain many parameter_part phrases. The one defining the parameters of the function is textually the leftmost, so the WITH clause uses Leftmost to choose the leftmost non-null environment.
Computations for obtaining the tag environment from a declarator[22]==If the declarator or type specifier that declares the identifier appears within the list of parameter declarations in a function prototype (not part of a function definition), the identifier has function prototype scope, which terminates at the end of the function declarator.This macro is invoked in definition 11.#define Leftmost(x,y) ((x)==NoEnv?(y):(x)) #define NOENV() NoEnv
Function prototype scope[23]==If an outer declaration of a lexically identical identifier exists in the same name space, it is hidden until the current scope terminates, after which it again becomes visible.This macro is invoked in definition 4.SYMBOL parameter_part INHERITS TagRangeScope END;
Two identifiers have the same scope if and only if their scopes terminate at the same point.
Structure, union and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag.
Tag scope[24]==Each enumeration constant has scope that begins just after the appearance of the defining enumerator in an enumerator_list.This macro is invoked in definition 4.SYMBOL TagDef INHERITS TagIdDefScope END; SYMBOL TagUse INHERITS TagIdUseEnv END;
enumerator[25]==Any other identifier has scope that begins just after the completion of its declarator.This macro is invoked in definition 142.enumerator Carry out a deferred binding[223]
Innermost declarator[26]==A typedef_name is an ordinary identifier, declared by a declaration containing the storage_class_specifier ``typedef''. The scopes of all ordinary identifiers must therefore be determined during parsing in order to support IdnOrType in its task of classifying character sequences recognized as identifier. Only in this way is it possible to decide whether a particular use of an ordinary identifier should be interpreted as a typedef_name.This macro is invoked in definition 153.direct_declarator Carry out a deferred binding[223]
Name spaces of identifiers[27]==This macro is invoked in definition 10.$/Name/AlgScope.gnrc +instance=Label +referto=Label :inst $/Name/CScope.gnrc +instance=Tag +referto=Tag :inst $/Name/CScope.gnrc +instance=Member +referto=Member :inst Ordinary identifier name space[181]
Disambiguation of member names[28]==Ordinary identifiers must be renamed during parsing in order to avoid an ambiguity in the grammar. That process does not meet the preconditions for using any of the Eli name analysis modules, and therefore must be handled with more primitive operations. The details are presented in a later chapter.This macro is invoked in definition 4.RULE: Expression ::= Expression '.' MemberIdUse END; RULE: Expression ::= Expression '->' MemberIdUse END;
component_list: [29]==This macro is invoked in definition 138.component_list: Begin a component_list[192] '{' struct_declaration_list End a component_list[193] '}' .
This section introduces the OIL identifiers used to represent basic C types, sets of types, and user-defined types. All of these identifiers begin with TypeIs_. Identifiers representing the basic types of C continue with one or more C keywords, all lower case, giving the canonic name of the type in the standard (e.g. TypeIs_char). Identifiers representing sets of types and user-defined types continue with a capitalized name. That name is the one used by the standard to describe the set of types or the derivation of the user-defined type wherever possible (e.g. TypeIs_Integral, TypeIs_Pointer).
Sets of types are specified in this section by OIL SET directives.
The standard provides mechanisms for a user to define additional types. Each of these mechanisms is specified in this section by an OIL CLASS.
Types[30]==A TypeIs_char object is large enough to store any member of the basic execution character set.This macro is invoked in definition 5.Signed integer types[31] Unsigned integer types[32] Floating types[33] Integral types[40] Arithmetic types[41] Scalar types[42] Promoted types[59] Structure types[36] Union types[37] Enumeration types[34] Function type derivation[38] Array type derivation[35] Pointer type derivation[39]
There are four signed integer types:
Signed integer types[31]==For each of the signed integer types, there is a corresponding (but different) unsigned integer type that uses the same amount of storage (including sign information) and has the same alignment requirements:This macro is invoked in definition 30.SET TypeIs_Signed_Integer= [TypeIs_signed_char, TypeIs_short, TypeIs_int, TypeIs_long];
Unsigned integer types[32]==There are three floating types:This macro is invoked in definition 30.SET TypeIs_Unsigned_Integer= [TypeIs_unsigned_char, TypeIs_unsigned_short, TypeIs_unsigned_int, TypeIs_unsigned_long];
Floating types[33]==TypeIs_char, the signed and unsigned integer types, and the floating types are collectively called the basic types. Even if the implementation defines two or more basic types to have the same representation, they are nevertheless different types.This macro is invoked in definition 30.SET TypeIs_Floating= [TypeIs_float, TypeIs_double, TypeIs_long_double];
An enumeration comprises a set of named integer constant values. Each distinct enumeration constitutes a different enumerated type.
Enumeration types[34]==TypeIs_void comprises an empty set of values; it is an incomplete type that cannot be completed.This macro is invoked in definition 30.CLASS TypeIs_Enum() BEGIN Enumeration conversion[58] Operator defined for this enumeration type[122] END;
Any number of derived types can be constructed from the object, function and incomplete types, as follows:
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. Array objects are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called ``array of T''. The construction of an array type from an element type is called ``array type derivation''.
Array type derivation[35]==A structure type describes a sequentially allocated nonempty set of member objects, each of which has an optionally specified name and possibly distinct type.This macro is invoked in definition 30.CLASS TypeIs_Array(elementType, pointerType) BEGIN Array conversion[62] Operators defined for this array type[73] END;
Structure types[36]==A union type describes an overlapping nonempty set of member objects, each of which has an optionally specified name and possibly distinct type.This macro is invoked in definition 30.CLASS TypeIs_Struct() BEGIN Operator defined for this struct type[120] END;
Union types[37]==A function type describes a function with a specified return type. A function type is characterized by its return type and the number and types of its parameters. A function type is said to be derived from its return type, and if its return type is T, the function type is sometimes called ``function returning T''. The construction of a function type from a return type is called ``function type derivation''.This macro is invoked in definition 30.CLASS TypeIs_Union() BEGIN Operator defined for this union type[121] END;
Function type derivation[38]==A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ``pointer to T''. The construction of a pointer type from a referenced type is called ``pointer type derivation''.This macro is invoked in definition 30.CLASS TypeIs_Function(returnType) BEGIN Operators defined for this function type[76] END;
Pointer type derivation[39]==These methods of constructing types can be applied recursively.This macro is invoked in definition 30.CLASS TypeIs_Pointer(referencedType) BEGIN Pointer[66] Discard pointer values[65] Null constant for this pointer type[68] Operators defined for this pointer type[74] END;
The standard specifies that the representations of integral objects shall define values by use of a pure binary numeration system:
Integral types[40]==Enumerated types are considered to be integral also, but an OIL set is a static object and therefore cannot contain a class as a member. Each enumerated type must therefore be individually described as integral, which is the effect of the integer promotions described below.This macro is invoked in definition 30.SET TypeIs_Integral= [TypeIs_char] + TypeIs_Signed_Integer + TypeIs_Unsigned_Integer;
Arithmetic objects are those that can participate in arithmetic operations:
Arithmetic types[41]==Scalar objects are those that can be compared with one another:This macro is invoked in definition 30.SET TypeIs_Arithmetic = TypeIs_Integral + TypeIs_Floating;
Scalar types[42]==Pointer types are considered to be scalar also, but an OIL set is a static object and therefore cannot contain a class as a member. Each pointer type must therefore be individually described as scalar, which is the effect of the pointer conversions described below.This macro is invoked in definition 30.SET TypeIs_Scalar = TypeIs_Arithmetic + [TypeIs_VoidPointer];
Constants[43]==This macro is invoked in definition 2.constant: floating_constant / integer_constant / character_constant .
Floating constants[44]==This macro is invoked in definition 15.floating_constant: $(F[45]E[46]?|D[47]+E[46])[flFL]? [mkidn]
F[45]==This macro is invoked in definition 44.(D[47]*\.D[47]+)
E[46]==This macro is invoked in definition 44.([eE][+-]?D[47]+)
D[47]==This macro is invoked in definitions 44, 45, 46, and 48.[0-9]
Integer constants[48]==This macro is invoked in definition 15.integer_constant: $([1-9]D[47]*|O[49]|H[50])([uU][lL]?|[lL][uU]?)? [c_mkint]
O[49]==This macro is invoked in definition 48.0[0-7]*
H[50]==This macro is invoked in definition 48.0[xX][0-9a-fA-F]+
Enumeration constants[51]==This macro is invoked in definition 2.enumeration_constant: OrdinaryIdDef Defer binding the declared identifier[222] .
Character constants[52]==This macro is invoked in definition 15.character_constant: C_CHAR_CONSTANT
String literals[53]==Sequences of string literals are translated as single strings. By defining such a sequence as a StringSeq, we allow the specification to use Eli's canned description of a single string literal.This macro is invoked in definition 15.string_literal: C_STRING_LIT
String sequence[54]==This macro is invoked in definition 2.StringSeq: string_literal / StringSeq string_literal .
Comments[55]==This macro is invoked in definition 15.C_COMMENT
Each implicit conversion is defined in this section by an OIL COERCION specification.
Implicit conversions[56]==The specifications in this section assume that objects of certain types are capable of representing all of the values of other types. Those assumptions are completely compatible with the standard, but may not hold for a specific implementation of C. If this type analysis module is being used in a translator, and the assumptions do not hold, then the specifications must be changed as indicated in the accompanying text.This macro is invoked in definition 5.Characters and integers[57] Usual arithmetic conversions[60] void[64] Conversions for null pointer constants[67]
Characters and integers[57]==This macro is invoked in definition 56.COERCION CChartoInt(TypeIs_char): TypeIs_int; COERCION CUnsignedChartoInt(TypeIs_unsigned_char): TypeIs_int; COERCION CShorttoInt(TypeIs_short): TypeIs_int; COERCION CUnsignedShorttoInt(TypeIs_unsigned_short): TypeIs_int;
Enumeration conversion[58]==It may be necessary to alter these definitions based upon the target machine if this module is to be used in a translator: If an int object cannot represent all values of the argument type, the result type for those conversions must be unsigned int.This macro is invoked in definition 34.COERCION CEnumtoInt(TypeIs_Enum): TypeIs_int;
Certain operators require that the integral promotion be performed on their operand(s), and the result has the promoted type. These operators are therefore defined in terms of sets that include only promoted integer types:
Promoted types[59]==This macro is invoked in definition 30.SET TypeIs_IntegralPromoted= [TypeIs_int, TypeIs_unsigned_int, TypeIs_long, TypeIs_unsigned_long]; SET TypeIs_ArithPromoted = TypeIs_IntegralPromoted + TypeIs_Floating;
Usual arithmetic conversions[60]==If both operands are integral, then integral promotions are performed on them. Then the following rules are applied:This macro is invoked in definition 56.COERCION CDoubletoLongDouble(TypeIs_double): TypeIs_long_double; COERCION CFloattoDouble(TypeIs_float): TypeIs_double; COERCION CUnsignedLongtoFloat(TypeIs_unsigned_long): TypeIs_float; Integer conversions[61]
Integer conversions[61]==It may be necessary to alter the definition of CUnsignedInttoLong based upon the target machine if this module is to be used in a translator: If a TypeIs_long object cannot represent all values of type TypeIs_unsigned_int the result type must be TypeIs_unsigned_long.This macro is invoked in definition 60.COERCION CLongtoUnsignedLong(TypeIs_long): TypeIs_unsigned_long; COERCION CUnsignedInttoLong(TypeIs_unsigned_int): TypeIs_long; COERCION CInttoLong(TypeIs_int): TypeIs_long; COERCION CInttoUnsignedInt(TypeIs_int): TypeIs_unsigned_int;
Array conversion[62]==Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type ``function returning type'' is converted to an expression that has type ``pointer to function returning type''.This macro is invoked in definition 35.COERCION CArraytoPtr (TypeIs_Array): pointerType;
Function conversion operator[63]==This macro is invoked in definition 9.CFunctoPtr;
void[64]==This macro is invoked in definition 56.COERCION CScalartoVoid(TypeIs_Scalar): TypeIs_void;
Discard pointer values[65]==This macro is invoked in definition 39.COERCION CPtrtoVoid(TypeIs_Pointer): TypeIs_void;
Pointer[66]==An integral constant expression with the value 0, or such an expression cast to TypeIs_VoidPointer, is called a null pointer constant. If a null pointer constant is assigned to or compared for equality to a pointer, the constant is converted to a pointer of that type. Such a pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function. A null pointer constant has TypeIs_NULL.This macro is invoked in definition 39.COERCION CVoidPtr(TypeIs_Pointer): TypeIs_VoidPointer;
Conversions for null pointer constants[67]==(The implicit conversion CNulltoIntegral is required to allow an integral constant expression with the value 0 to be interpreted as an integral value rather than a null pointer.)This macro is invoked in definition 56.COERCION CNulltoVoidPtr(TypeIs_NULL): TypeIs_VoidPointer; COERCION CNulltoIntegral(TypeIs_NULL): TypeIs_Integral;
Null constant for this pointer type[68]==This macro is invoked in definition 39.COERCION CNulltoPtr(TypeIs_NULL): TypeIs_Pointer;
Precedence and association are only interesting because they relate the structure of the program tree to the linear representation of the text. Once the tree has been built, the operands of an operator are reflected in the tree structure and there is no longer any need to distinguish different kinds of expression. Thus we define an equivalence class consisting of all of the symbols used by the standard to name expressions:
Expressions[69]==Any symbol in this equivalence class will be represented in the tree by a node with the name Expression, which is a new symbol not appearing anywhere in the grammar.This macro is invoked in definition 3.Expression ::= primary_expression postfix_expression unary_expression cast_expression multiplicative_expression additive_expression shift_expression relational_expression equality_expression AND_expression exclusive_OR_expression inclusive_OR_expression logical_AND_expression logical_OR_expression conditional_expression assignment_expression constant_expression expression expression_opt .
StringSeq replaces the symbol string_literal appearing in the standard's definition of a primary_expression. As discussed in Section 1.1.4 above, StringSeq embodies the semantic condition that a sequence of string literals is considered to be a single string literal in C.
Primary expressions[70]==This macro is invoked in definition 2.primary_expression: IdUse / constant / StringSeq / '(' expression ')' . IdUse: UnboundIdUse / OrdinaryIdUse .
Postfix operators[71]==This macro is invoked in definition 2.postfix_expression: primary_expression / postfix_expression '[' expression ']' / postfix_expression '(' argument_exp_list ')' / postfix_expression '(' ')' / postfix_expression '.' identifier / postfix_expression '->' identifier / postfix_expression '++' / postfix_expression '--' . argument_exp_list: assignment_expression / argument_exp_list ',' assignment_expression.
Array subscripting[72]==Distinct subscripting operations are defined for each array type and each pointer type other than TypeIs_VoidPointer. The second operand is specified to be a TypeIs_unsigned_long, although the standard specifies that it has integral type. Any integral type can be converted to TypeIs_unsigned_long by means of implicit conversions, so this specification is equivalent to that of the standard. The main reason for using TypeIs_unsigned_long is that OIL does not permit sets as operand specifications within a class definition, but a secondary reason is that this approach reduces the total number of operators in the compiler's database.This macro is invoked in definition 5.INDICATION Subscript_Indication: Subscript_Op, Array_Subscript_Op;
Operators defined for this array type[73]==This macro is defined in definitions 73 and 118.OPER Array_Subscript_Op(TypeIs_Array, TypeIs_unsigned_long): elementType;
This macro is invoked in definition 35.
Operators defined for this pointer type[74]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Subscript_Op(TypeIs_Pointer, TypeIs_unsigned_long): referencedType;
This macro is invoked in definition 39.
Function calls[75]==A distinct call operator is defined for each function type.This macro is invoked in definition 5.INDICATION Call_Indication: FunCall_Op;
Operators defined for this function type[76]==This macro is invoked in definition 38.OPER FunCall_Op(TypeIs_Function): returnType;
Postfix increment and decrement operators[77]==Distinct increment and decrement operators are defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION Increment_Indication: Increment_Op, Ptr_Inc_Op; INDICATION Decrement_Indication: Decrement_Op, Ptr_Dec_Op; OPER Increment_Op, Decrement_Op(TypeIs_Arithmetic): TypeIs_Arithmetic;
Operators defined for this pointer type[78]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Inc_Op, Ptr_Dec_Op(TypeIs_Pointer): TypeIs_Pointer;
This macro is invoked in definition 39.
Unary operators[79]==This macro is invoked in definition 2.unary_expression: postfix_expression / '++' unary_expression / '--' unary_expression / unary_operator cast_expression / 'sizeof' unary_expression / 'sizeof' '(' type_name ')'. unary_operator: '&' / '*' / '+' / '-' / '~' / '!'.
Address and indirection operators[80]==A distinct indirection operator is defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION Dereference_Indication: Ptr_Deref_Op; INDICATION Reference_Indication: Ptr_Ref_Op;
Operators defined for this pointer type[81]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Deref_Op(TypeIs_Pointer): referencedType; OPER Ptr_Ref_Op(referencedType): TypeIs_Pointer;
This macro is invoked in definition 39.
Unary arithmetic operators[82]==A distinct logical negation operator is defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION Plus_Indication: Plus_Op; INDICATION Minus_Indication: Minus_Op; INDICATION Bitwise_Not_Indication: Bitwise_Not_Op; INDICATION Not_Indication: Not_Op, Void_Ptr_Not_Op, Ptr_Not_Op; OPER Plus_Op, Minus_Op(TypeIs_ArithPromoted): TypeIs_ArithPromoted; OPER Bitwise_Not_Op(TypeIs_IntegralPromoted): TypeIs_IntegralPromoted; OPER Not_Op(TypeIs_Scalar): TypeIs_int; OPER Void_Ptr_Not_Op (TypeIs_VoidPointer): TypeIs_int;
Operators defined for this pointer type[83]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Not_Op (TypeIs_Pointer): TypeIs_int;
This macro is invoked in definition 39.
Cast operators[84]==This macro is invoked in definition 2.cast_expression: unary_expression / '(' type_name ')' cast_expression.
Cast operator semantics[85]==By defining TypeIs_CastResult as being equal to TypeIs_Scalar and then using these two set identifiers in defining Cast_Op, the specification defines a cast from every element of TypeIs_Scalar to every other element of TypeIs_Scalar. If Cast_Op were defined with the signature (TypeIs_Scalar): TypeIs_Scalar then the operand and result would be constrained to be identical.This macro is invoked in definition 5.INDICATION Cast_Indication: Cast_Op, Cast_IntegraltoPtr, Cast_VoidPtrtoPtr; SET TypeIs_CastResult = TypeIs_Scalar; OPER Cast_Op(TypeIs_Scalar): TypeIs_CastResult;
The definition of Cast_Op allows any pointer type to be cast to any integral type: There is an implicit conversion from any pointer type to TypeIs_VoidPointer, which is an element of TypeIs_Scalar, and every integral type is an element of TypeIs_CastResult.
Distinct cast operators are defined for each pointer type other than TypeIs_VoidPointer to handle casts from arbitrary integers and from TypeIs_VoidPointer to that pointer type. The operand of the former is specified to be a TypeIs_unsigned_long, although the standard specifies that it has integral type. Any integral type can be converted to TypeIs_unsigned_long by means of implicit conversions, so this specification is equivalent to that of the standard. The main reason for using TypeIs_unsigned_long is that OIL does not permit sets as operand specifications within a class definition, but a secondary reason is that this approach reduces the total number of operators in the compiler's database.
Operators defined for this pointer type[86]==The implicit conversion from any pointer type to TypeIs_VoidPointer, combined with Cast_VoidPtrtoPtr, allows any pointer type to be cast to any other pointer type. (This includes pointers to function types.)This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Cast_IntegraltoPtr(TypeIs_unsigned_long): TypeIs_Pointer; OPER Cast_VoidPtrtoPtr(TypeIs_VoidPointer): TypeIs_Pointer;
This macro is invoked in definition 39.
Multiplicative operators[87]==This macro is invoked in definition 2.multiplicative_expression: cast_expression / multiplicative_expression '*' cast_expression / multiplicative_expression '/' cast_expression / multiplicative_expression '%' cast_expression .
Multiplicative operator semantics[88]==This macro is invoked in definition 5.INDICATION Multiplication_Indication: MulOp; INDICATION Division_Indication: DivOp; INDICATION Mod_Indication: ModOp; OPER MulOp, DivOp(TypeIs_Arithmetic, TypeIs_Arithmetic): TypeIs_Arithmetic; OPER ModOp(TypeIs_Integral, TypeIs_Integral): TypeIs_Integral;
Additive operators[89]==This macro is invoked in definition 2.additive_expression: multiplicative_expression / additive_expression '+' multiplicative_expression / additive_expression '-' multiplicative_expression .
Additive operator semantics[90]==Distinct additive operators are defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION Addition_Indication: AddOp, Void_Ptr_Add_Op, Void_Ptr_Rev_Add_Op, Ptr_Add_Op, Ptr_Rev_Add_Op; INDICATION Subtraction_Indication: SubOp, Void_Ptr_Sub_Op, Ptr_Sub_Op, Ptr_Ptr_Sub_Op; OPER AddOp, SubOp(TypeIs_Arithmetic, TypeIs_Arithmetic): TypeIs_Arithmetic; OPER Void_Ptr_Add_Op, Void_Ptr_Sub_Op(TypeIs_VoidPointer, TypeIs_unsigned_long): TypeIs_VoidPointer; OPER Void_Ptr_Rev_Add_Op(TypeIs_unsigned_long, TypeIs_VoidPointer): TypeIs_VoidPointer;
Operators defined for this pointer type[91]==The integral operand of an additive operator involving a pointer and an integer is specified to be a TypeIs_unsigned_long. Any integral type can be converted to TypeIs_unsigned_long by means of implicit conversions, so this specification is equivalent to that of the standard. The main reason for using TypeIs_unsigned_long is that OIL does not permit sets as operand specifications within a class definition, but a secondary reason is that this approach reduces the total number of operators in the compiler's database.This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Add_Op, Ptr_Sub_Op(TypeIs_Pointer, TypeIs_unsigned_long): TypeIs_Pointer; OPER Ptr_Rev_Add_Op, Ptr_Rev_Sub_Op(TypeIs_unsigned_long, TypeIs_Pointer): TypeIs_Pointer; OPER Ptr_Ptr_Sub_Op(TypeIs_Pointer, TypeIs_Pointer): TypeIs_unsigned_long;
This macro is invoked in definition 39.
Bitwise shift operators[92]==This macro is invoked in definition 2.shift_expression: additive_expression / shift_expression '<<' additive_expression / shift_expression '>>' additive_expression .
Bitwise shift operator semantics[93]==By defining TypeIs_ShiftCount as being equal to TypeIs_IntegralPromoted and then using these two set identifiers in defining the bitwise shift operators, the specification allows different types of operands for the shift count and the value being shifted. The type of the result is that of the promoted left operand.This macro is invoked in definition 5.INDICATION Bit_Shift_Left_Indication: Bit_Shift_Left_Op; INDICATION Bit_Shift_Right_Indication: Bit_Shift_Right_Op; SET TypeIs_ShiftCount = TypeIs_IntegralPromoted; OPER Bit_Shift_Right_Op, Bit_Shift_Left_Op (TypeIs_IntegralPromoted, TypeIs_ShiftCount): TypeIs_IntegralPromoted;
Relational operators[94]==This macro is invoked in definition 2.relational_expression: shift_expression / relational_expression '<' shift_expression / relational_expression '>' shift_expression / relational_expression '<=' shift_expression / relational_expression '>=' shift_expression .
Relational operator semantics[95]==Distinct relational operators are defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION LessThan_Indication: LessThan_Op, Ptr_LT_Op; INDICATION Greater_Indication: Greater_Op, Ptr_GT_Op; INDICATION LessThan_Equal_Indication: LessThan_Equal_Op, Ptr_LTE_Op; INDICATION Greater_Equal_Indication: Greater_Equal_Op, Ptr_GTE_Op; OPER Greater_Op, LessThan_Op, Greater_Equal_Op, LessThan_Equal_Op (TypeIs_Scalar, TypeIs_Scalar): TypeIs_int;
Operators defined for this pointer type[96]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_LT_Op, Ptr_GT_Op, Ptr_LTE_Op, Ptr_GTE_Op (TypeIs_Pointer, TypeIs_Pointer): TypeIs_int;
This macro is invoked in definition 39.
Equality operators[97]==This macro is invoked in definition 2.equality_expression: relational_expression / equality_expression '==' relational_expression / equality_expression '!=' relational_expression .
Equality operator semantics[98]==Distinct equality operators are defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION Equality_Indication: Equality_Op, Ptr_Eq_Op; INDICATION Not_Equal_Indication: Not_Equal_Op, Ptr_NEq_Op; OPER Equality_Op, Not_Equal_Op(TypeIs_Scalar, TypeIs_Scalar): TypeIs_int;
Operators defined for this pointer type[99]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Eq_Op, Ptr_NEq_Op(TypeIs_Pointer, TypeIs_Pointer): TypeIs_int;
This macro is invoked in definition 39.
Bitwise AND operator[100]==This macro is invoked in definition 2.AND_expression: equality_expression / AND_expression '&' equality_expression.
Bitwise AND operator semantics[101]==This macro is invoked in definition 5.INDICATION Bitwise_And_Indication: Bitwise_And_Op; OPER Bitwise_And_Op(TypeIs_Integral, TypeIs_Integral): TypeIs_Integral;
Bitwise exclusive OR operator[102]==This macro is invoked in definition 2.exclusive_OR_expression: AND_expression / exclusive_OR_expression '^' AND_expression.
Bitwise exclusive OR operator semantics[103]==This macro is invoked in definition 5.INDICATION Bitwise_XOr_Indication: Bitwise_XOr_Op; OPER Bitwise_XOr_Op(TypeIs_Integral, TypeIs_Integral): TypeIs_Integral;
Bitwise inclusive OR operator[104]==This macro is invoked in definition 2.inclusive_OR_expression: exclusive_OR_expression / inclusive_OR_expression '|' exclusive_OR_expression.
Bitwise inclusive OR operator semantics[105]==This macro is invoked in definition 5.INDICATION Bitwise_Or_Indication: Bitwise_Or_Op; OPER Bitwise_Or_Op(TypeIs_Integral, TypeIs_Integral): TypeIs_Integral;
Logical AND operator[106]==This macro is invoked in definition 2.logical_AND_expression: inclusive_OR_expression / logical_AND_expression '&&' inclusive_OR_expression.
Logical AND operator semantics[107]==Distinct logical AND operators are defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION And_Indication: And_Op, Ptr_And_Op; OPER And_Op(TypeIs_Scalar, TypeIs_Scalar): TypeIs_int;
Operators defined for this pointer type[108]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_And_Op(TypeIs_Pointer, TypeIs_Pointer): TypeIs_int;
This macro is invoked in definition 39.
Logical OR operator[109]==This macro is invoked in definition 2.logical_OR_expression: logical_AND_expression / logical_OR_expression '||' logical_AND_expression.
Logical OR operator semantics[110]==Distinct logical OR operators are defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION Or_Indication: Or_Op, Ptr_Or_Op; OPER Or_Op(TypeIs_Scalar, TypeIs_Scalar): TypeIs_int;
Operators defined for this pointer type[111]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Or_Op(TypeIs_Pointer, TypeIs_Pointer): TypeIs_int;
This macro is invoked in definition 39.
Conditional operator[112]==This macro is invoked in definition 2.conditional_expression: logical_OR_expression / logical_OR_expression '?' expression ':' conditional_expression .
Conditional operator semantics[113]==Distinct conditional operators are defined for each pointer type other than TypeIs_VoidPointer.This macro is invoked in definition 5.INDICATION Conditional_Indication: Conditional_Op, Ptr_Conditional_Op; OPER Conditional_Op(TypeIs_Scalar): TypeIs_int;
Operators defined for this pointer type[114]==This specification constrains only the first operand of the conditional. Temporarily, the specification will simply balance the second and third operands of the conditional to obtain the result type.This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Conditional_Op(TypeIs_Pointer): TypeIs_int;
This macro is invoked in definition 39.
Assignment operators[115]==An assignment operator is identified during semantic analysis in the same way as any other dyadic operator. It is therefore convenient to map the symbol assignment_operator to binary_operator in the tree:This macro is invoked in definition 2.assignment_expression: conditional_expression / unary_expression assignment_operator assignment_expression . assignment_operator: '=' / '*=' / '/=' / '%=' / '+=' / '-=' / '<<=' / '>>=' / '&=' / '^=' / '|='.
Map the assignment operator symbol[116]==This macro is invoked in definition 3.binary_operator ::= assignment_operator .
Simple assignment[117]==By defining TypeIs_RHS_Scalar as being equal to TypeIs_Scalar and then using these two set identifiers in defining Assign_Op, the specification allows different types of operands for the left and right operands. The type of the result is that of the left operand.This macro is invoked in definition 5.INDICATION Assign_Indication: Assign_Op, Ptr_Assign_Op, Enum_Assign_Op, Struct_Assign_Op, Union_Assign_Op, Ptr_Void_Assign_Op, Array_Assign_Op; SET TypeIs_RHS_Arithmetic = TypeIs_Arithmetic; OPER Assign_Op(TypeIs_Arithmetic, TypeIs_RHS_Arithmetic): TypeIs_Arithmetic;
Distinct simple assignments are defined for each array type.
Operators defined for this array type[118]==Distinct simple assignments are defined for each pointer type other than TypeIs_VoidPointer.This macro is defined in definitions 73 and 118.OPER Array_Assign_Op(TypeIs_Array, pointerType): TypeIs_Array;
This macro is invoked in definition 35.
Operators defined for this pointer type[119]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Assign_Op(TypeIs_Pointer, TypeIs_Pointer): TypeIs_Pointer; OPER Ptr_Void_Assign_Op(TypeIs_Pointer, TypeIs_VoidPointer): TypeIs_Pointer;
This macro is invoked in definition 39.
Operator defined for this struct type[120]==This macro is invoked in definition 36.OPER Struct_Assign_Op(TypeIs_Struct, TypeIs_Struct): TypeIs_Struct;
Operator defined for this union type[121]==This macro is invoked in definition 37.OPER Union_Assign_Op(TypeIs_Union, TypeIs_Union): TypeIs_Union;
Operator defined for this enumeration type[122]==This macro is invoked in definition 34.OPER Enum_Assign_Op(TypeIs_Enum, TypeIs_int): TypeIs_Enum;
Compound assignment[123]==Distinct compound assignments are defined for each pointer type other than TypeIs_VoidPointer. The integral operand of a compound assignment involving a pointer and an integer is specified to be a TypeIs_unsigned_long. Any integral type can be converted to TypeIs_unsigned_long by means of implicit conversions, so this specification is equivalent to that of the standard. The main reason for using TypeIs_unsigned_long is that OIL does not permit sets as operand specifications within a class definition, but a secondary reason is that this approach reduces the total number of operators in the compiler's database.This macro is invoked in definition 5.INDICATION Mult_Eq_Indication: Mult_Eq_Op; INDICATION Div_Eq_Indication: Div_Eq_Op; INDICATION Mod_Eq_Indication: Mod_Eq_Op; INDICATION Plus_Eq_Indication: Plus_Eq_Op, Ptr_Plus_Eq_Op; INDICATION Minus_Eq_Indication: Minus_Eq_Op, Ptr_Minus_Eq_Op; INDICATION Bitwise_Shift_Left_Eq_Indication: Bitwise_Shift_Left_Eq_Op; INDICATION Bitwise_Shift_Right_Eq_Indication: Bitwise_Shift_Right_Eq_Op; INDICATION Bitwise_And_Eq_Indication: Bitwise_And_Eq_Op; INDICATION Bitwise_XOr_Eq_Indication: Bitwise_XOr_Eq_Op; INDICATION Bitwise_Or_Eq_Indication: Bitwise_Or_Eq_Op; SET TypeIs_RHS_Integral = TypeIs_Integral; OPER Mult_Eq_Op, Div_Eq_Op, Plus_Eq_Op, Minus_Eq_Op ( TypeIs_Arithmetic, TypeIs_RHS_Arithmetic ) : TypeIs_Arithmetic; OPER Mod_Eq_Op, Bitwise_Shift_Left_Eq_Op, Bitwise_Shift_Right_Eq_Op, Bitwise_And_Eq_Op, Bitwise_XOr_Eq_Op, Bitwise_Or_Eq_Op ( TypeIs_Integral, TypeIs_RHS_Integral ) : TypeIs_Integral;
Operators defined for this pointer type[124]==This macro is defined in definitions 74, 78, 81, 83, 86, 91, 96, 99, 108, 111, 114, 119, and 124.OPER Ptr_Plus_Eq_Op(TypeIs_Pointer, TypeIs_unsigned_long): TypeIs_Pointer; OPER Ptr_Minus_Eq_Op(TypeIs_Pointer, TypeIs_unsigned_long): TypeIs_Pointer;
This macro is invoked in definition 39.
Comma operator[125]==This macro is invoked in definition 2.expression: assignment_expression / expression ',' assignment_expression .
Constant Expressions[126]==This macro is invoked in definition 2.constant_expression: conditional_expression .
Declarations[127]==If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and the same name space, except for tags as specified in 6.5.2.3. An instance of the Eli Unique module can be used to detect multiply defined identifiers.This macro is invoked in definition 2.declaration: declaration_specifiers init_declarator_list_opt ';' End of a declaration[216] . declaration_specifiers: [136] init_declarator_list: init_declarator / init_declarator_list ',' init_declarator . init_declarator: declarator / declarator '=' initializer . Storage-class specifiers[132] Type specifiers[134] Type qualifiers[151] Declarators[153] Type names[165] Initialization[169]
Name analysis module for ordinary identifiers[128]==This macro is invoked in definition 10.$/Prop/Unique.gnrc :inst
Semantics of declarations[129]==A declaration specifies the interpretation and attributes of a set of identifiers.This macro is defined in definitions 129, 130, and 131.SYMBOL file INHERITS RangeUnique END; RULE: declaration_specifiers LISTOF declaration_specifier END; RULE: init_declarator_list LISTOF init_declarator END;
This macro is invoked in definition 4.
declaration_specifiers consists of a sequence of specifiers that indicate the linkage, storage duration, and part of the type of the entities that the declarators denote. The type that they name is embodied in the TypeSpecified attribute of the declaration_specifiers symbol. Information gleaned from the declaration specifiers about the storage class and type qualifier is embodied in six integer attributes that have the value 1 if the corresponding specifier or qualifier was present and 0 otherwise:
Semantics of declarations[130]==The init_declarator_list_opt is a comma-separated sequence of declarators, each of which may have additional type information, or an initializer, or both. The declarators contain the identifiers (if any) being declared.This macro is defined in definitions 129, 130, and 131.SYMBOL declaration_specifiers: TypeSpecified: DefTableKey; ATTR IsTypedef, IsExtern, IsStatic, IsRegister, IsConst, IsVolatile: int;
This macro is invoked in definition 4.
Semantics of declarations[131]==The TypeSpecified attribute embodies the type information indicated by the specifiers, and TypeChain carries that information to each declarator in the list. Additional type information provided by a declarator modifies the value of TypeChain, so each init_declarator in the list must reset the value for its successors.This macro is defined in definitions 129, 130, and 131.SYMBOL declaration_specifiers: TypeSpecified: DefTableKey; CHAIN TypeChain: DefTableKey; RULE: declaration ::= declaration_specifiers init_declarator_list_opt ';' COMPUTE CHAINSTART init_declarator_list_opt.TypeChain= declaration_specifiers.TypeSpecified; init_declarator_list_opt.IsTypedef=declaration_specifiers.IsTypedef; END; SYMBOL init_declarator COMPUTE THIS.TypeChain=THIS.TypeChain DEPENDS_ON TAIL.TypeChain; END; RULE: init_declarator ::= declarator '=' initializer COMPUTE IF(INCLUDING init_declarator_list_opt.IsTypedef, message(ERROR,"Cannot assign values to types", 0, COORDREF)); END;
This macro is invoked in definition 4.
Storage-class specifiers[132]==This macro is invoked in definition 127.storage_class_specifier: 'typedef' A typedef storage class specifier has been accepted[217] / 'extern' / 'static' / 'auto' / 'register' .
Declaration_specifier equivalence class[133]==This macro is defined in definitions 133, 135, and 152.declaration_specifier ::= storage_class_specifier .
This macro is invoked in definition 3.
The type_specifiers that must appear singly are therefore classified as type_specifier_1s, and those that may appear in groups as type_specifier_2s.
Type specifiers[134]==This macro is invoked in definition 127.type_specifier_1: 'void' / 'float' / struct_or_union_specifier / enum_specifier / typedef_name . type_specifier_2: 'char' / 'short' / 'int' / 'long' / 'double' / 'signed' / 'unsigned' . Structure and union specifiers[138] Enumeration specifiers[142]
Declaration_specifier equivalence class[135]==The phrase declaration_specifiers is then defined to enforce the constraint syntactically. All lists must be left-recursive here in order to detect the error at the proper symbol:This macro is defined in definitions 133, 135, and 152.declaration_specifier ::= type_specifier_1 type_specifier_2 .
This macro is invoked in definition 3.
declaration_specifiers: [136]==This macro is invoked in definition 127.declaration_specifiers: ds0 / ds1 / ds2. ds0: /* List without type specifiers */ storage_class_specifier / ds0 storage_class_specifier / type_qualifier / ds0 type_qualifier . ds1: /* List with a single type_specifier_1 */ type_specifier_1 / ds0 type_specifier_1 / ds1 storage_class_specifier / ds1 type_qualifier . ds2: /* List with one or more type_specifier_2's */ type_specifier_2 / ds0 type_specifier_2 / ds2 type_specifier_2 / ds2 storage_class_specifier / ds2 type_qualifier .
specifier_qualifier_list: [137]==This macro is invoked in definition 138.specifier_qualifier_list: sq0 / sq1 / sq2 . sq0: /* List without type specifiers */ type_qualifier / sq0 type_qualifier . sq1: /* List with a single type_specifier_1 */ type_specifier_1 / sq0 type_specifier_1 / sq1 type_qualifier . sq2: /* List with one or more type_specifier_2's */ type_specifier_2 / sq0 type_specifier_2 / sq2 type_specifier_2 / sq2 type_qualifier .
Structure and union specifiers[138]==A member_declarator must be distinguished from a declarator during parsing because the identifiers they declare belong to different name spaces, and those name spaces are treated differently as the program is parsed. A member_declarator_opt is semantically equivalent to a member_declarator:This macro is invoked in definition 134.struct_or_union_specifier: struct_or_union identifier component_list / struct_or_union component_list / struct_or_union identifier $';' . component_list: [29] struct_or_union: 'struct' / 'union' . struct_declaration_list: struct_declaration / struct_declaration_list struct_declaration. struct_declaration: specifier_qualifier_list struct_declarator_list ';'. specifier_qualifier_list: [137] struct_declarator_list: struct_declarator / struct_declarator_list ',' struct_declarator. struct_declarator: member_declarator / member_declarator_opt ':' constant_expression . Member declarators[160]
Member_declarator equivalence class[139]==A component_list defines the name space in which the members are defined. An instance of the Eli Unique module can be used to detect multiply defined members.This macro is invoked in definition 3.member_declarator ::= member_declarator_opt .
Name analysis modules for member identifiers[140]==The single name space is associated with the file phrase, and a separate environment is associated with each component_list phrase.This macro is invoked in definition 10.$/Prop/Unique.gnrc +instance=Member +referto=Member :inst $/Name/CScopeProp.gnrc +instance=Member +referto=Member :inst
Semantics of structure and union specifiers[141]==A MemberIdUse appears only as the right operand of a selection operator. The name space in which that member identifier was defined is the name space associated with the structure or union that is the left operand of that selection operator. Thus it is not possible to obtain a definition table key value at a MemberIdUse node until the analysis of expression types is complete.This macro is invoked in definition 4.SYMBOL file INHERITS MemberRootScope, MemberRangeUnique END; SYMBOL component_list INHERITS MemberRangeScope, MemberRangeScopeProp END; RULE: struct_declaration ::= declaration_specifiers struct_declarator_list ';' COMPUTE CHAINSTART struct_declarator_list.TypeChain= declaration_specifiers.TypeSpecified; END; SYMBOL struct_declarator_list COMPUTE THIS.TypeChain=THIS.TypeChain DEPENDS_ON TAIL.TypeChain; END; /* NOREPORTS SYMBOL struct_declarator COMPUTE THIS.TypeChain=THIS.TypeChain DEPENDS_ON TAIL.TypeChain; END; */ SYMBOL MemberIdDef INHERITS MemberIdDefScope, MemberUnique COMPUTE IF(NOT(THIS.MemberUnique), message(ERROR, "member identifier is multiply defined", 0, COORDREF)); END; SYMBOL MemberIdUse: Sym: int, MemberScope: Environment, MemberKey: DefTableKey; SYMBOL MemberIdUse COMPUTE SYNT.MemberKey=KeyInScope(THIS.MemberScope,THIS.Sym); IF(EQ(THIS.MemberScope,NoEnv),message(NOTE,"No environment",0,COORDREF)); IF(EQ(THIS.MemberKey, NoKey), message(ERROR, "Not a member of this structure or union", 0, COORDREF)); END;
Enumeration specifiers[142]==The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted. Thus, the identifiers of enumeration constants declared in the same scope shall all be distinct from each other and from other identifiers declared in ordinary declarators.This macro is invoked in definition 134.enum_specifier: 'enum' identifier Begin a list of enumeration constants[218] '{' enumerator_list End a list of enumeration constants[219] '}' / 'enum' Begin a list of enumeration constants[218] '{' enumerator_list End a list of enumeration constants[219] '}' / 'enum' identifier . enumerator_list: enumerator[25] / enumerator_list ',' enumerator[25] . enumerator: enumeration_constant / enumeration_constant '=' constant_expression.
Semantics of enumeration specifiers[143]==This macro is invoked in definition 4.SYMBOL enumeration_constant INHERITS Unique COMPUTE ResetType(THIS.Key, TypeIs_int); IF(NOT(THIS.Unique), message(ERROR, "identifier is multiply defined", 0, COORDREF)); END;
Tags[144]==If this declaration of the tag is visible, a subsequent declaration that uses the tag and that omits the bracketed list specifies the declared structure, union or enumerated type. Subsequent declarations in the same scope shall omit the bracketed list.This macro is invoked in definition 4.SYMBOL TagDef: HasCurly: int; RULE: struct_or_union_specifier ::= struct_or_union TagDef component_list COMPUTE TagDef.HasCurly=1; struct_or_union_specifier.Type= KeyForStructOrUnion(TagDef.TagKey,struct_or_union.IsStruct) DEPENDS_ON struct_or_union_specifier._C_GotTypes; component_list.MemberScopeKey=struct_or_union_specifier.Type; component_list._C_GotTypes=struct_or_union_specifier.Type; END; RULE: enum_specifier ::= 'enum' TagDef '{' enumerator_list '}' COMPUTE TagDef.HasCurly=1; enum_specifier.Type= KeyForEnum(TagDef.TagKey) DEPENDS_ON enum_specifier.Specification; END;
Check for multiply-declared tags[145]==This macro is invoked in definition 4.SYMBOL TagDef COMPUTE INH.HasCurly=0; THIS._C_TagGotKeys= IF(THIS.HasCurly,SetMultipleTag(THIS.TagKey,0,1)) DEPENDS_ON THIS._C_TagGotKeys; IF(AND(THIS.HasCurly,GetMultipleTag(THIS.TagKey,0)), message(ERROR,"Multiply-defined tag",0,COORDREF)) DEPENDS_ON INCLUDING file.TagGotKeys; END;
Property characterizing multiply-declared tags[146]==If a type specifier of the following form occurs prior to the declaration that defines the content, it declares a tag:This macro is invoked in definition 9.MultipleTag: int;
Tag that may or may not be a declaration[147]==A similar construction with enum does not exist and is not necessary as there can be no mutual dependencies between the declaration of an enumerated type and any other type.This macro is invoked in definition 4.RULE: struct_or_union_specifier ::= struct_or_union identifier COMPUTE .VisibleKey= KeyInEnv(INCLUDING TagAnyScope.TagEnv,identifier) DEPENDS_ON struct_or_union_specifier._C_TagGotKeys; .FinalKey= IF(NE(.VisibleKey,NoKey), .VisibleKey, DefineIdn(INCLUDING TagAnyScope.TagEnv,identifier)); struct_or_union_specifier._C_TagGotKeys=.FinalKey; struct_or_union_specifier.Type= KeyForStructOrUnion(.FinalKey,struct_or_union.IsStruct) DEPENDS_ON struct_or_union_specifier._C_GotTypes; struct_or_union_specifier._C_GotTypes=struct_or_union_specifier.Type; END; ATTR VisibleKey, FinalKey: DefTableKey;
Use of an enumerated type tag[148]==A declaration of the following form specifies a structure or union type and declares a tag, both of which are visible only within the scope in which the declaration occurs:This macro is invoked in definition 4.RULE: enum_specifier ::= 'enum' TagUse COMPUTE enum_specifier.Type= GetType(TagUse.TagKey, NoKey) DEPENDS_ON enum_specifier.Specification; END; SYMBOL TagUse COMPUTE IF(EQ(THIS.TagKey, NoKey), message(ERROR, "Identifier is not defined", 0, COORDREF)); END;
Forward definition of a tag[149]==A type specifier of the following form specifies a new structure, union or enumerated type, within the translation unit, that can only be referred to by the declaration of which it is a part.This macro is invoked in definition 4.RULE: declaration ::= struct_or_union TagDef ';' COMPUTE declaration._C_GotTypes= KeyForStructOrUnion(TagDef.TagKey,struct_or_union.IsStruct) DEPENDS_ON declaration._C_GotTypes; END;
Anonymous structure, union or enumerated type[150]==This macro is invoked in definition 4.RULE: struct_or_union_specifier ::= struct_or_union component_list COMPUTE struct_or_union_specifier.Type= KeyForStructOrUnion(NoKey,struct_or_union.IsStruct) DEPENDS_ON struct_or_union_specifier._C_GotTypes; component_list.MemberScopeKey=struct_or_union_specifier.Type; component_list._C_GotTypes=struct_or_union_specifier.Type; END; RULE: enum_specifier ::= 'enum' '{' enumerator_list '}' COMPUTE enum_specifier.Type= KeyForEnum(NoKey) DEPENDS_ON enum_specifier.Specification; END;
Type qualifiers[151]==This macro is invoked in definition 127.type_qualifier: 'const' / 'volatile'.
Declaration_specifier equivalence class[152]==This macro is defined in definitions 133, 135, and 152.declaration_specifier ::= type_qualifier .
This macro is invoked in definition 3.
Declarators[153]==The standard uses an optional pointer. This option must be made explicit here in order to avoid an LALR(1) conflict.This macro is defined in definitions 153, 155, 156, and 158.declarator: pointer Innermost declarator[26] Pointer declarator[197] / Innermost declarator[26] / pointer shielded Pointer declarator[197] / shielded .
This macro is invoked in definition 127.
An ordinary identifier must be bound at the end of its declarator. If a declarator has another declarator as a component, then the identifier will be bound at the end of the component declarator and no binding should take place at the end of the outer declarator. A new nonterminal, shielded, is used to distinguish these cases so that the the parser can take the proper action. This distinction is only relevant during parsing; semantically, shielded is completely equivalent to direct_declarator:
Direct_declarator equivalence class[154]==OrdinaryIdDef is a defining occurrence of an ordinary identifier. The kind of identifier being defined depends upon the context in which the declarator appears.This macro is invoked in definition 3.direct_declarator ::= shielded .
Declarators[155]==The symbol parameter_part represents a significant semantic concept, the function prototype scope for tags. This phrase is not distinguished in the standard, making the corresponding semantics difficult to express.This macro is defined in definitions 153, 155, 156, and 158.direct_declarator: OrdinaryIdDef Defer binding the declared identifier[222] / direct_declarator Array declarator[196] '[' constant_exp_opt ']' / direct_declarator parameter_part . shielded: '(' declarator ')' / shielded Array declarator[196] '[' constant_exp_opt ']' / shielded parameter_part .
This macro is invoked in definition 127.
Declarators[156]==The symbol parameters is introduced to simplify attachment of parsing actions, but it is semantically equivalent to a parameter_part:This macro is defined in definitions 153, 155, 156, and 158.parameter_part: Prototype begin[186] '(' Begin a parameter list[198] parameters Prototype end[187] ')' . parameters: Begin a parameter_type_list[194] parameter_type_list End a parameter_type_list[195] / identifier_list_opt .
This macro is invoked in definition 127.
Parameter_part equivalence class[157]==This macro is invoked in definition 3.parameter_part ::= parameters .
Declarators[158]==This macro is defined in definitions 153, 155, 156, and 158.pointer: '*' type_qualifier_list_opt / '*' type_qualifier_list_opt pointer . type_qualifier_list_opt: type_qualifier* . parameter_type_list: parameter_list / parameter_list ',' '...' . parameter_list: parameter_declaration / parameter_list ',' parameter_declaration. parameter_declaration: declaration_specifiers declarator / declaration_specifiers abstract_declarator_opt . identifier_list: OrdinaryIdDef Bind the identifier immediately[224] / identifier_list ',' OrdinaryIdDef Bind the identifier immediately[224] .
This macro is invoked in definition 127.
Semantics of declarators[159]==There is little difference between the phrase structure of a member_declarator and that of a declarator. The former is defined to preserve the context in which a declarator occurs, so that different actions can be attached in the two cases. A declarator declares an ordinary identifier, which must be consistently renamed during parsing, while a member_declarator declares a member identifier, which requires no action during parsing.This macro is invoked in definition 4.RULE: direct_declarator ::= IdDef COMPUTE direct_declarator._C_GotTypes= ORDER( ResetType(IdDef.Key, direct_declarator.TypeChain), IF(NE(GetSynCode(IdDef.Key,UnboundIdUse),typedef_name), Can be the operand of &[162] (`direct_declarator.TypeChain')), direct_declarator._C_GotTypes); END; RULE: member_direct_declarator ::= MemberIdDef COMPUTE member_direct_declarator._C_GotTypes= ORDER( Can be the operand of &[162] (`member_direct_declarator.TypeChain'), ResetType(MemberIdDef.MemberKey,member_direct_declarator.TypeChain), member_direct_declarator._C_GotTypes); END; SYMBOL parameter_id COMPUTE THIS.TypeChain=ORDER(ResetType(THIS.Key, TypeIs_int),THIS.TypeChain); END; RULE: parameter_declaration ::= declaration_specifiers declarator COMPUTE CHAINSTART declarator.TypeChain= declaration_specifiers.TypeSpecified; END; RULE: parameter_declaration ::= declaration_specifiers abstract_declarator COMPUTE CHAINSTART abstract_declarator.TypeChain= declaration_specifiers.TypeSpecified; parameter_declaration._C_GotTypes=abstract_declarator.TypeChain; END;
Member declarators[160]==Section 6.5.4.3 of the standard requires that an identifier list in a function declarator that is not part of a function definition be empty. Since a member_declarator cannot be a part of a function definition, there is no need for a non-empty identifier list alternative.This macro is invoked in definition 138.member_declarator: pointer member_direct_declarator / member_direct_declarator . member_direct_declarator: identifier / '(' member_declarator ')' / member_direct_declarator '[' constant_exp_opt ']' / member_direct_declarator parameter_part .
Pointer declarators[161]==The concrete syntax restricts the declaration_specifiers to be either empty or consist solely of type qualifiers. KeyForQualifier accounts for any qualifiers that might be present.This macro is invoked in definition 4.RULE: pointer ::= '*' declaration_specifiers COMPUTE pointer.TypeChain= KeyForQualifier( KeyForPointer(pointer.TypeChain), declaration_specifiers.IsConst, declaration_specifiers.IsVolatile); END; RULE: pointer ::= '*' declaration_specifiers pointer COMPUTE pointer[2].TypeChain= KeyForQualifier( KeyForPointer(pointer[1].TypeChain), declaration_specifiers.IsConst, declaration_specifiers.IsVolatile); END;
Pointer types also have to be guaranteed whenever an object that could be the operand of & is declared. The reason is that ``referencing'' operators are defined for each pointer type, so the type must be instantiated before & can be identified.
Can be the operand of &[162](¶1)==This macro is invoked in definition 159.KeyForPointer(¶1)
Array declarators[163]==This macro is invoked in definition 4.RULE: direct_declarator ::= direct_declarator '[' constant_exp_opt ']' COMPUTE direct_declarator[2].TypeChain=KeyForArray(direct_declarator[1].TypeChain); END; RULE: member_direct_declarator ::= member_direct_declarator '[' constant_exp_opt ']' COMPUTE member_direct_declarator[2].TypeChain= KeyForArray(member_direct_declarator[1].TypeChain); END; RULE: direct_abs_declarator ::= '[' constant_exp_opt ']' COMPUTE direct_abs_declarator.TypeChain=KeyForArray(direct_abs_declarator.TypeChain); END; RULE: direct_abs_declarator ::= direct_abs_declarator '[' constant_exp_opt ']' COMPUTE direct_abs_declarator[2].TypeChain= KeyForArray(direct_abs_declarator[1].TypeChain); END;
Function declarators (including prototypes)[164]==This macro is invoked in definition 4.RULE: direct_declarator ::= direct_declarator parameter_part COMPUTE direct_declarator[2].TypeChain= KeyForFunction(direct_declarator[1].TypeChain); END; RULE: member_direct_declarator ::= member_direct_declarator parameter_part COMPUTE member_direct_declarator[2].TypeChain= KeyForFunction(member_direct_declarator[1].TypeChain); END; RULE: direct_abs_declarator ::= '(' parameter_type_list_opt ')' COMPUTE direct_abs_declarator.TypeChain= KeyForFunction(direct_abs_declarator.TypeChain); END; RULE: direct_abs_declarator ::= direct_abs_declarator '(' parameter_type_list_opt ')' COMPUTE direct_abs_declarator[2].TypeChain= KeyForFunction(direct_abs_declarator[1].TypeChain); END;
Type names[165]==An abstract_declarator_opt is sematically equivalent to an abstract_declarator:This macro is invoked in definition 127.type_name: specifier_qualifier_list abstract_declarator_opt . abstract_declarator: pointer / pointer direct_abs_declarator / direct_abs_declarator . direct_abs_declarator: '(' abstract_declarator ')' / direct_abs_declarator '[' constant_exp_opt ']' / direct_abs_declarator '(' parameter_type_list_opt ')' / '[' constant_exp_opt ']' / '(' parameter_type_list_opt ')' .
Abstract_declarator equivalence class[166]==This macro is invoked in definition 3.abstract_declarator ::= abstract_declarator_opt . declaration_specifiers ::= type_qualifier_list_opt specifier_qualifier_list .
Semantics of type names[167]==This macro is invoked in definition 4.RULE: type_name ::= declaration_specifiers abstract_declarator COMPUTE CHAINSTART abstract_declarator.TypeChain= declaration_specifiers.TypeSpecified; type_name.Type=abstract_declarator.TypeChain; type_name._C_GotTypes=type_name.Type; END;
Type definitions[168]==Note that there is no lexical distinction between a typedef_name and an identifier. Thus semantic information must be used to differentiate them, and the differentiation must occur during parsing.This macro is invoked in definition 16.typedef_name: $[_a-zA-Z][_a-zA-Z0-9]*
Initialization[169]==This macro is invoked in definition 127.initializer: assignment_expression / '{' initializer_list '}' / '{' initializer_list ',' '}'. initializer_list: initializer / initializer_list ',' initializer.
Statements[170]==This macro is invoked in definition 2.statement: labeled_statement / Begin a nested compound statement[189] compound_statement / expression_statement / selection_statement / iteration_statement / jump_statement. Labeled statements[171] Compound statements[172] Expression statements[173] Selection statements[174] Iteration statements[175] Jump statements[176]
In the absence of parser information, the lexical analyzer will classify an identifier as an ordinary identifier (one of UnboundIdUse, OrdinaryIdUse or typedef_name depending on the context). Thus the parser must accept any of these classifications as a valid label.
Labeled statements[171]==This macro is invoked in definition 170.labeled_statement: UnboundIdUse ':' statement / OrdinaryIdUse ':' statement / typedef_name ':' statement / 'case' constant_expression ':' statement / 'default' ':' statement.
Compound statements[172]==This macro is invoked in definition 170.compound_statement: '{' declaration_list statement_list_opt End a compound statement[188] '}' / '{' statement_list_opt End a compound statement[188] '}' . declaration_list: declaration / declaration_list declaration . statement_list: statement / statement_list statement .
Expression statements[173]==This macro is invoked in definition 170.expression_statement: expression_opt ';' .
Selection statements[174]==This macro is invoked in definition 170.selection_statement: 'if' '(' expression ')' statement $'else' / 'if' '(' expression ')' statement 'else' statement / 'switch' '(' expression ')' statement.
Iteration statements[175]==This macro is invoked in definition 170.iteration_statement: 'while' '(' expression ')' statement / 'do' statement 'while' '(' expression ')' ';' / 'for' '(' for_init ';' for_test ';' for_incr ')' statement. for_init: / expression . for_test: / expression . for_incr: / expression .
Jump statements[176]==jump_statement: 'goto' identifier ';' / 'continue' ';' / 'break' ';