06 04 lexical constructs
All P4 keywords use only ASCII characters. All P4 identifiers must use only ASCII characters. P4 compilers should handle correctly strings containing 8-bit characters in comments and string literals. P4 is case-sensitive. Whitespace characters, including newlines are treated as token separators. Indentation is free-form; however, P4 has C-like block constructs, and all our examples use C-style indentation. Tab characters are treated as spaces.
The lexer recognizes the following kinds of terminals:
IDENTIFIER: start with a letter or underscore, and contain letters, digits and underscoresTYPE_IDENTIFIER: identifier that denotes a type nameINTEGER: integer literalsDONTCARE: a single underscore- Keywords such as
RETURN. By convention, each keyword terminal corresponds to a language keyword with the same spelling but using lowercase. For example, theRETURNterminal corresponds to thereturnkeyword.
Identifiers
P4 identifiers may contain only letters, numbers, and the underscore
character _, and must start with a letter or underscore. The special
identifier consisting of a single underscore _ is reserved to indicate
a “don’t care” value; its type may vary depending on the context.
Certain keywords (e.g., apply) can be used as identifiers if the
context makes it unambiguous.
nonTypeName
: IDENTIFIER
| APPLY
| KEY
| ACTIONS
| STATE
| ENTRIES
| TYPE
| PRIORITY
;
name
: nonTypeName
| TYPE_IDENTIFIER
;
Comments
P4 supports several kinds of comments:
- Single-line comments, introduced by
//and spanning to the end of line, - Multi-line comments, enclosed between
/*and*/ - Nested multi-line comments are not supported.
- Javadoc-style comments, starting with
/**and ending with*/
Use of Javadoc-style comments is strongly encouraged for the tables and actions that are used to synthesize the interface with the control-plane.
P4 treats comments as token separators and no comments are allowed
within a token—e.g. bi/**/t is parsed as two tokens, bi and t, and
not as a single token bit.
Literal constants
Boolean literals
There are two Boolean literal constants: true and false.
Integer literals
Integer literals are non-negative arbitrary-precision integers. By default, literals are represented in base 10. The following prefixes must be employed to specify the base explicitly:
0xor0Xindicates base 16 (hexadecimal)0oor0Oindicates base 8 (octal)0dor0Dindicates base 10 (decimal)0bor0Bindicates base 2
The width of a numeric literal in bits can be specified by an unsigned number prefix consisting of a number of bits and a signedness indicator:
windicates unsigned numberssindicates signed numbers
Note that a leading zero by itself does not indicate an octal (base 8) constant. The underscore character is considered a digit within number literals but is ignored when computing the value of the parsed number. This allows long constant numbers to be more easily read by grouping digits together. The underscore cannot be used in the width specification or as the first character of an integer literal. No comments or whitespaces are allowed within a literal. Here are some examples of numeric literals:
32w255 // a 32-bit unsigned number with value 255
32w0d255 // same value as above
32w0xFF // same value as above
32s0xFF // a 32-bit signed number with value 255
8w0b10101010 // an 8-bit unsigned number with value 0xAA
8w0b_1010_1010 // same value as above
8w170 // same value as above
8s0b1010_1010 // an 8-bit signed number with value -86
16w0377 // 16-bit unsigned number with value 377 (not 255!)
16w0o377 // 16-bit unsigned number with value 255 (base 8)
String literals
String literals are specified as an arbitrary sequence of 8-bit
characters, enclosed within double quote characters " (ASCII code 34).
Strings start with a double quote character and extend to the first
double quote sign which is not immediately preceded by an odd number of
backslash characters (ASCII code 92). P4 does not make any validity
checks on strings (i.e., it does not check that strings represent legal
UTF-8 encodings).
Since P4 does not provide any operations on strings, string literals are generally passed unchanged through the P4 compiler to other third-party tools or compiler-backends, including the terminating quotes. These tools can define their own handling of escape sequences (e.g., how to specify Unicode characters, or handle unprintable ASCII characters).
Here are 3 examples of string literals:
"simple string"
"string \" with \" embedded \" quotes"
"string with embedded
line terminator"
Optional trailing commas
The P4 grammar allows several kinds of comma-separated lists to end in an optional comma.
"one string \" with a quote inside;" ++ (" " ++ "another string")
// can be constant folded to
"one string \" with a quote inside; another string"
For example, the following declarations are both legal, and have the same meaning:
enum E {
a, b, c
}
enum E {
a, b, c,
}
This is particularly useful in combination with preprocessor directives:
enum E {
#if SUPPORT_A
a,
#endif
b,
c,
}