当前位置: 首页 > 知识库问答 >
问题:

生成文件语法

饶曦之
2023-03-14

有没有精确的makefile语法定义?或者至少是一些常见的子集,因为我猜有一些口味。这种语法可以用来编写解析器。

GNU Make手册似乎没有那么精确。基于该文档为makefile编写解析器需要一些猜测和尝试。

我在ANTLR邮件列表中也发现了类似的问题。但究竟是哪一种暗示了答案仍然没有答案。。。

共有2个答案

邓嘉致
2023-03-14

我为自己制作了GNU Make的语法,你可以在下面找到lexer的语法和概述。它并不完美,但它可以作为想要更好东西的人的起点。一些附加信息和背景信息在帖子中。

实现:lexer和parser。

野牛的语法垃圾

/* Assign lower precedence to NL. */
/* %precedence NL */
/* %precedence COMMENT "ifdef" "ifndef" "ifeq" "ifneq" */

  1  makefile: statements "end of file"
  2          | "end of file"

  3  statements: br
  4            | statement
  5            | statements br
  6            | statements statement

  7  conditional: if_eq_kw condition statements_opt "endif" comment_opt br
  8             | if_eq_kw condition statements_opt "else" statements_opt "endif" comment_opt br
  9             | if_eq_kw condition statements_opt "else" conditional
 10             | if_def_kw identifier statements_opt "endif" comment_opt br
 11             | if_def_kw identifier statements_opt "else" statements_opt "endif" comment_opt br
 12             | if_def_kw identifier statements_opt "else" conditional

 13  conditional_in_recipe: if_eq_kw condition recipes_opt "endif" comment_opt
 14                       | if_eq_kw condition recipes_opt "else" recipes_opt "endif" comment_opt
 15                       | if_eq_kw condition recipes_opt "else" conditional_in_recipe
 16                       | if_def_kw identifier recipes_opt "endif" comment_opt
 17                       | if_def_kw identifier recipes_opt "else" recipes_opt "endif" comment_opt
 18                       | if_def_kw identifier recipes_opt "else" conditional_in_recipe

 19  condition: '(' expressions_opt ',' expressions_opt ')'
 20           | SLIT SLIT

 21  define: "define" pattern definition "endef" br
 22        | specifiers "define" pattern definition "endef" br
 23        | "define" pattern ASSIGN_OP definition "endef" br
 24        | specifiers "define" pattern ASSIGN_OP definition "endef" br

 25  definition: comment_opt br
 26            | comment_opt br exprs_in_def br

 27  include: "include" expressions br

 28  statements_opt: comment_opt br
 29                | comment_opt br statements

 30  if_def_kw: "ifdef"
 31           | "ifndef"

 32  if_eq_kw: "ifeq"
 33          | "ifneq"

 34  statement: COMMENT
 35           | assignment br
 36           | function br
 37           | rule
 38           | conditional
 39           | define
 40           | include
 41           | export br

 42  export: "export"
 43        | "unexport"
 44        | assignment_prefix
 45        | assignment_prefix WS targets

 46  assignment: pattern ASSIGN_OP comment_opt
 47            | pattern ASSIGN_OP exprs_in_assign comment_opt
 48            | assignment_prefix ASSIGN_OP comment_opt
 49            | assignment_prefix ASSIGN_OP exprs_in_assign comment_opt

 50  assignment_prefix: specifiers pattern

 51  specifiers: "override"
 52            | "export"
 53            | "unexport"
 54            | "override" "export"
 55            | "export" "override"
 56            | "undefine"
 57            | "override" "undefine"
 58            | "undefine" "override"

 59  expressions_opt: %empty
 60                 | expressions

 61  expressions: expression
 62             | expressions WS expression

 63  exprs_nested: expr_nested
 64              | exprs_nested WS expr_nested

 65  exprs_in_assign: expr_in_assign
 66                 | exprs_in_assign WS expr_in_assign

 67  exprs_in_def: first_expr_in_def
 68              | br
 69              | br first_expr_in_def
 70              | exprs_in_def br
 71              | exprs_in_def WS expr_in_recipe
 72              | exprs_in_def br first_expr_in_def

 73  first_expr_in_def: char_in_def expr_in_recipe
 74                   | function expr_in_recipe
 75                   | char_in_def
 76                   | function

 77  exprs_in_recipe: expr_in_recipe
 78                 | exprs_in_recipe WS expr_in_recipe

 79  expression: expression_text
 80            | expression_function

 81  expr_nested: expr_text_nested
 82             | expr_func_nested

 83  expr_in_assign: expr_text_in_assign
 84                | expr_func_in_assign

 85  expr_in_recipe: expr_text_in_recipe
 86                | expr_func_in_recipe

 87  expression_text: text
 88                 | expression_function text

 89  expr_text_nested: text_nested
 90                  | expr_func_nested text_nested

 91  expr_text_in_assign: text_in_assign
 92                     | expr_func_in_assign text_in_assign

 93  expr_text_in_recipe: text_in_recipe
 94                     | expr_func_in_recipe text_in_recipe

 95  expression_function: function
 96                     | '(' exprs_nested ')'
 97                     | expression_text function
 98                     | expression_function function

 99  expr_func_nested: function
100                  | '(' exprs_nested ')'
101                  | expr_func_nested function
102                  | expr_text_nested function

103  expr_func_in_assign: function
104                     | expr_func_in_assign function
105                     | expr_text_in_assign function

106  expr_func_in_recipe: function
107                     | expr_func_in_recipe function
108                     | expr_text_in_recipe function

109  function: VAR
110          | "$(" function_name ")"
111          | "$(" function_name WS arguments ")"
112          | "$(" function_name ',' arguments ")"
113          | "$(" function_name ':' expressions ")"
114          | "$(" function_name ASSIGN_OP expressions ")"

115  function_name: function_name_text
116               | function_name_function

117  function_name_text: function_name_piece
118                    | function_name_function function_name_piece

119  function_name_piece: CHARS
120                     | function_name_piece CHARS

121  function_name_function: function
122                        | function_name_text function

123  arguments: %empty
124           | argument
125           | arguments ','
126           | arguments ',' argument

127  argument: expressions

128  rule: targets colon prerequisites NL
129      | targets colon prerequisites recipes NL
130      | targets colon assignment NL

131  target: pattern

132  pattern: pattern_text
133         | pattern_function

134  pattern_text: identifier
135              | pattern_function identifier

136  pattern_function: function
137                  | pattern_text function
138                  | pattern_function function

139  prerequisites: %empty
140               | targets

141  targets: target
142         | targets WS target

143  recipes: recipe
144         | recipes recipe

145  recipes_opt: comment_opt NL
146             | comment_opt recipes NL

147  recipe: LEADING_TAB exprs_in_recipe
148        | NL conditional_in_recipe
149        | NL COMMENT

150  identifier: CHARS
151            | ','
152            | '('
153            | ')'
154            | identifier CHARS
155            | identifier keywords
156            | identifier ','
157            | identifier '('
158            | identifier ')'

159  text: char
160      | text char

161  text_nested: char_nested
162             | text_nested char_nested

163  text_in_assign: char_in_assign
164                | text_in_assign char_in_assign

165  text_in_recipe: char_in_recipe
166                | text_in_recipe char_in_recipe

167  char: CHARS
168      | SLIT
169      | ASSIGN_OP
170      | ':'

171  char_nested: char
172             | ','

173  char_in_assign: char_nested
174                | '('
175                | ')'
176                | keywords

177  char_in_def: char
178             | '('
179             | ')'
180             | ','
181             | COMMENT
182             | "include"
183             | "override"
184             | "export"
185             | "unexport"
186             | "ifdef"
187             | "ifndef"
188             | "ifeq"
189             | "ifneq"
190             | "else"
191             | "endif"
192             | "define"
193             | "undefine"

194  char_in_recipe: char_in_assign
195                | COMMENT

196  keywords: "include"
197          | "override"
198          | "export"
199          | "unexport"
200          | "ifdef"
201          | "ifndef"
202          | "ifeq"
203          | "ifneq"
204          | "else"
205          | "endif"
206          | "define"
207          | "endef"
208          | "undefine"

209  br: NL
210    | LEADING_TAB

211  colon: ':'
212       | ':' ':'

213  comment_opt: %empty
214             | COMMENT

一些lexer的细节

  • 所有的和几乎所有的引号都是文字。
  • )::=

空格处理是很棘手的:lexer应该忽略它,除非之前返回的令牌需要后面的空格。

未配对的扩展的结束部分(})只是它们自己。而$(...)${...}的内容永远不是关键字。

解决困惑

两条评论表达了同样的问题:

另一方面,你make以某种方式解析makefile,允许一些,拒绝另一些。。。

解析语言不需要语法。然而,拥有它是件好事。

一般来说,可能的语言比形式语法更多,因为语法有排除某些语言的约束。

我猜make在管理状态的同时读取输入并处理它,这样在每一点上它都知道下一步可以接受什么样的输入以及如何处理它。正式语言倾向于无上下文,这意味着它们不会记录自己的状态。正是这种差距,使得很难形式化make的语言,即使在没有语法的情况下实现它仍然是可能的。

蒋芷阳
2023-03-14

似乎gnu make没有官方语法,而且。。。

为make编写语法是很棘手的,因为语法是极其依赖上下文的。

正如Paul D.Smith在gnu make邮件列表中的一条消息中所说。保罗·D·史密斯是gnu make的官方维护者。

 类似资料:
  • 使用 Hexo 生成静态文件快速而且简单。 $ hexo generate 监视文件变动 Hexo 能够监视文件变动并立即重新生成静态文件,在生成时会比对文件的 SHA1 checksum,只有变动的文件才会写入。 $ hexo generate --watch 完成后部署 您可执行下列的其中一个命令,让 Hexo 在生成完毕后自动部署网站,两个命令的作用是相同的。 $ hexo generate

  • 好的,所以最近我一直在尝试在Android Studio(1.1.0)上运行我的应用程序,但是每次尝试运行的时候,都会弹出以下错误: 注意:我最近导入了一个jar文件,从那以后,问题就开始了。不确定这是否重要。

  • 我正在尝试将一个网站从Heroku迁移到AWS,但在代码构建方面遇到了麻烦。源代码在GitHub上,我使用的是CodePipeline-CodeBuild-Elastic Beanstalk。管道运行良好,代码似乎正在向Elastic Beanstalk过渡。然而,我被困在代码构建步骤。(buildspec.yml如下所示) 日志似乎可以很好地运行命令,但是当我将构建输出到S3存储桶时,没有构建文

  • 问题内容: 我正在尝试通过学习本教程来学习hyperjaxb 。我遵循了所有指示,直到标题部分。这包括以下步骤: 但是什么也没产生。没有目录,也没有。我对整个目录结构进行了关键字搜索,以确认运行后这些资源不存在。我也将目录结构导入到新的Eclipse Maven项目中,并在新的Eclipse Maven项目中进行了尝试,但同样缺少结果。 如何使本教程生成预期的生成文件? 另外,是否有更好的方法从x

  • 当我尝试使用Makefile命令生成proto文件时-,我得到这个错误- 当我运行which go时,我有: 哪个协议返回此- 下面是我的<代码>。zshrc看起来像: 我也安装了插件 请否则我应该添加我的以避免此错误吗?

  • 一直以来不会使用C++一直是我心头痛,不过学习Go从某种意义上补偿了我这个遗憾。 比如生成dll一直以来几乎就是C和C++的专利,现在我可以用Go轻松的实现这一点。 下面我使用一个实例来做到这一点,这个是我写的判断jpeg图是不是正向的一个Go的函数 package main import "C" import ( "fmt" "os" SunnyUtil "githu