AntLR4:为Dockefile编写语法

时间:2016-11-26 16:31:28

标签: antlr grammar antlr4 dockerfile

我试图写一个能识别 dockerfile 的语法。 (无上下文语法) 长话短说,dockerfiles是由命令组成的文本文件。 命令可以是单行或多行,并由其名称标识。

最简单的dockerfile命令示例:

FROM anImageNameThatCanContainsPrettyMuchAnythingButWS

EXPOSE aNumber

有一些更复杂的命令,例如:

ADD aPath anotherPath

COPY aPath anotherPath

ENV aKey=aValue

这是RUN命令中最复杂的命令。 RUN命令基本上可以是任何 shell 命令,因此可以是任何命令。我唯一想要实现的是分裂' RUN的{​​{1}}个命令。

到目前为止我做了什么:

&&

那有什么不对? 首先grammar Dockerfile; dockerfile: ((COMMENT | command))+ EOF; COMMENT : ( '#' ~[\r\n]* '\r'? '\n' | '/*' .*? '*/' ) -> skip ; command: one_line | run; one_line: (from | env | entrypoint | maintainer | workdir | add | copy | expose) (NEWLINE)*; from: FROM ANYKEYS; maintainer: MAINTAINER ANYKEYS ANYKEYS; env: ENV ANYKEYS '=' ANYKEYS; entrypoint: ENTRYPOINT ANYKEYS; workdir: WORKDIR ANYKEYS; add: ADD .*?; copy: COPY src dest; src: ANYKEYS | '.'; dest: ANYKEYS | '.'; expose: EXPOSE NUMBER; run: RUN body NEWLINE; body: shellCmd (SHELLAND shellCmd)* ; shellCmd: ANYKEYS+; SHARP: '#'; FROM: [fF][rR][oO][mM]; ENV: [eE][nN][vV]; RUN: [rR][uU][nN]; ENTRYPOINT: [eE][nN][tT][rR][yY][pP][oO][iI][nN][tT]; MAINTAINER: [mM][aA][iI][nN][tT][aA][iI][nN][eE][rR]; WORKDIR: [wW][oO][rR][kK][dD][iI][rR]; SHELLAND: '&&' | ('\\' NEWLINE '&&'); ADD: [aA][dD][dD]; COPY: [cC][oO][pP][yY]; EXPOSE: [eE][xX][pP][oO][sS][eE]; NUMBER: [0-9]+; LETTER: [a-zA-Z]; ANYKEYS: (LETTER | NUMBER | ':' | '_' | '-' | '/' | '|' | '"' | '=' | '*' | '\\' | '\'' | '+' | ']' | '[' | '{' | '}' | ';' | '!' | '~' | '.' | '–' | '$' | '<' | '>' | '@' | ',')+; NEWLINE: ('\n' | '\r')+; WS : ((' ' | '\t')+) -> skip; 规则是ulgy但我可以找到更好的方法来做到这一点。 接下来,ANYKEYS无法正常工作,产生RUN exit 9000错误,因为extraneous input '9000' expecting {SHELLAND, ANYKEYS, NEWLINE}应与ANYKEYS规则中的NUMBER匹配,所以我无法理解

我有点迷失,不明白为什么它不符合这样的输入,并且不知道如何以更好的方式做到这一点

感谢您的帮助和建议!

1 个答案:

答案 0 :(得分:0)

我不熟悉AntLR4,但是对于你的语法来说,包含一些指令的多种形式是很重要的。

以下说明有两种形式:

RUN
ADD
COPY
ENTRYPOINT
HEALTHCHECK

以下说明有三种形式:

CMD

RUN

RUN指令有两种形式:

RUN <command>                          # (shell form, the command is run in a shell
                                       #  which by default is /bin/sh -c on Linux
                                       #  or cmd /S /C on Windows)

RUN ["executable", "param1", "param2"] # (exec form)

ADD

ADD指令有两种形式:

ADD <src>... <dest>
ADD ["<src>",... "<dest>"] # (this form is required for paths containing whitespace)

COPY

COPY指令有两种形式:

COPY <src>... <dest>
COPY ["<src>",... "<dest>"] # (this form is required for paths containing whitespace)

入口点

ENTRYPOINT指令有两种形式:

ENTRYPOINT ["executable", "param1", "param2"] # (exec form, preferred)
ENTRYPOINT command param1 param2              # (shell form)

健康检查

HEALTHCHECK指令有两种形式:

HEALTHCHECK [OPTIONS] CMD command # (check container health by running a command inside the container)
HEALTHCHECK NONE                  # (disable any healthcheck inherited from the base image)

CMD

CMD指令有三种形式:

CMD ["executable","param1","param2"] # (exec form, this is the preferred form)
CMD ["param1","param2"]              # (as default parameters to ENTRYPOINT)
CMD command param1 param2            # (shell form)

有关每个命令的更多信息和示例,请参阅:https://docs.docker.com/engine/reference/builder/