Before parsing an FPP model, the compiler converts the source text into a list of tokens. This process is called lexing.
A token is one of the following:
-
A symbol.
-
An identifier.
-
An integer literal.
-
A line of an annotation beginning with
@
or@<
.
The following are reserved words in FPP.
They may not be used as identifiers, except
when preceded by the $
character, as discussed below.
F32
F64
I16
I32
I64
I8
U16
U32
U64
U8
action
active
activity
always
array
assert
async
at
base
block
bool
change
choice
command
component
connections
constant
container
cpu
default
diagnostic
do
drop
else
entry
enum
enter
event
exit
false
fatal
format
get
group
guard
guarded
health
high
hook
id
if
import
include
initial
input
instance
internal
locate
low
machine
match
module
omit
on
opcode
orange
output
packet
packets
param
passive
phase
port
priority
private
product
queue
queued
record
recv
red
ref
reg
request
resp
save
send
serial
set
severity
signal
size
stack
state
string
struct
sync
telemetry
text
throttle
time
topology
true
type
unmatched
update
warning
with
yellow
The following sequences of characters are symbol tokens in FPP:
(
)
*
+
,
-
->
.
/
:
;
=
[
]
{
}
Definition: An identifier is an unqualified name consisting of one or more characters. The first character must be a letter or an underscore. Characters after the first character may be letters, digits, and underscores.
For example:
-
identifier
,identifier3
, and__identifier3
are valid identifiers. -
3identifier
is not a valid identifier, because it starts with a digit. -
identifier%
is not a valid identifier, because it contains the character%
.
Escaped keywords: Any identifier may be preceded by the character $
, with
no intervening space.
An identifier $
I has the same meaning as I, except that if I is a
reserved word, then I is scanned
as an identifier and not as a reserved word.
For example:
-
$identifier
is a valid identifier. It has the same meaning asidentifier
. -
$time
is a valid identifier. It represents the character sequencetime
treated as an identifier and not as a reserved word. -
time
is a reserved word. It may not be used as an identifier.
An end-of-line token is a sequence of one or more newlines. A newline (or line break) is the NL character (ASCII code 0x0A), optionally preceded by a CR character (ASCII code 0x0D). End-of-line tokens separate the elements of element sequences.
The lexer ignores comments. Specifically:
-
A comment followed by a newline is treated as a newline.
-
A comment at the end of a file, not followed by a newline, is treated as no text.
Apart from end-of-line tokens, the lexer treats whitespace as follows:
-
Space characters are ignored, except to separate tokens.
-
No other whitespace or non-printable characters are allowed outside of a string, comment, or annotation. In particular, the tab character may not appear in an FPP model outside of a string, comment, or annotation.
The character \
, when appearing before a
newline,
suppresses the newline.
Both the \
and the following newline are ignored, and no
end-of-line token,
is created.
For example, this
constant a \
= 1
is equivalent to this:
constant a = 1
Note that \
is required in this case.
For example, the following is not syntactically correct:
constant a # Error
= 1
The newline indicates the end of an element sequence, but
constant a
is not a valid element sequence.
The following symbols consume sequences of newlines that follow them, without creating an end-of-line token:
(
*
+
,
-
->
/
:
;
=
[
{
For example, the following code is legal:
module M {
constant a = 0
}
It is equivalent to this code:
module M { constant a = 0 }
The newline after the {
symbol is consumed by the symbol.
The newline after the constant definition is consumed
by the element sequence member.
The following code is also legal, because the newline is
consumed by the =
symbol:
constant a =
0
Similarly, the following code is legal, because the newline
is consumed by the +
symbol:
constant a = 1 +
2
To simplify parsing, the lexer may collapse a sequence of one or more end-of-line tokens into a single token, or into no token, if the operation does not change the meaning of the result according to the parse rules. For example, the lexer may treat this code
constant a = [
1
2
3
]
as if it were this
constant a = [
1
2
3
]
or this
constant a = [
1
2
3 ]
According to the rules for parsing element sequences, all three code sections are equivalent.