+determined by the immediately surrounding context -- usually some kind of
+bracket. The first such delimiter character which is not enclosed in
+brackets, braces or parentheses ends the fragment.
+
+%%%--------------------------------------------------------------------------
+\section{C types} \label{sec:syntax.type}
+
+Sod's syntax for C types closely mirrors the standard C syntax. A C type has
+two parts: a sequence of @<declaration-specifier>s and a @<declarator>. In
+Sod, a type must contain at least one @<declaration-specifier> (i.e.,
+`implicit @|int|' is forbidden), and storage-class specifiers are not
+recognized.
+
+
+\subsection{Declaration specifiers} \label{sec:syntax.type.declspec}
+
+\begin{grammar}
+<declaration-specifier> ::= <type-name>
+\alt "struct" <identifier> | "union" <identifier> | "enum" <identifier>
+\alt "void" | "char" | "int" | "float" | "double"
+\alt "short" | "long"
+\alt "signed" | "unsigned"
+\alt "bool" | "_Bool"
+\alt "imaginary" | "_Imaginary" | "complex" | "_Complex"
+\alt <qualifier>
+\alt <storage-specifier>
+\alt <atomic-type>
+\alt <other-declspec>
+
+<qualifier> ::= <atomic> | "const" | "volatile" | "restrict"
+
+<plain-type> ::= @<declaration-specifier>^+ <abstract-declarator>
+
+<atomic-type> ::= <atomic> "(" <plain-type> ")"
+
+<atomic> ::= "atomic" | "_Atomic"
+
+<storage-specifier> ::= <alignas> "(" <c-fragment> ")"
+
+<alignas> ::= "alignas" "_Alignas"
+
+<type-name> ::= <identifier>
+\end{grammar}
+
+Declaration specifiers may appear in any order. However, not all
+combinations are permitted. A declaration specifier must consist of zero or
+more @<qualifier>s, zero or more @<storage-specifier>s, and one of the
+following, up to reordering:
+\begin{itemize}
+\item @<type-name>;
+\item @<atomic-type>;
+\item @"struct" @<identifier>; @"union" @<identifier>; @"enum" @<identifier>;
+\item @"void";
+\item @"_Bool", @"bool";
+\item @"char"; @"unsigned char"; @"signed char";
+\item @"short", @"signed short", @"short int", @"signed short int";
+ @"unsigned short", @"unsigned short int";
+\item @"int", @"signed", @"signed int"; @"unsigned", @"unsigned int";
+\item @"long", @"signed long", @"long int", @"signed long int"; @"unsigned
+ long", @"unsigned long int";
+\item @"long long", @"signed long long", @"long long int", @"signed long long
+ int"; @"unsigned long long", @"unsigned long long int";
+\item @"float"; @"double"; @"long double";
+\item @"float _Imaginary", @"float imaginary"; @"double _Imaginary", @"double
+ imaginary"; @"long double _Imaginary", @"long double imaginary";
+\item @"float _Complex", @"float complex"; @"double _Complex", @"double
+ complex"; @"long double _Complex", @"long double complex".
+\end{itemize}
+All of these have their usual C meanings. Groups separated by commas mean
+the same thing, and Sod will not preserve the distinction.
+
+Almost all of these mean the same as they do in C. There are some minor
+differences:
+\begin{itemize}
+\item In C, the `tag' namespace is shared between @|struct|, @|union|, and
+ @|enum|; Sod has three distinct namespaces for tags. This may be fixed in
+ the future.
+\item The @<other-declspec> production is a syntactic extension point, where
+ extensions can introduce their own additions to the type system.
+\end{itemize}
+
+C standards from C99 onwards have tended to introduce new keywords beginning
+with an underscore followed by an uppercase letter, so as to avoid conflicts
+with existing code. More conventional spellings are then provided by macros
+in new header files. For example, C99 introduced @"_Bool", and a header file
+@|<stdbool.h>| which defines the macro @|bool|. Sod recognizes both the ugly
+underscore names and the more conventional macro names on input, but always
+emits the ugly names. This doesn't cause a compatibility problem in Sod,
+because Sod's parser recognizes keywords only in the appropriate context.
+For example, the (ill-advised) slot declaration
+\begin{prog}
+ bool bool;
+\end{prog}
+is completely acceptable, and will cause the C structure member
+\begin{prog}
+ \_Bool bool;
+\end{prog}
+to be emitted on output, which will be acceptable to C as long as
+@|<stdbool.h>| is not included.
+
+A @<type-name> is an identifier which has been declared as being a type name,
+using the @"typename" or @"class" definitions. The following type names are
+defined in the built-in module.
+\begin{itemize}
+\item @|va_list|
+\item @|size_t|
+\item @|ptrdiff_t|
+\item @|wchar_t|
+\end{itemize}
+
+
+\subsection{Declarators} \label{sec:syntax.type.declarator}
+
+\begin{grammar}
+<declarator>$[k, a]$ ::= @<pointer>^* <primary-declarator>$[k, a]$
+
+<primary-declarator>$[k, a]$ ::= $k$
+\alt "(" <primary-declarator>$[k, a]$ ")"
+\alt <primary-declarator>$[k, a]$ @<declarator-suffix>$[a]$
+
+<pointer> ::= "*" @<qualifier>^*
+
+<declarator-suffix>$[a]$ ::= "[" <c-fragment> "]"
+\alt "(" $a$ ")"
+
+<argument-list> ::= $\epsilon$ | "\dots"
+\alt <list>$[\mbox{@<argument>}]$ @["," "\dots"@]
+
+<argument> ::= @<declaration-specifier>^+ <argument-declarator>
+
+<abstract-declarator> ::= <declarator>$[\epsilon, \mbox{@<argument-list>}]$
+
+<argument-declarator> ::=
+ <declarator>$[\mbox{@<identifier> @! $\epsilon$}, \mbox{@<argument-list>}]$
+
+<simple-declarator> ::=
+ <declarator>$[\mbox{@<identifier>}, \mbox{@<argument-list>}]$
+\end{grammar}
+
+The declarator syntax is taken from C, but with some differences.
+\begin{itemize}
+\item Array dimensions are uninterpreted @<c-fragments>, terminated by a
+ closing square bracket. This allows array dimensions to contain arbitrary
+ constant expressions.
+\item A declarator may have either a single @<identifier> at its centre or a
+ pair of @<identifier>s separated by a @`.'; this is used to refer to
+ slots or messages defined in superclasses.
+\end{itemize}
+The remaining differences are (I hope) a matter of presentation rather than
+substance.
+
+There is additional syntax to support messages and methods which accept
+keyword arguments.
+
+\begin{grammar}
+<keyword-argument> ::= <argument> @["=" <c-fragment>@]
+
+<keyword-argument-list> ::=
+ @[<list>$[\mbox{@<argument>}]$@]
+ "?" @[<list>$[\mbox{@<keyword-argument>}]$@]
+
+<method-argument-list> ::= <argument-list> @! <keyword-argument-list>
+
+<dotted-name> ::= <identifier> "." <identifier>
+
+<keyword-declarator>$[k]$ ::=
+ <declarator>$[k, \mbox{@<method-argument-list>}]$
+\end{grammar}
+
+%%%--------------------------------------------------------------------------
+\section{Properties} \label{sec:syntax.prop}
+
+\begin{grammar}
+<properties> ::= "[" <list>$[\mbox{@<property>}]$ "]"
+
+<property> ::= <identifier> "=" <expression>
+
+<expression> ::= <additive>
+
+<additive> ::= <term>
+ | <additive> "+" <term>
+ | <additive> "--" <term>
+
+<term> ::= <factor>
+ | <term> "*" <factor>
+ | <term> "/" <factor>
+
+<factor> ::= <primary>
+ | "!" <factor> | "~" factor
+ | "+" <factor> | "--" <factor>
+
+<primary> ::=
+ <integer-literal> | <string-literal> | <char-literal> | <identifier>
+\alt "<" <plain-type> ">" | "{" <c-fragment> "}" | "?" <s-expression>
+ | "(" <expression> ")"
+\end{grammar}
+
+\emph{Property sets} are a means for associating miscellaneous information
+with compile-time metaobjects such as modules, classes, messages, methods,
+slots, and initializers. By using property sets, additional information can
+be passed to extensions without the need to introduce idiosyncratic syntax.
+(That said, extensions can add additional first-class syntax, if necessary.)
+
+An error is reported if an unrecognized property is associated with an
+object.
+
+
+\subsection{Property values} \label{sec:syntax.prop.value}
+
+A property has a name, given as an @<identifier>, and a value computed by
+evaluating an @<expression>. The value can be one of a number of types.
+
+\begin{itemize}
+
+\item An @<integer-literal> denotes a value of type @|int|.
+
+\item Similarly @<string-literal> and @<char-literal> denote @|string| and
+ @|char| values respectively. Note that, as properties, characters are
+ quite distinct from integers, whereas in C, a character literal denotes a
+ value of type @|int|.
+
+\item There are no variables in the property-value syntax. Rather, an
+ @<identifier> denotes that identifier, as a value of type @|id|.
+
+\item A C type (a @<plain-type>, as described in \xref{sec:syntax.type})
+ between angle brackets, e.g., @|<int>|, or @|<char *>|, or @|<void (*(int,
+ void (*)(int)))(int)>|, denotes that C type, as a value of type @|type|.
+
+\item A @<c-fragment> within braces denotes the tokens between (and not
+ including) the braces, as a value of type @|c-fragment|.
+
+\end{itemize}
+
+As shown in the grammar, there are four binary operators, @"+" (addition),
+@"--" (subtraction), @"*" (multiplication), and @"/" (division);
+multiplication and division have higher precedence than addition and
+subtraction, and operators of the same precedence associate left-to-right.
+There are also unary @"+" (no effect) and @"--" (negation) operators, with
+higher precedence. All of the above operators act only on integer operands
+and yield integer results. (Although the unary @"+" operator yields its
+operand unchanged, an error is still reported if it is applied to a
+non-integer value.) There are currently no bitwise, logical, or comparison
+operators.
+
+Finally, an S-expression preceded by @|?| causes the expression to be read in
+the current package (which is always @|sod-user| at the start of a module)
+and immediately evaluated (using @|eval|); the resulting value is converted
+into a property value using the \descref{gf}{decode-property}[generic
+function].
+
+
+\subsection{Property output types and coercions}
+\label{sec:syntax.prop.coerce}
+
+When a property value is inspected by the Sod translator, or an extension, it
+is \emph{coerced} so as to conform to a requested output type. This coercion
+process is performed by the \descref{gf}{coerce-property-value}[generic
+function], and additional output types and coercions can be defined by
+extensions. The built-in output types coercions, from the value types listed
+above, are as follows.
+
+\begin{itemize}
+
+\item The output types @|int|, @|string|, @|char|, @|id|, and @|c-fragment|
+ correspond to the like-named value types described above. No coercions to
+ these output types are defined for the described value types.\footnote{%
+ There is a coercion to @|id| from the value type @|symbol|, but it is
+ only possible to generate a property value of type @|symbol| using Lisp.}
+
+\item The output type @|type| denotes a C type, as does the value type
+ @|type|. In addition, a value of type @|id| can be coerced to a C type if
+ it is the name of a class, a type name explicitly declared by @|typename|,
+ or it is one of: @|bool|, @|_Bool|, @|void|, @|char|, @|short|, @|int|,
+ @|signed|, @|unsigned|, @|long|, @|size_t|, @|ptrdiff_t|, @|wchar_t|,
+ or @|va_list|.
+
+\item The @|boolean| output type denotes a boolean value, which may be either
+ true or false. A value of type @|id| is considered true if it is @|true|,
+ @|t|, @|yes|, @|on|, @|yup|, or @|verily|; or false if it is @|false|,
+ @|nil|, @|no|, @|off|, @|nope|, or @|nowise|; it is erroneous to provide
+ any other identifier where a boolean value is wanted. A value of type
+ @|int| is considered true if it is nonzero, or false if it is zero.
+
+\item The @|symbol| output type denotes a Lisp symbol.
+
+ A value of type @|id| is coerced to a symbol as follows. First, the
+ identifier name is subjected to \emph{case inversion}: if all of the
+ letters in the name have the same case, either upper or lower, then they
+ are replaced with the corresponding letters in the opposite case, lower or
+ upper; if the name contains letters of both cases, then it is not changed.
+ For example, @|foo45| becomes @|FOO45|, or \emph{vice-versa}; but @|Splat|
+ remains as it is. Second, the name is subjected to \emph{separator
+ switching}: all underscores in the name are replaced with hyphens (and
+ \emph{vice-versa}, though hyphens aren't permitted in identifiers in the
+ first place). Finally, the resulting name is interned in the current
+ package, which will usually be @|sod-user| unless changed explicitly by the
+ module.
+
+ A value of type @|string| is coerced to a symbol as follows. If the string
+ contains no colons, then it is case-inverted (but not separator-switched)
+ and interned in the current package. Otherwise, the string either has the
+ form $p @|:| q$, where $q$ does not begin with a colon (the
+ \emph{single-colon} case) or $p @|::| q$ (the \emph{double-colon} case);
+ where $p$ does not contain a colon. Both $p$ and $q$ are case-inverted
+ (but not separator-switched). If $p$ does not name a package, then an
+ error is reported; as a special case, if $p$ is empty, then it is
+ considered to name the @|keyword| package. Otherwise, $q$ is looked up as
+ a symbol name in package~$p$; in the single-colon case, if the symbol is
+ not an exported symbol in package~$p$, then an error is reported; in the
+ double-colon case, $q$ is interned in package~$p$ (and so there needn't be
+ an exported symbol -- or, indeed, and symbol at all -- named $q$
+ beforehand).
+
+\item The @|keyword| output type denotes symbols within the @|keyword|
+ package. Value of type @|id| or @|string| can be coerced to a @|keyword|
+ in the same way as to a @|symbol|, as described above, only the converted
+ name is looked up in the @|keyword| package rather than the current
+ package. (A @|string| can override this by specifying an explicit package
+ name, but this is unlikely to be very helpful.)
+
+\end{itemize}