WHITESPACE = _{ (" " | "\t") } // identifiers identifier = { "AttributeBegin" | "AttributeEnd" | "ActiveTransform" | "AreaLightSource" | "Accelerator" | "ConcatTransform" | "CoordinateSystem" | "CoordSysTransform" | "Camera" | "Film" | "Integrator" | "Include" | "Identity" | "LightSource" | "LookAt" | "MakeNamedMaterial" | "MakeNamedMedium" | "Material" | "MediumInterface" | "NamedMaterial" | "ObjectBegin" | "ObjectEnd" | "ObjectInstance" | "PixelFilter" | "ReverseOrientation" | "Rotate" | "Shape" | "Sampler" | "Scale" | "TransformBegin" | "TransformEnd" | "Transform" | "Translate" | "TransformTimes" | "Texture" | "WorldBegin" | "WorldEnd" } // rules in alphabetical order // Accelerator // CoordinateSystem // Identity // TransformTimes // comments comment_line = { "#" ~ (!NEWLINE ~ ANY)* ~ NEWLINE } trailing_comment = { "#" ~ (!NEWLINE ~ ANY)* } // statements remaining_line = { (!(NEWLINE | "#") ~ ANY)* } statement_line = { identifier ~ remaining_line ~ (trailing_comment)? ~ NEWLINE } // count empty lines later empty_line = { NEWLINE } // catch any lines left to do remaining_params = { (!(NEWLINE | "#") ~ ANY)* } todo_line = { remaining_params ~ (trailing_comment)? ~ NEWLINE } // main .pbrt file pbrt = { SOI ~ (comment_line | statement_line | empty_line | todo_line )* ~ EOI } // single lines with all parameters empty_string = { "\"" ~ "\"" } string = { ("\"" ~ ident ~ "\"") | ("\"" ~ filename ~ "\"") } type_name = { "\"" ~ ident ~ "\"" } ident = { (ASCII_ALPHA | "_" | "|" | ASCII_DIGIT) ~ (ASCII_ALPHA | " " | "_" | "|" | "-" | ":" | "." | "#" | "(" | ")" | ASCII_DIGIT)* } file_name = { "\"" ~ filename ~ "\"" } filename = { ("/" | "./" ~ ("../")? | "../" ~ ("../")?)? ~ // optional (can be a full or relative path) (ASCII_ALPHA | "_") ~ (ASCII_ALPHA | "_" | "-" | "+" | "." | "/" | '0'..'9')* } type_params = { "Texture" ~ string ~ string ~ string ~ parameter* | "Material" ~ (empty_string | string) ~ parameter* | !("MediumInterface") ~ identifier ~ (type_name | file_name) ~ parameter* } name_and_or_params = { // identifier "type" parameter-list type_params | // predetermined number of arguments of predetermined type active_transform | concat_transform | look_at | medium_interface | rotate | scale | transform | translate | // catch others remaining_line } // ActiveTransform [ StartTime | EndTime | All ] all = { "All" } start_time = { "StartTime" } end_time = { "EndTime" } active_transform = { ("ActiveTransform" ~ all) | ("ActiveTransform" ~ start_time) | ("ActiveTransform" ~ end_time) } // ConcatTransform m00 .. m33 concat_transform = { ("ConcatTransform" ~ lbrack ~ // followed by 16 numbers: number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ rbrack) | ("ConcatTransform" ~ // followed by 16 numbers: number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number) } // LookAt eye_x eye_y eye_z look_x look_y look_z up_x up_y up_z look_at = { "LookAt" ~ // followed by 9 numbers: // eye_x eye_y eye_z number ~ number ~ number ~ // look_x look_y look_z number ~ number ~ number ~ // up_x up_y up_z number ~ number ~ number } // MediumInterface "" "vol" medium_interface = { "MediumInterface" ~ (empty_string | string) ~ (empty_string | string) } // Rotate angle x y z rotate = { "Rotate" ~ // followed by 4 numbers: number ~ number ~ number ~ number } // Scale x y z scale = { "Scale" ~ // followed by 3 numbers: number ~ number ~ number } // Transform m00 .. m33 transform = { ("Transform" ~ lbrack ~ // followed by 16 numbers: number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ rbrack) | ("Transform" ~ // followed by 16 numbers: number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number ~ number) } // Translate x y z translate = { "Translate" ~ // followed by 3 numbers: number ~ number ~ number } // helpers lbrack = { "[" } rbrack = { "]" } // NUMBER -+?(0-9+|((0-9+\.0-9*)|(\.0-9+)))(eE-+?0-9+)? number = @{ ("-" | "+")? ~ // optional sign, followed by ( ( ("." ~ '0'..'9'+) // dot and digits | // or ('0'..'9'+ ~ "." ~ '0'..'9'*) // digits, dot, and (optional digits) ) | // or '0'..'9'+ // just digits ) ~ ( // followed by (optional) ("e" | "E") ~ // 'e' or 'E', followed by ("-" | "+")? ~ // optional sign, followed by '0'..'9'+ // digits )? } integer = @{ ("-" | "+")? ~ // optional sign, followed by ( '1'..'9' ~ // at least one non-zero digit, followed by '0'..'9'* // just digits ) | // or '0'..'9' // single digit } parameter = { bool_param | blackbody_param | float_param | integer_param | point2_param | point_param | normal_param | rgb_param | spectrum_param | string_param | texture_param | vector_param } bool_param = { ("\"bool" ~ ident ~ "\"" ~ lbrack ~ string ~ rbrack) | ("\"bool" ~ ident ~ "\"" ~ string) } blackbody_param = { ("\"blackbody" ~ ident ~ "\"" ~ lbrack ~ number ~ number+ ~ rbrack) } float_param = { ("\"float" ~ ident ~ "\"" ~ lbrack ~ number+ ~ rbrack) | ("\"float" ~ ident ~ "\"" ~ number) } string_param = { "\"string" ~ ident ~ "\"" ~ lbrack ~ string ~ rbrack | "\"string" ~ ident ~ "\"" ~ string } integer_param = { ("\"integer" ~ ident ~ "\"" ~ lbrack ~ integer+ ~ rbrack) | ("\"integer" ~ ident ~ "\"" ~ integer) } point2_param = { "\"point2" ~ ident ~ "\"" ~ lbrack ~ number+ ~ rbrack } point_param = { "\"point" ~ ident ~ "\"" ~ lbrack ~ number+ ~ rbrack } vector_param = { "\"vector" ~ ident ~ "\"" ~ lbrack ~ number ~ number ~ number ~ rbrack } normal_param = { "\"normal" ~ ident ~ "\"" ~ lbrack ~ number+ ~ rbrack } rgb_param = { ("\"rgb" ~ ident ~ "\"" ~ lbrack ~ number ~ number ~ number ~ rbrack) | ("\"color" ~ ident ~ "\"" ~ lbrack ~ number ~ number ~ number ~ rbrack) } // TODO: "spectrum Kd" [ 300 .3 400 .6 410 .65 415 .8 500 .2 600 .1 ] // or // "spectrum Kd" "filename" spectrum_param = { "\"spectrum" ~ ident ~ "\"" ~ string } texture_param = { "\"texture" ~ ident ~ "\"" ~ lbrack ~ string ~ rbrack | "\"texture" ~ ident ~ "\"" ~ string }