Expression Reference |
Lexical Conventions
The language parser operates on a C++ istream with the locale set to the standard "C" locale. Spaces, tabs, and line endings (composed of cr, lf, or (cr, lf) ) are considered white space and are ignored, except as they separate tokens.
Lexical Grammar
simple_token = "+" | "-" | "*" | "/" | "%" | "?" | ":" | "=" | "!" | "{" | "}" | "<" | ">" | ";" | "@". compound_token = "&&" | "||" | "<=" | ">=" | "==" | "!=". string = quoted_string { quoted_string }. lead_comment = "/*" {character} "*/". trail_comment = "//" {character} eol. identifer = (letter | "_") {letter | "_" | digit}. keywords = "empty" | "true" | "false" | <extension>. number = digits ["e" ["+" | "-"]] digits. quoted_string = '"' {character} '"' | "'" {character} "'". digits = digit { digit }.
Comments
Comments are lexical tokens to facilitate the editing and subsequent formatting of the language in alternate representations. The trail_comment is terminated by any form of line ending.
Strings
Strings can be quoted either with single or double quotation marks. Adjacent strings are concatenated into a single string. There are no quote characters within a string. It is expected that the text within the string represents a higher-level representation (such as XML) which can provide additional mark-up.
Keywords
The empty
, true
, and false
keywords represent the associated values (the empty
value corresponds to adobe::empty_t). The list of keywords can be extended by dependent grammars.
Numbers:
Numbers are always 64 bit IEEE double precision values.
- Todo:
- (sparent) : Lexical conventions for hexadecimal constants may be added in the future.
Expressions
The expression syntax and semantics are designed to closely resemble the C language. Expressions are dynamically typed and there is no implicit type coercion between types.
Expression Grammar
expression = or_expression ["?" expression ":" expression]. or_expression = and_expression { "||" and_expression }. and_expression = equality_expression { "&&" equality_expression }. equality_expression = relational_expression { ("==" | "!=") relational_expression }. relational_expression = additive_expression { ("<" | ">" | "<=" | ">=") additive_expression }. additive_expression = multiplicative_expression { ("+" | "-") multiplicative_expression }. multiplicative_expression = unary_expression { ("*" | "/" | "%") unary_expression }. unary_expression = postfix_expression | (unary_operator unary_expression). unary_operator = "+" | "-" | "!". postfix_expression = primary_expression { ("[" expression "]") | ("." identifier) }. primary_expression = name | number | boolean | string | "empty" | array | dictionary | variable_or_fuction | ( "(" expression ")" ). variable_or_function = identifier ["(" [argument_expression_list] ")"]. array = "[" [argument_list] "]". dictionary = "{" named_argument_list "}". argument_expression_list = named_argument_list | argument_list. argument_list = expression { "," expression }. named_argument_list = named_argument { "," named_argument }. named_argument = identifier ":" expression. name = "@" identifier. boolean = "true" | "false".
Types
boolean
Values of type boolean
are either true
or false
.
name
A name is a literal identifier. Names are used as keys for dictionaries [see dictionary_t] and can be used as enumerations would be used in C.
number
Numbers are always 64 bit IEEE double precision values.
string
A value of type string
can be any sequence of non '\0' characters.
empty
A value of type empty
has only the single value of empty
.
array
An array
is a heterogeneous (any type, including arrays and dictionaries may be placed in an array) ordered sequence. Arrays support random access through the index operator. See [indexing]
dictionary
A dictionary
is a heterogeneous SortedAssociativeContainer that associates objects of type name
(the key) with objects of any type. It is also a UniqueAssociativeContainer, no two elements have the same key.
Operators
Index Operator
An array
or dictionary
may be indexed by an expression in square brackets. For an array
, the expression must evaluate to a number
, the floor of which will be used as a zero based integer index. For a dictionary
, the expression must evaluate to a name
. If the indexed item does not exist in the container a runtime exception is thrown.
A dictionary
may also be indexed using the dot operator where the following identifier is evaluated as a name. The following two expressions are equivalent:
dict[@my_name] dict.my_name
Unary Operators
The operand for unary +
and -
must be of type number
. The unary -
operator returns the negative of the operand. The unary +
operator is ignored, and provided for symmetry with unary -
.
The operand for !
must be of type boolean
. The result is true
if the operand is false
. The result is false
if the operand is true
.
Arithmetic Operators
The operands for +
, -
, *
, /
, and %
must be of type number
. The result of the binary operator +
is the sum of the operands. The result of the binary operator -
is the difference of the operands.
Operators *
and /
respectively denote floating point multiplication and division. The %
operator will truncate each operand to an integer and return the remainder. It is undefined if the remainder is negative if one of the operands is negative.
- Todo:
- (sparent) : The % operator is left over from Eve1 which supported only integer arithmetic. It will likely be redefined in the future to be a proper floating point modulus.
Logical Operators
The operands for &&
and ||
must be of type boolean
. The result of the &&
and ||
operator is of type boolean
denoting the logical-and or logical-or of the operands. The first operand is evaluated and if it is false
for && or true
for || then the second operand is not evaluated.
- Todo:
- (sparent) : [move this discussion down to a section on evaluating sheets.] The tracking of "considered" in Adam is currently handled at too course a granularity, an item is considered if is evaluated - there are some interesting issues with short circuit booleans - for example, for logical-or if the second operand evaluates to true - the value of the first operand doesn't matter. Was it considered? Similarly, does it contribute to the result. The answer today is yes for both of these but this may be revisited.
Relational Operators
The operands for <
(less than), >
(greater than), <=
(less than or equal to), and >=
(greater than or equal to) must be of type number
. The result is of type boolean
.
Equality Operators
The operands for ==
(equal) and !=
(not equal) can be of any type. If the operands are not of the same type then they will compare as not equal.
Conditional Operator
The conditional operator takes three operands, separated by ? and
:. The first operand must be of type
boolean
. If the first operand is true
, then the result is the second operand. If the first operand is false
then the result is the third operand. Only one of the second and third expressions is evaluated.
Precedence and Order of Evaluation
- Todo:
- (sparent) : Allowing for operator overloading on external types is a possible future extension.
Special Functions
intentionally empty
Supplied Functions
intentionally empty