6. YANG Syntax
The YANG syntax is similar to that of SMIng [RFC3780] and programming languages like C and C++. This C-like syntax was chosen specifically for its readability, since YANG values the time and effort of the readers of models above those of modules writers and YANG tool-chain developers. This section introduces the YANG syntax. Legal characters in YANG modules are the Unicode and ISO/IEC 10646 [ISO.10646] characters, including tab, carriage return, and line feed but excluding the other C0 control characters, the surrogate blocks, and the noncharacters. The character syntax is formally defined by the rule "yang-char" in Section 14. YANG modules and submodules are stored in files using the UTF-8 [RFC3629] character encoding. Lines in a YANG module end with a carriage return-line feed combination or with a line feed alone. A carriage return that is not followed by a line feed may only appear inside a quoted string (Section 6.1.3). Note that carriage returns and line feeds that appear inside quoted strings become part of the value of the string without modification; the value of a multi-line quoted string contains the same form of line ends as those lines of the YANG module.
6.1. Lexical Tokenization
YANG modules are parsed as a series of tokens. This section details the rules for recognizing tokens from an input stream. YANG tokenization rules are both simple and powerful. The simplicity is driven by a need to keep the parsers easy to implement, while the power is driven by the fact that modelers need to express their models in readable formats.6.1.1. Comments
Comments are C++ style. A single line comment starts with "//" and ends at the end of the line. A block comment starts with "/*" and ends with the nearest following "*/". Note that inside a quoted string (Section 6.1.3), these character pairs are never interpreted as the start or end of a comment.6.1.2. Tokens
A token in YANG is either a keyword, a string, a semicolon (";"), or braces ("{" or "}"). A string can be quoted or unquoted. A keyword is either one of the YANG keywords defined in this document, or a prefix identifier, followed by a colon (":"), followed by a language extension keyword. Keywords are case sensitive. See Section 6.2 for a formal definition of identifiers.6.1.3. Quoting
An unquoted string is any sequence of characters that does not contain any space, tab, carriage return, or line feed characters, a single or double quote character, a semicolon (";"), braces ("{" or "}"), or comment sequences ("//", "/*", or "*/"). Note that any keyword can legally appear as an unquoted string. Within an unquoted string, every character is preserved. Note that this means that the backslash character does not have any special meaning in an unquoted string. If a double-quoted string contains a line break followed by space or tab characters that are used to indent the text according to the layout in the YANG file, this leading whitespace is stripped from the string, up to and including the column of the starting double quote character, or to the first non-whitespace character, whichever occurs first. Any tab character in a succeeding line that must be examined for stripping is first converted into 8 space characters.
If a double-quoted string contains space or tab characters before a line break, this trailing whitespace is stripped from the string. A single-quoted string (enclosed within ' ') preserves each character within the quotes. A single quote character cannot occur in a single-quoted string, even when preceded by a backslash. Within a double-quoted string (enclosed within " "), a backslash character introduces a representation of a special character, which depends on the character that immediately follows the backslash: \n newline \t a tab character \" a double quote \\ a single backslash The backslash MUST NOT be followed by any other character. If a quoted string is followed by a plus character ("+"), followed by another quoted string, the two strings are concatenated into one string, allowing multiple concatenations to build one string. Whitespace, line breaks, and comments are allowed between the quoted strings and the plus character. In double-quoted strings, whitespace trimming is done before substitution of backslash-escaped characters. Concatenation is performed as the last step.6.1.3.1. Quoting Examples
The following strings are equivalent: hello "hello" 'hello' "hel" + "lo" 'hel' + "lo" The following examples show some special strings: "\"" - string containing a double quote '"' - string containing a double quote "\n" - string containing a newline character '\n' - string containing a backslash followed by the character n
The following examples show some illegal strings: '''' - a single-quoted string cannot contain single quotes """ - a double quote must be escaped in a double-quoted string The following strings are equivalent: "first line second line" "first line\n" + " second line"6.2. Identifiers
Identifiers are used to identify different kinds of YANG items by name. Each identifier starts with an uppercase or lowercase ASCII letter or an underscore character, followed by zero or more ASCII letters, digits, underscore characters, hyphens, and dots. Implementations MUST support identifiers up to 64 characters in length and MAY support longer identifiers. Identifiers are case sensitive. The identifier syntax is formally defined by the rule "identifier" in Section 14. Identifiers can be specified as quoted or unquoted strings.6.2.1. Identifiers and Their Namespaces
Each identifier is valid in a namespace that depends on the type of the YANG item being defined. All identifiers defined in a namespace MUST be unique. o All module and submodule names share the same global module identifier namespace. o All extension names defined in a module and its submodules share the same extension identifier namespace. o All feature names defined in a module and its submodules share the same feature identifier namespace. o All identity names defined in a module and its submodules share the same identity identifier namespace. o All derived type names defined within a parent node or at the top level of the module or its submodules share the same type identifier namespace. This namespace is scoped to all descendant nodes of the parent node or module. This means that any descendant node may use that typedef, and it MUST NOT define a typedef with the same name.
o All grouping names defined within a parent node or at the top level of the module or its submodules share the same grouping identifier namespace. This namespace is scoped to all descendant nodes of the parent node or module. This means that any descendant node may use that grouping, and it MUST NOT define a grouping with the same name. o All leafs, leaf-lists, lists, containers, choices, rpcs, actions, notifications, anydatas, and anyxmls defined (directly or through a "uses" statement) within a parent node or at the top level of the module or its submodules share the same identifier namespace. This namespace is scoped to the parent node or module, unless the parent node is a case node. In that case, the namespace is scoped to the closest ancestor node that is not a case or choice node. o All cases within a choice share the same case identifier namespace. This namespace is scoped to the parent choice node. Forward references are allowed in YANG.6.3. Statements
A YANG module contains a sequence of statements. Each statement starts with a keyword, followed by zero or one argument, followed by either a semicolon (";") or a block of substatements enclosed within braces ("{ }"): statement = keyword [argument] (";" / "{" *statement "}") The argument is a string, as defined in Section 6.1.2.6.3.1. Language Extensions
A module can introduce YANG extensions by using the "extension" keyword (see Section 7.19). The extensions can be imported by other modules with the "import" statement (see Section 7.1.5). When an imported extension is used, the extension's keyword MUST be qualified using the prefix with which the extension's module was imported. If an extension is used in the module where it is defined, the extension's keyword MUST be qualified with the prefix of this module. The processing of extensions depends on whether support for those extensions is claimed for a given YANG parser or the tool set in which it is embedded. An unsupported extension appearing in a YANG module as an unknown-statement (see Section 14) MAY be ignored in its entirety. Any supported extension MUST be processed in accordance with the specification governing that extension.
Care must be taken when defining extensions so that modules that use the extensions are meaningful also for applications that do not support the extensions.6.4. XPath Evaluations
YANG relies on XML Path Language (XPath) 1.0 [XPATH] as a notation for specifying many inter-node references and dependencies. An implementation is not required to implement an XPath interpreter but MUST ensure that the requirements encoded in the data model are enforced. The manner of enforcement is an implementation decision. The XPath expressions MUST be syntactically correct, and all prefixes used MUST be present in the XPath context (see Section 6.4.1). An implementation may choose to implement them by hand, rather than using the XPath expression directly. The data model used in the XPath expressions is the same as that used in XPath 1.0 [XPATH], with the same extension for root node children as used by XSLT 1.0 (see Section 3.1 in [XSLT]). Specifically, it means that the root node may have any number of element nodes as its children. The data tree has no concept of document order. An implementation needs to choose some document order, but how it is done is an implementation decision. This means that XPath expressions in YANG modules SHOULD NOT rely on any specific document order. Numbers in XPath 1.0 are IEEE 754 [IEEE754-2008] double-precision floating-point values; see Section 3.5 in [XPATH]. This means that some values of int64, uint64, and decimal64 types (see Sections 9.2 and 9.3) cannot be exactly represented in XPath expressions. Therefore, due caution should be exercised when using nodes with 64-bit numeric values in XPath expressions. In particular, numerical comparisons involving equality may yield unexpected results. For example, consider the following definition: leaf lxiv { type decimal64 { fraction-digits 18; } must ". <= 10"; } An instance of the "lxiv" leaf having the value of 10.0000000000000001 will then successfully pass validation.
6.4.1. XPath Context
All YANG XPath expressions share the following XPath context definition: o The set of namespace declarations is the set of all "import" statements' prefix and namespace pairs in the module where the XPath expression is specified, and the "prefix" statement's prefix for the "namespace" statement's URI. o Names without a namespace prefix belong to the same namespace as the identifier of the current node. Inside a grouping, that namespace is affected by where the grouping is used (see Section 7.13). Inside a typedef, that namespace is affected by where the typedef is referenced. If a typedef is defined and referenced within a grouping, the namespace is affected by where the grouping is used (see Section 7.13). o The function library is the core function library defined in [XPATH] and the functions defined in Section 10. o The set of variable bindings is empty. The mechanism for handling unprefixed names is adopted from XPath 2.0 [XPATH2.0] and helps simplify XPath expressions in YANG. No ambiguity may ever arise, because YANG node identifiers are always qualified names with a non-null namespace URI. The accessible tree depends on where the statement with the XPath expression is defined: o If the XPath expression is defined in a substatement to a data node that represents configuration, the accessible tree is the data in the datastore where the context node exists. The root node has all top-level configuration data nodes in all modules as children. o If the XPath expression is defined in a substatement to a data node that represents state data, the accessible tree is all state data in the server, and the running configuration datastore. The root node has all top-level data nodes in all modules as children. o If the XPath expression is defined in a substatement to a "notification" statement, the accessible tree is the notification instance, all state data in the server, and the running configuration datastore. If the notification is defined on the top level in a module, then the root node has the node
representing the notification being defined and all top-level data nodes in all modules as children. Otherwise, the root node has all top-level data nodes in all modules as children. o If the XPath expression is defined in a substatement to an "input" statement in an "rpc" or "action" statement, the accessible tree is the RPC or action operation instance, all state data in the server, and the running configuration datastore. The root node has top-level data nodes in all modules as children. Additionally, for an RPC, the root node also has the node representing the RPC operation being defined as a child. The node representing the operation being defined has the operation's input parameters as children. o If the XPath expression is defined in a substatement to an "output" statement in an "rpc" or "action" statement, the accessible tree is the RPC or action operation instance, all state data in the server, and the running configuration datastore. The root node has top-level data nodes in all modules as children. Additionally, for an RPC, the root node also has the node representing the RPC operation being defined as a child. The node representing the operation being defined has the operation's output parameters as children. In the accessible tree, all leafs and leaf-lists with default values in use exist (see Sections 7.6.1 and 7.7.2). If a node that exists in the accessible tree has a non-presence container as a child, then the non-presence container also exists in the accessible tree. The context node varies with the YANG XPath expression and is specified where the YANG statement with the XPath expression is defined.
6.4.1.1. Examples
Given the following module: module example-a { yang-version 1.1; namespace urn:example:a; prefix a; container a { list b { key id; leaf id { type string; } notification down { leaf reason { type string; } } action reset { input { leaf delay { type uint32; } } output { leaf result { type string; } } } } } notification failure { leaf b-ref { type leafref { path "/a/b/id"; } } } }
and given the following data tree, specified in XML: <a xmlns="urn:example:a"> <b> <id>1</id> </b> <b> <id>2</id> </b> </a> The accessible tree for a notification "down" on /a/b[id="2"] is: <a xmlns="urn:example:a"> <b> <id>1</id> </b> <b> <id>2</id> <down> <reason>error</reason> </down> </b> </a> // possibly other top-level nodes here The accessible tree for an action invocation of "reset" on /a/b[id="1"] with the "when" parameter set to "10" would be: <a xmlns="urn:example:a"> <b> <id>1</id> <reset> <delay>10</delay> </reset> </b> <b> <id>2</id> </b> </a> // possibly other top-level nodes here
The accessible tree for the action output of this action is: <a xmlns="urn:example:a"> <b> <id>1</id> <reset> <result>ok</result> </reset> </b> <b> <id>2</id> </b> </a> // possibly other top-level nodes here The accessible tree for a notification "failure" could be: <a xmlns="urn:example:a"> <b> <id>1</id> </b> <b> <id>2</id> </b> </a> <failure> <b-ref>2</b-ref> </failure> // possibly other top-level nodes here6.5. Schema Node Identifier
A schema node identifier is a string that identifies a node in the schema tree. It has two forms, "absolute" and "descendant", defined by the rules "absolute-schema-nodeid" and "descendant-schema-nodeid" in Section 14, respectively. A schema node identifier consists of a path of identifiers, separated by slashes ("/"). In an absolute schema node identifier, the first identifier after the leading slash is any top-level schema node in the local module or in an imported module. References to identifiers defined in external modules MUST be qualified with appropriate prefixes, and references to identifiers defined in the current module and its submodules MAY use a prefix. For example, to identify the child node "b" of top-level node "a", the string "/a/b" can be used.
7. YANG Statements
The following sections describe all of the YANG statements. Note that even a statement that does not have any substatements defined in YANG can have vendor-specific extensions as substatements. For example, the "description" statement does not have any substatements defined in YANG, but the following is legal: description "Some text." { ex:documentation-flag 5; }7.1. The "module" Statement
The "module" statement defines the module's name and groups all statements that belong to the module together. The "module" statement's argument is the name of the module, followed by a block of substatements that holds detailed module information. The module name is an identifier (see Section 6.2). Names of modules published in RFC streams [RFC4844] MUST be assigned by IANA; see Section 14 in [RFC6020]. Private module names are assigned by the organization owning the module without a central registry. See Section 5.1 for recommendations on how to name modules. A module typically has the following layout: module <module-name> { // header information <yang-version statement> <namespace statement> <prefix statement> // linkage statements <import statements> <include statements> // meta-information <organization statement> <contact statement> <description statement> <reference statement>
// revision history <revision statements> // module definitions <other statements> }7.1.1. The module's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | anydata | 7.10 | 0..n | | anyxml | 7.11 | 0..n | | augment | 7.17 | 0..n | | choice | 7.9 | 0..n | | contact | 7.1.8 | 0..1 | | container | 7.5 | 0..n | | description | 7.21.3 | 0..1 | | deviation | 7.20.3 | 0..n | | extension | 7.19 | 0..n | | feature | 7.20.1 | 0..n | | grouping | 7.12 | 0..n | | identity | 7.18 | 0..n | | import | 7.1.5 | 0..n | | include | 7.1.6 | 0..n | | leaf | 7.6 | 0..n | | leaf-list | 7.7 | 0..n | | list | 7.8 | 0..n | | namespace | 7.1.3 | 1 | | notification | 7.16 | 0..n | | organization | 7.1.7 | 0..1 | | prefix | 7.1.4 | 1 | | reference | 7.21.4 | 0..1 | | revision | 7.1.9 | 0..n | | rpc | 7.14 | 0..n | | typedef | 7.3 | 0..n | | uses | 7.13 | 0..n | | yang-version | 7.1.2 | 1 | +--------------+---------+-------------+
7.1.2. The "yang-version" Statement
The "yang-version" statement specifies which version of the YANG language was used in developing the module. The statement's argument is a string. It MUST contain the value "1.1" for YANG modules defined based on this specification. A module or submodule that doesn't contain the "yang-version" statement, or one that contains the value "1", is developed for YANG version 1, defined in [RFC6020]. Handling of the "yang-version" statement for versions other than "1.1" (the version defined here) is out of scope for this specification. Any document that defines a higher version will need to define the backward compatibility of such a higher version. For compatibility between YANG versions 1 and 1.1, see Section 12.7.1.3. The "namespace" Statement
The "namespace" statement defines the XML namespace that all identifiers defined by the module are qualified by in the XML encoding, with the exception of identifiers for data nodes, action nodes, and notification nodes defined inside a grouping (see Section 7.13 for details). The argument to the "namespace" statement is the URI of the namespace. See also Section 5.3.7.1.4. The "prefix" Statement
The "prefix" statement is used to define the prefix associated with the module and its namespace. The "prefix" statement's argument is the prefix string that is used as a prefix to access a module. The prefix string MAY be used with the module to refer to definitions contained in the module, e.g., "if:ifName". A prefix is an identifier (see Section 6.2). When used inside the "module" statement, the "prefix" statement defines the prefix suggested to be used when this module is imported. To improve readability of the NETCONF XML, a NETCONF client or server that generates XML or XPath that uses prefixes SHOULD use the prefix defined by the module as the XML namespace prefix, unless there is a conflict.
When used inside the "import" statement, the "prefix" statement defines the prefix to be used when accessing definitions inside the imported module. When a reference to an identifier from the imported module is used, the prefix string for the imported module followed by a colon (":") and the identifier is used, e.g., "if:ifIndex". To improve readability of YANG modules, the prefix defined by a module SHOULD be used when the module is imported, unless there is a conflict. If there is a conflict, i.e., two different modules that both have defined the same prefix are imported, at least one of them MUST be imported with a different prefix. All prefixes, including the prefix for the module itself, MUST be unique within the module or submodule.7.1.5. The "import" Statement
The "import" statement makes definitions from one module available inside another module or submodule. The argument is the name of the module to import, and the statement is followed by a block of substatements that holds detailed import information. When a module is imported, the importing module may: o use any grouping and typedef defined at the top level in the imported module or its submodules. o use any extension, feature, and identity defined in the imported module or its submodules. o use any node in the imported module's schema tree in "must", "path", and "when" statements, or as the target node in "augment" and "deviation" statements. The mandatory "prefix" substatement assigns a prefix for the imported module that is scoped to the importing module or submodule. Multiple "import" statements may be specified to import from different modules. When the optional "revision-date" substatement is present, any typedef, grouping, extension, feature, and identity referenced by definitions in the local module are taken from the specified revision of the imported module. It is an error if the specified revision of the imported module does not exist. If no "revision-date" substatement is present, it is undefined from which revision of the module they are taken. Multiple revisions of the same module can be imported, provided that different prefixes are used.
+---------------+---------+-------------+ | substatement | section | cardinality | +---------------+---------+-------------+ | description | 7.21.3 | 0..1 | | prefix | 7.1.4 | 1 | | reference | 7.21.4 | 0..1 | | revision-date | 7.1.5.1 | 0..1 | +---------------+---------+-------------+ The import's Substatements7.1.5.1. The import's "revision-date" Statement
The import's "revision-date" statement is used to specify the version of the module to import.7.1.6. The "include" Statement
The "include" statement is used to make content from a submodule available to that submodule's parent module. The argument is an identifier that is the name of the submodule to include. Modules are only allowed to include submodules that belong to that module, as defined by the "belongs-to" statement (see Section 7.2.2). When a module includes a submodule, it incorporates the contents of the submodule into the node hierarchy of the module. For backward compatibility with YANG version 1, a submodule is allowed to include another submodule belonging to the same module, but this is not necessary in YANG version 1.1 (see Section 5.1). When the optional "revision-date" substatement is present, the specified revision of the submodule is included in the module. It is an error if the specified revision of the submodule does not exist. If no "revision-date" substatement is present, it is undefined which revision of the submodule is included. Multiple revisions of the same submodule MUST NOT be included. +---------------+---------+-------------+ | substatement | section | cardinality | +---------------+---------+-------------+ | description | 7.21.3 | 0..1 | | reference | 7.21.4 | 0..1 | | revision-date | 7.1.5.1 | 0..1 | +---------------+---------+-------------+ The includes's Substatements
7.1.7. The "organization" Statement
The "organization" statement defines the party responsible for this module. The argument is a string that is used to specify a textual description of the organization(s) under whose auspices this module was developed.7.1.8. The "contact" Statement
The "contact" statement provides contact information for the module. The argument is a string that is used to specify contact information for the person or persons to whom technical queries concerning this module should be sent, such as their name, postal address, telephone number, and electronic mail address.7.1.9. The "revision" Statement
The "revision" statement specifies the editorial revision history of the module, including the initial revision. A series of "revision" statements detail the changes in the module's definition. The argument is a date string in the format "YYYY-MM-DD", followed by a block of substatements that holds detailed revision information. A module SHOULD have at least one "revision" statement. For every published editorial change, a new one SHOULD be added in front of the revisions sequence so that all revisions are in reverse chronological order.7.1.9.1. The revision's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | description | 7.21.3 | 0..1 | | reference | 7.21.4 | 0..1 | +--------------+---------+-------------+
7.1.10. Usage Example
The following example relies on [RFC6991]. module example-system { yang-version 1.1; namespace "urn:example:system"; prefix "sys"; import ietf-yang-types { prefix "yang"; reference "RFC 6991: Common YANG Data Types"; } include example-types; organization "Example Inc."; contact "Joe L. User Example Inc. 42 Anywhere Drive Nowhere, CA 95134 USA Phone: +1 800 555 0100 Email: joe@example.com"; description "The module for entities implementing the Example system."; revision 2007-06-09 { description "Initial revision."; } // definitions follow... }