Lexical structure
Every EdgeQL command is composed of a sequence of tokens, terminated by a semicolon (;
). The types of valid tokens as well as their order is determined by the syntax of the particular command.
EdgeQL is case sensistive except for keywords (in the examples the keywords are written in upper case as a matter of convention).
There are several kinds of tokens: keywords, identifiers, literals (constants) and symbols (operators and punctuation).
Tokens are normally separated by whitespace (space, tab, newline) or comments.
Identifiers
There are two ways of writing identifiers in EdgeQL: plain and quoted. The plain identifiers are similar to many other languages, they are alphanumeric with underscores and cannot start with a digit. The quoted identifiers start and end with a backtick `quoted.identifier`
and can contain any characters inside with a few exceptions. They must not start with an ampersand (@
) or contain a double colon (::
). If there’s a need to include a backtick character as part of the identifier name a double-backtick sequence (``
) should be used: `quoted``identifier`
will result in the actual identifier being quoted`identifier
.
identifier | ::= | plain_ident | quoted_ident |
plain_ident | ::= | ident_first ident_rest |
ident_first | ::= | <any letter, underscore> |
ident_rest | ::= | <any letter, digits, underscore> |
quoted_ident | ::= | “`” qident_first qident_rest “`” |
qident_first | ::= | <any character except “@”> |
qident_rest | ::= | <any character> |
Quoted identifiers are usually needed to represent module names that contain a dot (.
) or to distinguish names from reserved keywords (for instance to allow referring to a link named “order” as `order`
).
Names and keywords
There are a number of reserved and unreserved keywords in EdgeQL. Every identifier that is not a reserved keyword is a valid name. Names are used to refer to concepts, links, link properties, etc.
short_name | ::= | not_keyword_ident | quoted_ident |
not_keyword_ident | ::= | <any plain_ident except for keyword> |
keyword | ::= | reserved_keyword | unreserved_keyword |
reserved_keyword | ::= | case insensitive sequence matching any of the following “AGGREGATE” | “ALTER” | “AND” | “ANY” | “COMMIT” | “CREATE” | “DELETE” | “DETACHED” | “DISTINCT” | “DROP” | “ELSE” | “EMPTY” | “EXISTS” | “FALSE” | “FILTER” | “FUNCTION” | “GET” | “GROUP” | “IF” | “ILIKE” | “IN” | “INSERT” | “IS” | “LIKE” | “LIMIT” | “MODULE” | “NOT” | “OFFSET” | “OR” | “ORDER” | “OVER” | “PARTITION” | “ROLLBACK” | “SELECT” | “SET” | “SINGLETON” | “START” | “TRUE” | “UPDATE” | “UNION” | “WITH” |
unreserved_keyword | ::= | case insensitive sequence matching any of the following “ABSTRACT” | “ACTION” | “AFTER” | “ARRAY” | “AS” | “ASC” | “ATOM” | “ANNOTATION” | “BEFORE” | “BY” | “CONCEPT” | “CONSTRAINT” | “DATABASE” | “DESC” | “EVENT” | “EXTENDING” | “FINAL” | “FIRST” | “FOR” | “FROM” | “INDEX” | “INITIAL” | “LAST” | “LINK” | “MAP” | “MIGRATION” | “OF” | “ON” | “POLICY” | “PROPERTY” | “REQUIRED” | “RENAME” | “TARGET” | “THEN” | “TO” | “TRANSACTION” | “TUPLE” | “VALUE” | “VIEW” |
Fully-qualified names consist of a module, ::
, and a short name. They can be used in most places where a short name can appear (such as paths and shapes).
name | ::= | short_name | fq_name |
fq_name | ::= | short_name “::” short_name | short_name “::” unreserved_keyword |
Constants
A number of scalar types have literal constant expressions.
Strings
Production rules for str literals:
string | ::= | str | rawstr |
str | ::= | “‘“ str_content “‘“ | ‘“‘ str_content ‘“‘ |
raw_str | ::= | “r’” raw_content “‘“ | ‘r”‘ raw_content ‘“‘ | dollar_quote raw_content dollar_quote |
raw_content | ::= | <any character different from delimiting quote> |
dollar_quote | ::= | “$” q_char0? q_char “$” |
q_char0 | ::= | “A”…”Z” | “a”…”z” | ““ |
qchar | ::= | “A”…”Z” | “a”…”z” | ““ | “0”…”9” |
str_content | ::= | <newline> | unicode | str_escapes |
unicode | ::= | <any printable unicode character not preceded by “\”> |
str_escapes | ::= | <see below for details> |
The inclusion of “high ASCII” character in edgeql:q_char in practice reflects the ability to use some of the letters with diacritics like ò
or ü
in the dollar-quote delimiter.
Here’s a list of valid edgeql:str_escapes:
Escape Sequence | Meaning |
---|---|
| Backslash and all whitespace up to next non-whitespace character is ignored |
| Backslash () |
| Single quote (‘) |
| Double quote (“) |
| ASCII backspace ( |
| ASCII form feed ( |
| ASCII newline ( |
| ASCII carriage return ( |
| ASCII tabulation ( |
| Character with hex value hh |
| Character with 16-bit hex value hhhh |
| Character with 32-bit hex value hhhhhhhh |
Here’s some examples of regular strings using escape sequences
select 'hello
world';
{'hello
world'}
select "hello\nworld";
{'hello
world'}
select 'hello \
world';
{'hello world'}
select 'https://edgedb.com/\
docs/edgeql/lexical\
#constants';
{'https://edgedb.com/docs/edgeql/lexical#constants'}
select 'hello \\ world';
{'hello \ world'}
select 'hello \'world\'';
{"hello 'world'"}
select 'hello \x77orld';
{'hello world'}
select 'hello \u0077orld';
{'hello world'}
Raw strings don’t have any specially interpreted symbols; they contain all the symbols between the quotes exactly as typed.
select r'hello \\ world';
{'hello \\ world'}
select r'hello \
world';
{'hello \
world'}
select r'hello
world';
{'hello
world'}
Dollar-quoted String Constants
A special case of raw strings are dollar-quoted strings. They allow using either kind of quote symbols '
or "
as part of the string content without the quotes terminating the string. In fact, because the dollar-quote delimiter sequences can have arbitrary alphanumeric additional fillers, it is always possible to surround any content with dollar-quotes in an unambiguous manner:
select $$hello
world$$;
{'hello
world'}
select $$hello\nworld$$;
{'hello\nworld'}
select $$"hello" 'world'$$;
{"\"hello\" 'world'"}
select $a$hello$$world$$$a$;
{'hello$$world$$'}
More specifically, a delimiter:
Must start with an ASCII letter or underscore
Has following characters that can be digits 0-9, underscores or ASCII letters
Bytes
Production rules for bytes literals:
bytes | ::= | “b’” bytes_content “‘“ | ‘b”‘ bytes_content ‘“‘ |
bytes_content | ::= | <newline> | ascii | bytes_escapes |
ascii | ::= | <any printable ascii character not preceded by “\”> |
bytes_escapes | ::= | <see below for details> |
Here’s a list of valid edgeql:bytes_escapes:
Escape Sequence | Meaning |
---|---|
| Backslash () |
| Single quote (‘) |
| Double quote (“) |
| ASCII backspace ( |
| ASCII form feed ( |
| ASCII newline ( |
| ASCII carriage return ( |
| ASCII tabulation ( |
| Character with hex value hh |
Integers
There are two kinds of integer constants: limited size (int64) and unlimited size (bigint). Unlimited size integer bigint literals are similar to a regular integer literals with an n
suffix. The production rules are as follows:
bigint | ::= | integer “n” |
integer | ::= | “0” | non_zero digit* |
non_zero | ::= | “1”…”9” |
digit | ::= | “0”…”9” |
By default all integer literals are interpreted as int64, while an explicit cast can be used to convert them to int16 or int32:
select 0;
{0}
select 123;
{123}
select <int16>456;
{456}
select <int32>789;
{789}
Examples of bigint literals:
select 123n;
{123n}
select 12345678901234567890n;
{12345678901234567890n}
Real Numbers
Just as for integers, there are two kinds of real number constants: limited precision (float64) and unlimited precision (decimal). The decimal constants have the same lexical structure as float64, but with an n
suffix:
decimal | ::= | float “n” |
float | ::= | float_wo_dec | float_w_dec |
float_wo_dec | ::= | integer_part exp |
float_w_dec | ::= | integer_part “.” decimal_part? exp? |
integer_part | ::= | “0” | non_zero digit* |
decimal_part | ::= | digit+ |
exp | ::= | “e” (“+” | “-“)? digit+ |
By default all float literals are interpreted as float64, while an explicit cast can be used to convert them to float32:
select 0.1;
{0.1}
select 12.3;
{12.3}
select 1e3;
{1000.0}
select 1.2e-3;
{0.0012}
select <float32>12.3;
{12.3}
Examples of decimal literals:
select 12.3n;
{12.3n}
select 12345678901234567890.12345678901234567890n;
{12345678901234567890.12345678901234567890n}
select 12345678901234567890.12345678901234567890e-3n;
{12345678901234567.89012345678901234567890n}
Punctuation
EdgeQL uses ;
as a statement separator. It is idempotent, so multiple repetitions of ;
don’t have any additional effect.
Comments
Comments start with a #
character that is not otherwise part of a string literal and end at the end of line. Semantically, a comment is equivalent to whitespace.
comment | ::= | “#” <any other characters until the end of line> |
Operators
EdgeQL operators listed in order of precedence from lowest to highest:
operator |
---|