# The complete grammar: how Pliro fits together [Syntax and values](README.md) Grammar describes which combinations of words and symbols form valid code. This page uses a compact technical notation called EBNF. You do not need to memorize it to start programming; use the linked beginner articles first. ## How to read the notation **EBNF** means *Extended Backus–Naur Form*. It is a way to write rules about a language. Think of it as a recipe that says which ingredients may go where. It is not Pliro code to run. | Notation | How to read it | |---|---| | `name = ... ;` | The rule called `name` consists of the parts on the right. The semicolon ends this rule. | | `"let"` | The quoted word or symbol is written literally in the program. | | `a, b` | First `a`, then `b`. | | `a \| b` | Choose `a` or `b`. | | `[ a ]` | `a` is optional: it may be left out. | | `{ a }` | Repeat `a` zero or more times. | | `( a \| b )` | Keep these alternatives together as a group. | | `(* ... *)` | An explanation for the reader of the grammar. | Unquoted names refer to other rules. For example, `identifier` means a name, `expression` means code that produces a value, and `statement` means an instruction. `newline` ends a line and **EOF** (*end of file*) means there is no source text left. `INDENT` and `DEDENT` mark entering and leaving an indented block. Comments are ignored for these grammar rules; the technical word *trivia* here means text that does not change the program's instructions. A **token** is one recognized piece of code, such as a name, a number, or `+`. The **parser** puts these pieces together using the grammar. `&TOKEN` means “check that this piece comes next, but leave it for the surrounding rule to handle.” The punctuation in this table describes the grammar; quoted punctuation inside a rule describes what to type in Pliro. This EBNF describes the implemented canonical grammar using English spellings. `INDENT` and `DEDENT` are produced from leading spaces. Comments are omitted as trivia. ```ebnf program = { newline | statement }, EOF ; statement = useStatement | letStatement | setStatement | ifStatement | whileStatement | forStatement | functionDeclaration | eventHandler | returnStatement | commandCallStatement | expressionStatement ; useStatement = "use", moduleName, lineEnd ; moduleName = identifier, { ".", identifier } ; letStatement = "let", identifier, "=", expression, lineEnd ; setStatement = "set", assignmentTarget, "=", expression, lineEnd ; assignmentTarget = identifier, { "[", expression, "]" | ".", identifier } ; ifStatement = "if", expression, block, [ "else", block ] ; whileStatement = "while", expression, block ; forStatement = "for", identifier, "in", expression, block ; functionDeclaration = "function", identifier, "(", [ parameters ], ")", block ; parameters = identifier, { ",", identifier }, [ "," ] ; eventHandler = "when", expression, block ; returnStatement = "return", [ expression ], lineEnd ; commandCallStatement = commandTarget, commandFirstArgument, { ",", expression }, [ "," ], lineEnd ; commandTarget = identifier, { ".", identifier } ; commandFirstArgument = expression (* first token: identifier, number, string, true, false, none, not, or "{" *) ; expressionStatement = expression, lineEnd ; block = ":", newline, { newline }, INDENT, statement, { newline | statement }, DEDENT ; lineEnd = newline | &DEDENT | &EOF ; expression = logicalOr ; logicalOr = logicalAnd, { "or", logicalAnd } ; logicalAnd = equality, { "and", equality } ; equality = comparison, { ( "==" | "!=" ), comparison } ; comparison = additive, { ( "<" | "<=" | ">" | ">=" ), additive } ; additive = multiplicative, { ( "+" | "-" ), multiplicative } ; multiplicative = unary, { ( "*" | "/" | "%" ), unary } ; unary = ( "not" | "+" | "-" ), unary | postfix ; postfix = primary, { callSuffix | indexSuffix | memberSuffix } ; callSuffix = "(", [ arguments ], ")" ; arguments = expression, { ",", expression }, [ "," ] ; indexSuffix = "[", expression, "]" ; memberSuffix = ".", identifier ; primary = number | string | "true" | "false" | "none" | identifier | "(", expression, ")" | listLiteral | mapLiteral ; listLiteral = "[", [ arguments ], "]" ; mapLiteral = "{", [ mapEntry, { ",", mapEntry }, [ "," ] ], "}" ; mapEntry = expression, ":", expression ; ``` `&TOKEN` means that the parser requires that token next without consuming it; the enclosing block or program consumes the eventual `DEDENT` or `EOF`. For the command form, the first argument may begin with an identifier, number, text literal, `true`, `false`, `none`, `not`, or a map literal. Use a parenthesized call when the first argument begins with unary `+` or `-`, a grouping `(`, or a list literal `[`. See [Section 5.4](../../../pliro-syntax.en.md#54-calls-and-expression-statements). ## Related entries [Syntax and values](README.md) · [Built-ins](../builtins/README.md) · [Programming guides](../guides/README.md)