grammar DockerfileRB::Dockerfile

rule dockerfile
  (
    comment |
    add | add_with_whitespace |
    arg |
    copy | copy_with_whitespace |
    cmd_exec | cmd_shell |
    entrypoint_exec | entrypoint_shell |
    env_with_whitespace | env_key_value |
    expose |
    healthcheck_none |
    from |
    label |
    maintainer |
    run_exec |
    run_shell |
    stopsignal |
    user |
    volume_json |
    volume_string |
    workdir |
    line_break
  )*
  {
    parsed = matches.map(&:value).compact
    value = Hash.new {|h,k| h[k] = [] }
    parsed.each{|p| value[p.class.name.split('::').last.downcase].push p }
    value
  }
end

rule add
  ('ADD' space arg_term:('--chown=' [a-zA-Z0-9.@/_\-\$\\]+ ':' [a-zA-Z0-9:.@/_\-\$\\]+)? space? src_term:(string) space dest_term:(string) ) <DockerfileRB::AddParser>
end

rule add_with_whitespace
  ('ADD' space arg_term:('--chown=' [a-zA-Z0-9.@/_\-\$\\]+ ':' [a-zA-Z0-9:.@/_\-\$\\]+)? space? '[' quote src_term:(string_with_whitespace) quote comma quote dest_term:(string_with_whitespace) quote ']' ) <DockerfileRB::AddParser>
end

rule arg
  ('ARG' space arg_name_term:(string) '=' arg_value_term:(string)) <DockerfileRB::ArgParser>
end

rule as
  ('AS' space as_term:(string)) {
    captures(:as_term)
  }
end

rule comment
  '#' space? (string_with_whitespace | '\'' | '=' | '"')* line_break
end

rule copy
  ('COPY' space arg_term:('--chown=' [a-zA-Z0-9.@/_\-\$\\]+ ':' [a-zA-Z0-9:.@/_\-\$\\]+)? space? src_term:(string) space dest_term:(string) ) <DockerfileRB::CopyParser>
end

rule copy_with_whitespace
  ('COPY' space arg_term:('--chown=' [a-zA-Z0-9.@/_\-\$\\]+ ':' [a-zA-Z0-9:.@/_\-\$\\]+)? space? '[' quote src_term:(string_with_whitespace) quote comma quote dest_term:(string_with_whitespace) quote ']' ) <DockerfileRB::CopyParser>
end

rule cmd_exec
  ('CMD' space '[' (quote cmd_term:(string) quote comma?)* ']') <DockerfileRB::CmdParser>
end

rule cmd_shell
  ('CMD' space (cmd_term:(string) space?)*) <DockerfileRB::CmdParser>
end

rule entrypoint_exec
  ('ENTRYPOINT' space '[' (quote entrypoint_term:(string) quote comma?)* ']') <DockerfileRB::EntrypointExecParser>
end

rule entrypoint_shell
  ('ENTRYPOINT' space (entrypoint_term:(string) space?)*) <DockerfileRB::EntrypointShellParser>
end

rule env_with_whitespace
  ('ENV' space key_term:(string) space value_term:(string_with_whitespace)) <DockerfileRB::EnvWhitespaceParser>
end

rule env_key_value
  ('ENV' space (key_term:(escaped_string) space? '=' quote? space? value_term:(escaped_string) quote? line_continuation?)+) <DockerfileRB::EnvKeyValueParser>
end

rule expose
  ('EXPOSE' space expose_term:(string)) <DockerfileRB::ExposeParser>
end

rule healthcheck_none
  'HEALTHCHECK NONE' <DockerfileRB::HealthcheckNoneParser>
end

rule from
  ('FROM' space from_term:(string) space? as?) <DockerfileRB::FromParser>
end

rule label
  ('LABEL' space label_term:(quote? string_with_whitespace quote? '=' quote? string_with_whitespace quote? line_continuation?)+) <DockerfileRB::LabelParser>
end

rule maintainer
  ('MAINTAINER' space maintainer_term:(string)) <DockerfileRB::MaintainerParser>
end

rule run_exec
  ('RUN' space '[' (quote run_term:(string_with_whitespace) quote comma?)* ']') <DockerfileRB::RunExecParser>
end

rule run_shell
  ('RUN' space (run_term:(run_string) space? line_continuation? (comment)*)*) <DockerfileRB::RunShellParser>
end

rule stopsignal
  ('STOPSIGNAL' space signal_term:(signal)) <DockerfileRB::StopsignalParser>
end

rule user
  ('USER' space user_term:(string)) <DockerfileRB::UserParser>
end

rule volume_string
  ('VOLUME' space (volume_term:(string) space?)* (']')?) <DockerfileRB::VolumeStringParser>
end

rule volume_json
  ('VOLUME' space '[' (quote volume_term:(string) quote comma?)* ']') <DockerfileRB::VolumeJSONParser>
end

rule workdir
  ('WORKDIR' space quote? workdir_term:(path) quote?) <DockerfileRB::WorkdirParser>
end

rule path
  [a-zA-Z0-9:.@/_\-\$\[\]\\]+
end

rule string
  [a-zA-Z0-9:;!#<>*&^,(){}+#.@/_\-\$\[\]\|$?]+
end

rule string_with_whitespace
  (string | ' ')+
end

rule escaped_string
  (escape? string_with_whitespace escape?)+
end

rule run_string
  [a-zA-Z0-9:;!#<>*&^,(){}+#.@/_\-\$\[\]\|$ ='"?]+ | '\\'
end

rule comma
  space? ',' space?
end

rule escape
  ('\\' &' ')*
end

rule quote
  space? '"' space?
end

rule line_continuation
  space? '\\' space? line_break
end

rule space
  [ \t]*
end

rule indent
  [ \t\r\n]*
end

rule line_break
  (space? "\n" | space? "\r\n") { nil }
end

rule signal
  [\d] | "SIG"[A-Z]+
end

end