8. Formal Language Grammar#
This section gives the complete syntax of OSL. Syntactic structures that have
a name ending in -opt
are optional. Structures surrounded by curly braces
{ }
may be repeated 0 or more times. Text in typewriter
face indicates
literal text. The \(\epsilon\) character is used to indicate that it is
acceptable for there to be nothing (empty, no token).
8.1. Lexical elements#
<digit> ::= “0
” | “1
” | “2
” | “3
” | “4
” | “5
” | “6
” | “7
” | “8
” | “9
”
<digit-sequence> ::= <digit> { <digit> }
<hexdigit> ::= <digit> | “a
” | “A
” | “b
” | “B
” | “c
” | “C
” | “d
” | “D
” | “e
” | “E
” | “f
” | “F
”
<hexdigit-sequence> ::= <hexdigit> { <hexdigit> }
<integer> ::= <sign> <digit-sequence>
\(~~~~~~~~~~\) | <sign> “0x
” <hexdigit-sequence>
<floating-point> ::= <digit-sequence> <decimal-part-opt> <exponent-opt>
\(~~~~~~~~~~\) | <decimal-part> <exponent-opt>
<decimal-part> ::= ‘.
’ { <digit> }
<exponent> ::= ‘e
’ <sign> <digit-sequence>
<sign> ::= ‘-
’ | ‘+
’ | \(\epsilon\)
<number> ::= <integer>
\(~~~~~~~~~~\) | <floating-point>
<char-sequence> ::= { <any-char> }
<stringliteral> ::= "
<char-sequence> "
<identifier> ::= <letter-or-underscore> { <letter-or-underscore-or-digit> }
8.2. Overall structure#
<shader-file> ::= { <global-declaration> }
<global-declaration> ::= <function-declaration>
\(~~~~~~~~~~\) | <struct-declaration>
\(~~~~~~~~~~\) | <shader-declaration>
<shader-declaration> ::=
\(~~~~~~~~~~~~\) \(~~~~~~~~~~\)
<shadertype> <identifier> <metadata-block-opt>
“(” <shader-formal-params-opt> “)” “{” <statement-list> “}”
<shadertype> ::= “displacement” | “shader” | “surface” | “volume”
<shader-formal-params> ::= <shader-formal-param> { “,” <shader-formal-param> }
<shader-formal-param> ::= <outputspec> <typespec> <identifier>
<initializer> <metadata-block-opt>
\(~~~~~~~~~~\) | <outputspec> <typespec> <identifier> <arrayspec>
<initializer-list> <metadata-block-opt>
<metadata-block> ::= “[[” <metadata> { “,” <metadata> } “]]”
<metadata> ::= <simple-typespec> <identifier> <initializer>
8.3. Declarations#
<function-declaration> ::=
\(~~~~~~~~~~~~\) <typespec> <identifier>
“(” <function-formal-params-opt> “)” “{” <statement-list> “}”
<function-formal-params> ::= <function-formal-param> { “,” <function-formal-param> }
<function-formal-param> ::= <outputspec> <typespec> <identifier> <arrayspec-opt>
<outputspec> ::= “output” | \(\epsilon\)
<struct-declaration> ::= “struct” <identifier> “{” <field-declarations> “}” “;”
<field-declarations> ::= <field-declaration> { <field-declaration> }
<field-declaration> ::= <typespec> <typed-field-list> “;”
<typed-field-list> ::= <typed-field> { “,” <typed-field> }
<typed-field> ::= <identifier> <arrayspec-opt>
<local-declaration> ::= <function-declaration>
\(~~~~~~~~~~\) | <variable-declaration>
<arrayspec> ::= “[” <integer> “]”
\(~~~~~~~~~~\) | “[” “]”
<variable-declaration> ::= <typespec> <def-expressions> “;”
<def-expressions> ::= <def-expression> { “,” <def-expression> }
<def-expression> ::= <identifier> <initializer-opt>
\(~~~~~~~~~~\) | <identifier> <arrayspec> <initializer-list-opt>
<initializer> ::= “=” <expression>
<initializer-list> ::= “=” <compound-initializer>
<compound-initializer> ::= “{” <init-expression-list> “}”
<init-expression-list> ::= <init-expression> { “,” <init-expression> }
<init-expression> ::= <expression> | <compound-initializer>
<typespec> ::= <simple-typename>
\(~~~~~~~~~~\) | “closure” <simple-typename>
\(~~~~~~~~~~\) | <identifier-structname>
<simple-typename> ::= “color” | “float” | “matrix” | “normal” | “point” | “string” | “vector” | “void”
8.4. Statements#
<statement-list> ::= <statement> { <statement> }
<statement> ::=
<compound-expression-opt> “;”
\(~~~~~~~~~~\) | <scoped-statements>
\(~~~~~~~~~~\) | <local-declaration>
\(~~~~~~~~~~\) | <conditional-statement>
\(~~~~~~~~~~\) | <loop-statement>
\(~~~~~~~~~~\) | <loopmod-statement>
\(~~~~~~~~~~\) | <return-statement>
<scoped-statements> ::= “{” <statement-list-opt> “}”
<conditional-statement> ::=
\(~~~~~~~~~~~~\) “if” “(” <compound-expression> “)” <statement>
\(~~~~~~~~~~\) | “if” “(” <compound-expression> “)” <statement> “else” <statement>
<loop-statement> ::=
\(~~~~~~~~~~~~\) “while” “(” <compound-expression> “)” <statement>
\(~~~~~~~~~~\) | “do” <statement> “while” “(” <compound-expression> “)” “;”
\(~~~~~~~~~~\) | “for” “(” <for-init-statement-opt> <compound-expression-opt> “;”
<compound-expression-opt> “)” <statement>
<for-init-statement> ::=
\(~~~~~~~~~~~~\) <expression-opt> “;”
\(~~~~~~~~~~\) | <variable-declaration>
<loopmod-statement> ::= “break” “;”
\(~~~~~~~~~~\) | “continue” “;”
<return-statement> ::= “return” <expression-opt> “;”
8.5. Expressions#
<expression-list> ::= <expression> { “,” <expression> }
<expression> ::= <number>
\(~~~~~~~~~~\) | <stringliteral>
\(~~~~~~~~~~\) | <type-constructor>
\(~~~~~~~~~~\) | <incdec-op> <variable-ref>
\(~~~~~~~~~~\) | <expression> <binary-op> <expression>
\(~~~~~~~~~~\) | <unary-op> <expression>
\(~~~~~~~~~~\) | “(” <compound-expression> “)”
\(~~~~~~~~~~\) | <function-call>
\(~~~~~~~~~~\) | <assign-expression>
\(~~~~~~~~~~\) | <ternary-expression>
\(~~~~~~~~~~\) | <typecast-expression>
\(~~~~~~~~~~\) | <variable-ref>
\(~~~~~~~~~~\) | <compound-initializer>
<compound-expression> ::= <expression> { “,” <expression> }
<variable-lvalue> ::= <identifier> <array-deref-opt> <component-deref-opt>
\(~~~~~~~~~~\) | <variable_lvalue> “[” <expression> “]”
\(~~~~~~~~~~\) | <variable_lvalue> “.” <identifier>
<variable-ref> ::= <identifier> <array-deref-opt>
<array-deref> ::= “[” <expression> “]”
<component-deref> ::= “[” <expression> “]”
\(~~~~~~~~~~\) | “.” <component-field>
<component-field> ::= “x” | “y” | “z” | “r” | “g” | “b”
<binary-op> ::= “*” | “/” | “%”
\(~~~~~~~~~~\) | “+” | “-”
\(~~~~~~~~~~\) | “<<” | “>>”
\(~~~~~~~~~~\) | “<” | “<=” | “>” | “>=”
\(~~~~~~~~~~\) | “==” | “!=”
\(~~~~~~~~~~\) | “&”
\(~~~~~~~~~~\) | “^”
\(~~~~~~~~~~\) | “|”
\(~~~~~~~~~~\) | “&&” | “and”
\(~~~~~~~~~~\) | “||” | “or”
<unary-op> ::= “-” | “~” | “!” | “not”
<incdec-op> ::= “++” | “–”
<type-constructor> ::= <typespec> “(” <expression-list> “)”
<function-call> ::= <identifier> “(” <function-args-opt> “)”
<function-args> ::= <expression> { “,” <expression> }
<assign-expression> ::= <variable-lvalue> <assign-op> <expression>
<assign-op> ::= “=” | “*=” | “/=” | “+=” | “-=” | “&=” | “|=” | “^=” | “<<=” | “>>=”
<ternary-expression> ::= <expression> “?” <expression> “:” <expression>
<typecast-expression> ::= “(” <simple-typename> “)” <expression>