# rule based checks if given TIFF is a specific baseline TIFF
#
# author: Andreas Romeyke, 2015-2017
# licensed under conditions of libtiff
# (see http://libtiff.maptools.org/misc.html)
#

start           <- ( Line )+ EndOfFile
Line            <- LineType EndOfLine		
LineType        <- TagLine				       		      
                 / ModeLine				       
		 / CommentLine
                 / SpaceLine
                 / IncludeLine
		 / < ( !EndOfLine .)+ >			       {fprintf(stderr, "REST: '%s'\n", yytext); }
CommentLine     <- '#' ( !EndOfLine .)*                        { commentline(); }
IncludeLine     <- 'include' OpenBracket < ( [A-Za-z0-9_./\-]+ ) > ClosingBracket { set_include ( yytext );  }
ModeLine        <- 'mode' OpenBracket < Mode > ClosingBracket  { int i = i_pop(); set_mode( i );  }
LogicalOr       <- 'logical_or' LogicalOrOpen LogicalOrList LogicalOrClose

LogicalOrOpen   <- OpenBracket                                 { set_rule_logical_open();}
LogicalOrClose  <- ClosingBracket                              { }

LogicalOrListElement   <- Any                                  { v_push( any ); incr_logical_elements();}
                 / Range                                       { v_push( range); incr_logical_elements();}
                 / Only                                        { v_push( only ); incr_logical_elements();}
                 / Number                                      { v_push( only ); incr_logical_elements();}
                 / NTupel                                      { v_push( ntupel); incr_logical_elements();}
                 / RegEx                                       { v_push( regex ); incr_logical_elements();}
                 / PrintableAscii                              { v_push( printable_ascii ); incr_logical_elements();}
LogicalOrList   <- LogicalOrListElement (Colon LogicalOrListElement)*

Mode            <- 'baseline'                                  { i_push(mode_baseline ); }
                 / 'enable_type_checks'                        { i_push(mode_enable_type_checks); }
                 / 'enable_offset_checks'                      { i_push(mode_enable_offset_checks); }
                 / 'enable_ifd_checks'                         { i_push(mode_enable_ifd_checks); }
                 / 'enhanced'                                  #/* TODO: later if all types of TIFF are supported */

TagLine         <- Tag Semicolon Requirements Semicolon Content { rule_addtag_config();  }
                 / Tag Semicolon Requirements Semicolon LogicalOr { set_rule_logical_close(); }
            
Tag             <- < Number >                                  {
                        int tag = i_pop();
                        /* rule_tagorder_in_dsl( tag ); */
                        if (tag < 254) set_parse_error("wrong tag (should be >253)", yytext);
                        else if (tag > 65535) set_parse_error("wrong tag (should be <65536)", yytext);
                        else settag( tag );
                }
TagReference    <- < Number >                                  {
                        int tag = i_pop();
                        if (tag < 254) set_parse_error("wrong tagreference (should be >253)", yytext);
                        else if (tag > 65535) set_parse_error("wrong tagreference (should be <65536)", yytext);
                        else settagref( tag );
                }
Semicolon       <- ';' ( Space )*
Requirements    <- 'mandatory'                                 { set_mandatory(); }
                 / IfDepends                                   { set_ifdepends(); }
                 / OptDepends                                  { set_optdepends(); }
                 / 'optional'                                  { set_optional(); }
IfDepends       <- 'depends' OpenBracket TagReference Dot ValueReference ClosingBracket

OptDepends      <- 'optdepends' OpenBracket TagReference Dot ValueReference ClosingBracket


Content          <- Any                                         { v_push( any ); }
                 / Range                                       { v_push( range); }
                 / Only                                        { v_push( only ); }
                 / NTupel                                      { v_push( ntupel ); reset_valuelist() }
                 / RegEx                                       { v_push( regex ); }
                 / PrintableAscii                              { v_push( printable_ascii ); }
                 / Datetime                                    { v_push( datetime ); }
                 / Iccprofile                                  { v_push( iccprofile ); }
#                 / SBit                                        { v_push( sbit ); }
Range           <- 'range' OpenBracket Number Colon Number ClosingBracket
Number          <- < '0x' ( [0-9a-f]+ ) >                      { i_push(strtol(yytext, NULL, 0) ); }
                 / '2^' < ( Digit )+ >                         { i_push(2<<atol(yytext) ); }
                 / < ( Digit )+ >                              { i_push(atol(yytext) );}
Colon           <- ',' (Space )*
Dot             <- '.' (Space )*
OpenBracket     <- '('
ClosingBracket     <- ')'

ValueList       <- Value (Colon Value)*
Value           <- Number                                      { incr_values(); }
NTupel          <- 'ntupel' OpenBracket ValueList ClosingBracket {int v=parser_state.valuelist; i_push(v); reset_valuelist(); }
ValueReference  <- Any                                         { parser_state.any_reference = any_ref; }
                 / Number                                      { parser_state.any_reference = only_ref; i_push(atol(yytext) );}
                 / RegEx                                       { parser_state.any_reference = regex_ref; }
                 / Range                                       { parser_state.any_reference = range_ref; }
                 / NTupel                                      { parser_state.any_reference = ntupel_ref; }
                 / Only                                        { parser_state.any_reference = only_ref; }
Only            <- 'only' OpenBracket Number ClosingBracket    {  }
#SBit            <- 'sbit'  OpenBracket < Digit > ClosingBracket{  i_push(atol(yytext) ); }
#                 / 'sbit'  OpenBracket Digit                   { set_parse_error("'sbit' expects a closing bracket", yytext); }
#                 / 'sbit'  OpenBracket                         { set_parse_error("'sbit' expects a digit", yytext); }
#                 / 'sbit'                                      { set_parse_error("'sbit' expects an open bracket", yytext); }
RegEx           <- 'regex' OpenBracket '"' < ( PCRE )* > '"' ClosingBracket { regex_push ( yytext ); }
Datetime        <- 'datetime'
Iccprofile      <- 'iccprofile'
PrintableAscii  <- 'printascii'
SpaceLine       <- ( Space )*
Space           <- ' ' / '\t'
Any             <- 'any'
Digit           <- [0-9]
EndOfLine       <- [\r\n]                                      {incrlineno();}
EndOfFile       <- !.
PCRE            <- EscapedPCRE
                 / [^"\\]
# FIXME: unescape char in yybuffer
EscapedPCRE     <- '\\' '\\'
                 / '\\' '"'


