% TXL Base Grammar for Gnu Makefiles % Jim Cordy, Ecole Polytechnique, March 2014 % Copyright 2014,2015 by James R. Cordy % Originally based on the Makefile grammar published in % "Build Code Analysis with Symbolic Evaluation" % Ahmed Tamrawi, Hoan Anh Nguyen, Hung Viet Nguyen, Tien N. Nguyen % ICSE 2012, pp. 650-660 % Version 1.5, 26 Nov 2015 % Version 1.4, 11 Sep 2014 % Makefiles are character-level sensitive #pragma -char -w 32000 comments '# end comments % We want to parse comments #pragma -comment tokens tab "\t" escaped_comment "\\\#" escaped_quote "\\\"" evallit "`[(\\`)#`]*`" ignore " " | " " charlit "'#'*'" end tokens define EOL [WS] [comment?] [newline] end define define WS [tabspace*] end define define tabspace [tab] | [space] end define define BSWS [WS] '\ [newline] [WS] end define % 1) Makefile → {Statement|Rule} define program [StatementOrRule*] end define define StatementOrRule [Statement] | [Rule] end define % 2) Statement → Assignment|Definition|FunctionCall|Foreach|If|Directive define Statement [IfStatement] % order matters! | [FunctionCallStatement] % includes Foreach | [Definition] | [Directive] | [Assignment] | [CommentStatement] | [NullStatement] end define define NullStatement [EOL] end define define CommentStatement [WS] [comment] [EOL] end define define FunctionCallStatement [FunctionCall] [EOL] end define % 3) Assignment → [private|export|override] (Id|Expr) (+=|:=|=) Expr define Assignment [WS] [PrivateExportOverride?] [WS] [Id] [WS] [AssignmentOp] [WS] [BSWS?] [Expr?] [AssignmentContinuation*] [EOL?] end define define AssignmentContinuation [EOL] [tabspace] [WS] [Expr] end define define PrivateExportOverride 'private | 'export | 'override end define compounds += := ?= end compounds define AssignmentOp '+= | ':= | '?= | '= end define % 4) Id → IdPart ((WS)* IdPart)* define Id [IdPart+] end define % 5) IdPart→ [^WS=:;\n]+ define IdPart [IdToken] | [Evaluation] | [FunctionCall] end define tokens id "[\a_%][\a\d_-./%]*" end tokens define IdToken [id] ['@ ?] | [number] | '- | '% | '. | '/ | '* | ':. | ': '% ['= ?] | '+ | '- ['< ?] | ', [not space] | '\ [space] | '= '. end define % 6) Definition → [private|export|override] define Id +=|:=|= \n ∼\n % endef define Definition [WS] [PrivateExportOverride?] [WS] 'define [WS] [DefId] [WS] [AssignmentOp?] [EOL] [StatementOrRuleOrRecipeExpr*] [EndDef] [EOL] end define define EndDef [WS] 'endef end define define StatementOrRuleOrRecipeExpr [not EndDef] [RealStatementOrRuleOrRecipeExpr] end define define RealStatementOrRuleOrRecipeExpr [StatementOrRule] | [WSRecipeExpr] end define define WSRecipeExpr [WS] [RecipeExpr] end define define DefId [id] [DashId*] end define define DashId '- [id] end define % 7) FunctionCall → $(FunctionName [Expr [{,Expr}]] ) define FunctionCall '$ '( [FunctionName] [tabspace] [list WSExpr+] [WS] ') end define define WSExpr [WS] [Term] [tabspace_WSExpr*] end define define tabspace_WSExpr [tabspace] [WSTerm] end define % 8) FunctionName → subst|patsubst|strip|findstring|filter|... define FunctionName [id] [dash_id*] end define define dash_id '- [id] end define % 9) Expr → Term{[WS] Term} define Expr [WSTerm+] end define define WSTerm [WS] [Term] end define % 10) Term → FunctionCall|ELiteral|Evaluation|Foreach|If define Term [IfStatement] % order matters | [AutoEval] | [Id] % includes Evaluation, FunctionCall and Foreach | [not Id] [Literal] | [BSWS] % empty line? end define % 11) ELiteral → WLiteral ((\WS)* WLiteral)* % 12) WLiteral → [^WS \n]+ define Literal [NotWSNL+] end define define NotWSNL [not WSNL] [token] | '\ [BSSPTB] end define define BSSPTB [not newline] [token] end define define WSNL [tabspace] | [newline] | '\ end define % 13) Evaluation → $(Id|Expr) define Evaluation '$ ['$ ?] '( [Id] ') % second $ is technically an escaped var ref in a macro | '$ ['$ ?] '{ [Id] '} % bash-style variable | '$ [id] % observed, linux | '$ '( [Id] ': [Assignment] ') % observed, Gnu end define % 14) Rule → Expr (: | ::) (Assignment| | Expr) [Recipe] define Rule [space?] [Targets] ': [': ?] [Patterns] [Dependencies] [Recipe] end define define Targets [TargetBSWS+] end define define TargetBSWS [BSWS] % continuation of targets | [Target] end define define Target [Id] [WS] end define define Patterns [Pattern*] end define define Pattern [WS] [Id] [WS] ': end define define Dependencies [DependencyBSWS*] end define define DependencyBSWS [BSWS] % continuation of targets | [Dependency] end define define Dependency [WSTerm] end define % 15) Recipe → (;|\n\t)RecipeExpr{\n\t RecipeExpr} define Recipe [SemiRecipeExpr?] [EOL] [TabRecipeExpr*] end define define AtMinusPlus '@ | '- | '+ end define define SemiRecipeExpr [WS] '; [WS] [AtMinusPlus*] [RecipeExpr] end define define TabRecipeExpr [IfRecipe] | [tab] [WS] [AtMinusPlus*] [RecipeExpr] [EOL] | [EOL] % commented out lines end define % 16) RecipeExpr → RecipeTerm{ WS RecipeTerm} define RecipeExpr [RecipeTerm] [WSRecipeTerm*] end define define WSRecipeTerm [WS] [RecipeTerm] end define % 17) RecipeTerm → FunctionCall|Evaluation|RecipeLiteral|AutoEval|Foreach|If % 18) RecipeLiteral → [^\n]+ define RecipeTerm [IfRecipe] | [AutoEval] | [Id] % includes Evaluation, FunctionCall and Foreach | [not Id] [Literal] | [BSWS] % empty line? end define % 19) AutoEval → $@|$<|$?|$^|$+|... compounds $@ $< $? $^ $+ $* '$% '$| end compounds define AutoEval '$@ | '$< | '$? | '$^ | '$+ | '$* | '$% | '$| % | ... end define % 20) Foreach → $(foreach Id,Expr,Expr|RecipeExpr) define Foreach '$ '( 'foreach [WS] [ForIterator] ') end define define ForIterator [Id] , [Expr] , [Expr] | [RecipeExpr] end define % 21) If → (((ifeq|ifneq) (Expr,Expr) | ((ifdef|ifndef) Expr)) % {Rule|Statement}|RecipePart [else {Rule|Statement}|RecipePart] endif) | % $(if Expr,Expr|RecipeExpr[,Expr|RecipeExpr])) define IfStatement [WS] [IfEqNeq] [WS] [IfEqExpr] [EOL] [StatementOrRuleOrRecipePart*] [IfElse?] [EndIf] [EOL] | [WS] [IfDef] [WS] [IfDefExpr] [EOL] [StatementOrRuleOrRecipePart*] [IfElse?] [EndIf] [EOL] end define define IfFunction [WS] '$ '( 'if [WS] [IfRecipeExpr] ') end define keys endif % must be distinguished! end keys define EndIf [WS] 'endif end define define StatementOrRuleOrRecipePart [not EndIf] [RealStatementOrRuleOrRecipePart] end define define RealStatementOrRuleOrRecipePart [StatementOrRule] | [RecipePart] end define define IfEqNeq 'ifeq | 'ifneq end define define IfDef 'ifdef | 'ifndef end define define IfEqExpr '( [NCWSExpr*] ', [WSExpr*] [WS] ') | [WSExpr] [WSExpr] end define define NCWSExpr [WS] [not ',] [WSExpr] end define define IfDefExpr [Id] end define define IfElse [WS] 'else [EOL] [StatementOrRuleOrRecipePart*] end define define IfRecipe [IfStatement] end define define IfRecipeExpr [list WSExprOrRecipeExpr+] end define define WSExprOrRecipeExpr [WS] [ExprOrRecipeExpr] end define define ExprOrRecipeExpr [Expr] | [RecipeExpr] end define % 22) RecipePart → \n\t RecipeExpr{\n\t RecipeExpr} define RecipePart [TabRecipeExpr+] end define % 23) Directive → Include|Vpath|Export|Undefine define Directive [Include] | [Vpath] | [Export] | [Undefine] end define % 24) Include → (include|sinclude|-include) Expr define Include [WS] [IncludeOrSInclude] [WS] [Expr] [EOL] end define define IncludeOrSInclude 'include | 'sinclude | '- 'include end define % 25) Vpath → vpath [Expr] define Vpath [WS] 'vpath [WS] [Expr?] [EOL] end define % 26) Export → (unexport|export) [Expr] define Export [WS] [UnexportOrExport] [WS] [Expr?] [EOL] end define define UnexportOrExport 'unexport | 'export end define % 27) Undefine → [override] undefine Id define Undefine [WS] ['override ?] [WS] 'undefine [WS] [Id] [EOL] end define