start: (patch)*
patch: file_declaration instruction*

file_declaration: "file" string

?string: STRING | RAW_STRING | LONG_STRING

?instruction: insert
            | preg_replace
            | define_anchor

insert: "insert" location string

preg_replace: "preg_replace" range PATTERN string

define_anchor: "define_anchor" anchor affix PATTERN
             | "define_anchor" range_anchor "range" PATTERN

?affix: "before" | "after"

?location: LINE_NUMBER
         | CHAR_INDEX
         | LINE_COLUMN
         | anchor

range: "(" location "-" location ")"
     | range_anchor

anchor: "@" IDENTIFIER
range_anchor: "@$" IDENTIFIER

STRING: /"([^"\\]|\\.)*"/
RAW_STRING: /'[^']*'/
LONG_STRING: /<<\s*(?P<terminator>[^\n]+)\n.*\n(?P=terminator)/s
LINE_NUMBER: /ln\d+/
CHAR_INDEX: /ch\d+/
LINE_COLUMN: /ln\d+c\d+/
IDENTIFIER: /[a-zA-Z_][a-zA-Z0-9_]*/
PATTERN: /\/([^\/\\]|\\.)*\//

COMMENT: /#[^\r\n]+/

%ignore /[\t \f\n]+/
%ignore COMMENT