Lexical syntax
SPL defines a set of rules to determine the syntax of a program.
SPL files are written in Unicode with UTF-8 encoding. Most syntactic elements, including keywords and identifiers, use the subset of Unicode that overlaps with ASCII characters (the subset 32-126 of the Latin-1 alphabet ISO 8859-1). Restricting identifiers to ASCII facilitates interoperability with native languages like C++ and with file systems. The only two constructs where other Unicode characters are valid are Unicode string literals and comments. Identifiers start with an ASCII letter or underscore, followed by ASCII letters, digits, or underscores. Identifiers of formal parameters of composite operators start with a dollar. The syntax for literal values of primitive types (numbers, Booleans, strings, and other types) is similar to that of Java™ or C++.
SPL has two forms of comments: single-line comments (from //
to
the end of the line) and delimited comments (between /*
and */
).
Delimited comments can span multiple lines, and can be followed by
regular code in the same line.
SPL syntax is not sensitive to indentation or line breaks. SPL
syntax is case-sensitive. For example, mud
and Mud
are
different identifiers.
An SPL keyword, such as if
or stream
,
cannot be used as an identifier. SPL uses lexical scoping for identifiers.
In other words, a declaration in an inner scope shadows declarations
of the same identifier in statically enclosing scopes. SPL allows
textual uses of function and stream names to precede their definition to
support recursive functions and cyclic stream graphs. SPL does not permit
synonymous entities of different categories in the same scope. For
example, the code f : for(;;) { f f = new f().f(); }
is
valid in Java™, even though
the same identifier refers to a label, a type, a variable, a constructor,
and a method. In SPL, however, it is a compile-time error if a program
declares both an operator that is named f
and a function
that is named f
in the same scope. As another example,
it is a compile-time error if a program declares both a type that
is named t
and a variable named t
in
the same scope. In other words, SPL does not segregate scopes by identifier
categories, unlike, for example Java™.
That also means that identifiers in inner scopes shadow identifiers
in outer scopes even when they are of a different category. For example,
a locally declared stream s
hides any function s
in
an outer scope. As seen later, namespaces and composite operators
provide not only a scope but also support disambiguation with qualified
names, and data that is hiding with private members.