# MikroTik RouterOS Script PEG Grammar
Script = Statement*
Statement =
/ Comment
/ ControlFlow
/ Command
/ Assignment
/ Expression
/ EmptyLine
# Comments
Comment = "#" [^\r\n]* EOL?
# Control Flow Structures
ControlFlow =
/ IfStatement
/ WhileLoop
/ ForLoop
/ ForeachLoop
/ DoLoop
IfStatement =
":if" _ "(" _ Expression _ ")" _ Block (_ ":else" _ Block)?
WhileLoop =
":while" _ "(" _ Expression _ ")" _ Block
ForLoop =
":for" _ Identifier _ "from" _ Expression _ "to" _ Expression _ ("step" _ Expression)? _ "do" _ Block
ForeachLoop =
":foreach" _ Identifier _ ("," _ Identifier)? _ "in" _ Expression _ "do" _ Block
DoLoop =
":do" _ Block _ ("while" _ "(" _ Expression _ ")")?
Block =
/ "{" _ Statement* _ "}"
/ Statement
# Commands
Command = CommandPath (_ Parameter)*
CommandPath =
/ "/" Identifier ("/" Identifier)* # Absolute path like /ip/address
/ Identifier ("/" Identifier)* # Relative path like interface/print
Parameter =
/ NamedParameter
/ Flag
/ Value
NamedParameter = Identifier "=" Value
Flag = Identifier
# Variable Assignment
Assignment =
/ GlobalAssignment
/ LocalAssignment
GlobalAssignment = ":global" _ Identifier _ ("=" _ Expression)?
LocalAssignment =
/ ":local" _ Identifier _ ("=" _ Expression)?
/ ":set" _ VariableReference _ Expression
# Expressions
Expression =
/ LogicalOr
LogicalOr = LogicalAnd (_ ("||" / "or") _ LogicalAnd)*
LogicalAnd = Equality (_ ("&&" / "and") _ Equality)*
Equality = Relational (_ ("=" / "!=" / "<>") _ Relational)*
Relational = Additive (_ ("<=" / ">=" / "<" / ">") _ Additive)*
Additive = Multiplicative (_ ("+" / "-") _ Multiplicative)*
Multiplicative = Unary (_ ("*" / "/" / "%") _ Unary)*
Unary =
/ ("!" / "not") _ Unary
/ Primary
Primary =
/ "(" _ Expression _ ")"
/ FunctionCall
/ VariableReference
/ ArrayAccess
/ Literal
# Function Calls
FunctionCall =
/ "[" _ CommandPath (_ Parameter)* _ "]" # Command execution
/ Identifier _ "(" _ ArgumentList? _ ")" # Function call
ArgumentList = Expression (_ "," _ Expression)*
# Variables and Arrays
VariableReference =
/ "$" Identifier
/ "$" "(" Expression ")"
ArrayAccess =
/ VariableReference _ "->" _ (Identifier / "(" _ Expression _ ")")
/ Identifier _ "->" _ (Identifier / "(" _ Expression _ ")")
# Literals
Literal =
/ String
/ Number
/ Boolean
/ IPAddress
/ MacAddress
/ Time
/ Array
String =
/ "\"" DoubleStringChar* "\""
/ "'" SingleStringChar* "'"
DoubleStringChar =
/ "\\" .
/ [^"]
SingleStringChar =
/ "\\" .
/ [^']
Number =
/ Float
/ Integer
Float = Integer "." [0-9]+
Integer = [0-9]+
Boolean =
/ "true"
/ "false"
/ "yes"
/ "no"
# Network specific literals
IPAddress =
IPv4Address ("/" [0-9]+)?
IPv4Address =
[0-9]+ "." [0-9]+ "." [0-9]+ "." [0-9]+
MacAddress =
[0-9A-Fa-f]+ ":" [0-9A-Fa-f]+ ":" [0-9A-Fa-f]+ ":" [0-9A-Fa-f]+ ":" [0-9A-Fa-f]+ ":" [0-9A-Fa-f]+
Time =
[0-9]+ ("d" / "h" / "m" / "s" / "ms")
# Arrays and data structures
Array =
/ "{" _ ArrayElementList? _ "}"
ArrayElementList = ArrayElement (_ ";" _ ArrayElement)*
ArrayElement =
/ Identifier "=" Expression
/ Expression
# Value types
Value =
/ String
/ Number
/ Boolean
/ IPAddress
/ MacAddress
/ Time
/ Array
/ VariableReference
/ Expression
# Identifiers
Identifier = [a-zA-Z_][a-zA-Z0-9_-]*
# Whitespace and end of line
_ = [ \t]*
__ = [ \t\r\n]*
EOL = "\r\n" / "\n" / "\r"
EmptyLine = _ EOL
# Script specific constructs
ScriptCall =
/ ":execute" _ Expression
/ ":parse" _ Expression
/ ":return" (_ Expression)?
/ ":error" _ Expression
# Import/Export
ImportExport =
/ ":import" _ (String / Identifier)
/ ":export" _ ("file" "=" String)?
# Special RouterOS constructs
SpecialConstruct =
/ ScriptCall
/ ImportExport
/ ":beep" (_ Parameter)*
/ ":delay" _ Expression
/ ":environment" _ "print"
/ ":log" _ ("error" / "warning" / "info" / "debug") _ Expression
/ ":put" _ Expression
/ ":resolve" _ Expression
/ ":typeof" _ Expression
# Update Statement to include special constructs
Statement :=
/ Comment
/ ControlFlow
/ SpecialConstruct
/ Command
/ Assignment
/ Expression
/ EmptyLine