1# 2# puppetManifest.ctags --- multitable regex parser for Puppet's manifest file 3# 4# Copyright (c) 2017, Red Hat, Inc. 5# Copyright (c) 2017, Masatake YAMATO 6# 7# Author: Masatake YAMATO <yamato@redhat.com> 8# 9# This program is free software; you can redistribute it and/or 10# modify it under the terms of the GNU General Public License 11# as published by the Free Software Foundation; either version 2 12# of the License, or (at your option) any later version. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program; if not, write to the Free Software 21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22# USA. 23# 24# 25# References: 26# 27# - https://github.com/puppetlabs/puppet-specifications/blob/master/language/intro.md 28# - https://docs.puppet.com/puppet/5.1/lang_visual_index.html 29# 30--langdef=PuppetManifest{_autoFQTag} 31--map-PuppetManifest=+.pp 32 33# 34# Kinds 35# 36--kinddef-PuppetManifest=c,class,classes 37--kinddef-PuppetManifest=d,definition,definitions 38--kinddef-PuppetManifest=n,node,nodes 39--kinddef-PuppetManifest=r,resource,resources 40--kinddef-PuppetManifest=v,variable,variables 41--kinddef-PuppetManifest=p,param,parameters 42--kinddef-PuppetManifest=V,vresource,virtual resources 43--kinddef-PuppetManifest=t,type,type aliases 44 45# 46# Separators 47# 48--_scopesep-PuppetManifest=/c::: 49--_scopesep-PuppetManifest=*/*::: 50 51# 52# Prelude 53# 54--_prelude-PuppetManifest={{ 55 % spec:dict<num,kind> TRYMAKETAG tag:int true 56 % spec:dict<num,kind> TRYMAKETAG false 57 /trymaketag { 58 { 59 { 60 1 index _matchstr { 61 % key value str 62 3 -1 roll 63 % value str key 64 _matchloc 65 % value str loc 66 3 -1 roll exch 67 % str value loc 68 _tag _commit 69 stop 70 } { 71 pop pop 72 } ifelse 73 } forall 74 } stopped 75 } def 76}} 77 78# 79# Tables 80# 81--_tabledef-PuppetManifest=main 82--_tabledef-PuppetManifest=separator 83--_tabledef-PuppetManifest=any 84--_tabledef-PuppetManifest=ignoreWhiteSpace 85--_tabledef-PuppetManifest=end 86--_tabledef-PuppetManifest=endWithPop 87 88--_tabledef-PuppetManifest=ssliteral 89--_tabledef-PuppetManifest=dsliteral 90 91--_tabledef-PuppetManifest=comment 92 93--_tabledef-PuppetManifest=blockStart 94--_tabledef-PuppetManifest=blockHead 95--_tabledef-PuppetManifest=blockHeadPopAtLast 96--_tabledef-PuppetManifest=block 97 98--_tabledef-PuppetManifest=classStart 99#--_tabledef-PuppetManifest=resourceBlock{args=end} 100--_tabledef-PuppetManifest=resourceBlock 101 102--_tabledef-PuppetManifest=skipLiteral 103--_tabledef-PuppetManifest=skipBlock 104--_tabledef-PuppetManifest=skipArray 105--_tabledef-PuppetManifest=skipArgs 106--_tabledef-PuppetManifest=skipCollector 107 108--_tabledef-PuppetManifest=signature 109--_tabledef-PuppetManifest=skipDefaultValue 110 111--_tabledef-PuppetManifest=var 112 113--_tabledef-PuppetManifest=defineStart 114--_tabledef-PuppetManifest=caseStart 115--_tabledef-PuppetManifest=ifStart 116 117--_tabledef-PuppetManifest=nodeStart 118 119--_tabledef-PuppetManifest=typeStart 120 121# 122# Utilities 123# 124--_mtable-regex-PuppetManifest=separator/[a-zA-Z0-9]// 125--_mtable-regex-PuppetManifest=separator///{tleave} 126 127--_mtable-regex-PuppetManifest=any/.// 128--_mtable-regex-PuppetManifest=ignoreWhiteSpace/[ \t\n]+// 129--_mtable-regex-PuppetManifest=end///{tleave} 130--_mtable-regex-PuppetManifest=endWithPop///{tleave}{scope=pop} 131 132--_mtable-regex-PuppetManifest=ssliteral/[^']*'//{tleave} 133--_mtable-regex-PuppetManifest=ssliteral/[^']+// 134--_mtable-regex-PuppetManifest=dsliteral/[^"]*"//{tleave} 135--_mtable-regex-PuppetManifest=dsliteral/[^"]+// 136 137# 138# comment 139# 140--_tabledef-PuppetManifest=comment_multiline 141--_tabledef-PuppetManifest=comment_oneline 142--_mtable-regex-PuppetManifest=comment/\/\*//{tenter=comment_multiline} 143--_mtable-regex-PuppetManifest=comment/\#//{tenter=comment_oneline} 144--_mtable-regex-PuppetManifest=comment_multiline/\*\///{tleave} 145--_mtable-extend-PuppetManifest=comment_multiline+any 146--_mtable-regex-PuppetManifest=comment_oneline/\n//{tleave} 147--_mtable-extend-PuppetManifest=comment_oneline+any 148 149# 150# skipLiteral 151# 152--_mtable-regex-PuppetManifest=skipLiteral/'//{tenter=ssliteral} 153--_mtable-regex-PuppetManifest=skipLiteral/"//{tenter=dsliteral} 154 155# 156# skipBlock 157# 158--_mtable-extend-PuppetManifest=skipBlock+comment 159--_mtable-extend-PuppetManifest=skipBlock+skipLiteral 160--_mtable-regex-PuppetManifest=skipBlock/\{//{tenter=skipBlock} 161--_mtable-regex-PuppetManifest=skipBlock/\}//{tleave} 162--_mtable-extend-PuppetManifest=skipBlock+any 163 164# 165# skipArray 166# 167--_mtable-extend-PuppetManifest=skipArray+comment 168--_mtable-extend-PuppetManifest=skipArray+skipLiteral 169--_mtable-regex-PuppetManifest=skipArray/\[//{tenter=skipArray} 170--_mtable-regex-PuppetManifest=skipArray/\]//{tleave} 171--_mtable-extend-PuppetManifest=skipArray+any 172 173# 174# skipArgs 175# 176--_mtable-extend-PuppetManifest=skipArgs+comment 177--_mtable-extend-PuppetManifest=skipArgs+skipLiteral 178--_mtable-regex-PuppetManifest=skipArgs/\(//{tenter=skipArgs} 179--_mtable-regex-PuppetManifest=skipArgs/\)//{tleave} 180--_mtable-extend-PuppetManifest=skipArgs+any 181 182# 183# signature 184# 185--_mtable-extend-PuppetManifest=signature+comment 186--_mtable-extend-PuppetManifest=signature+skipLiteral 187--_mtable-extend-PuppetManifest=signature+ignoreWhiteSpace 188--_mtable-regex-PuppetManifest=signature/\)//{tleave}{{ 189 % 190 % fill signature 191 % 192 dup ?, eq { pop } if 193 ?) _buildstring _scopetop { 194 exch signature: 195 } { 196 % something wrong 197 pop 198 } ifelse 199}} 200--_mtable-regex-PuppetManifest=signature/\$([a-zA-Z][_a-zA-Z0-9:]*)[ \t]*([=,])[ \t]*/\1/p/{scope=ref}{{ 201 % push the name of parameter for filling the signature field of definition 202 \2 0 get ?= eq { 203 /skipDefaultValue _tenter 204 } if 205 ?$ \1 ?, 206}} 207--_mtable-extend-PuppetManifest=signature+any 208 209# 210# skipDefaultValue 211# 212--_mtable-extend-PuppetManifest=skipDefaultValue+comment 213--_mtable-extend-PuppetManifest=skipDefaultValue+skipLiteral 214--_mtable-regex-PuppetManifest=skipDefaultValue/\[//{tenter=skipArray} 215--_mtable-regex-PuppetManifest=skipDefaultValue/\{//{tenter=skipBlock} 216--_mtable-regex-PuppetManifest=skipDefaultValue/\(//{tenter=skipArgs} 217--_mtable-regex-PuppetManifest=skipDefaultValue/,//{tleave} 218--_mtable-regex-PuppetManifest=skipDefaultValue/\)//{tleave}{_advanceTo=0start} 219--_mtable-extend-PuppetManifest=skipDefaultValue+any 220 221# 222# skipCollector 223# 224--_mtable-extend-PuppetManifest=skipCollector+comment 225--_mtable-extend-PuppetManifest=skipCollector+skipLiteral 226--_mtable-regex-PuppetManifest=skipCollector/<<?\|//{tenter=skipCollector} 227--_mtable-regex-PuppetManifest=skipCollector/\|>>?//{tleave} 228--_mtable-extend-PuppetManifest=skipCollector+any 229 230 231 232# 233# block 234# 235--_mtable-regex-PuppetManifest=blockStart/(@)?(::[a-zA-Z0-9:_]+|[a-zA-Z][a-zA-Z0-9:_]*)[ \t\n]*\{//{tenter=resourceBlock}{{ 236 \1 _isstring { 237 /vresource 238 } { 239 /resource 240 } ifelse \2 true 241 % kind:name type:string true 242}} 243--_mtable-regex-PuppetManifest=blockStart/class[ \t\n]+//{tenter=classStart} 244--_mtable-regex-PuppetManifest=blockStart/define[ \t\n]+//{tenter=defineStart} 245--_mtable-regex-PuppetManifest=blockStart/case[ \t\n]+//{tenter=caseStart} 246--_mtable-regex-PuppetManifest=blockStart/(if|elsif|else|unless)[ \t\n]+//{tenter=ifStart} 247--_mtable-regex-PuppetManifest=blockStart/node[ \t\n]+//{tenter=nodeStart} 248--_mtable-regex-PuppetManifest=blockStart/type[ \t\n]+//{tenter=typeStart} 249--_mtable-regex-PuppetManifest=blockStart/\$//{tenter=var} 250 251 252--_mtable-extend-PuppetManifest=blockHead+comment 253--_mtable-extend-PuppetManifest=blockHead+ignoreWhiteSpace 254--_mtable-regex-PuppetManifest=blockHead/\{//{tenter=block,end} 255--_mtable-extend-PuppetManifest=blockHead+any 256 257--_mtable-extend-PuppetManifest=blockHeadPopAtLast+comment 258--_mtable-regex-PuppetManifest=blockHeadPopAtLast/\{//{tenter=block,endWithPop} 259--_mtable-extend-PuppetManifest=blockHeadPopAtLast+ignoreWhiteSpace 260--_mtable-regex-PuppetManifest=blockHeadPopAtLast/inherits[ \t\n]+(::[a-z][_a-zA-Z0-9:]*|[a-z][_a-zA-Z0-9:]*)[ \t\n]*//{{ 261 _scopetop { 262 dup :kind /class eq { 263 \1 inherits: 264 } { 265 pop 266 } ifelse 267 } if 268}} 269--_mtable-extend-PuppetManifest=blockHeadPopAtLast+any 270 271--_mtable-extend-PuppetManifest=block+ignoreWhiteSpace 272--_mtable-extend-PuppetManifest=block+blockStart 273--_mtable-regex-PuppetManifest=block/<<?\|//{tenter=skipCollector} 274 275# Following stack manipulation for handling following input. 276# A { 277# "a": b => c; 278# "d": e => f; 279# } 280# B { 281# "g": h => i; 282# "j": k => k /* THIS COMMENT CANNOT BE IGNORED WELL */ 283# } 284--_mtable-regex-PuppetManifest=block/;?[ \t\n]*\}//{tleave} 285--_mtable-regex-PuppetManifest=block/;//{tjump=resourceBlock}{scope=pop}{{ 286 false 287}} 288#--_mtable-regex-PuppetManifest=block/;//{tleave}{scope=pop} 289--_mtable-regex-PuppetManifest=block/:// 290--_mtable-extend-PuppetManifest=block+comment 291--_mtable-extend-PuppetManifest=block+skipLiteral 292--_mtable-regex-PuppetManifest=block/\{//{tenter=block} 293--_mtable-regex-PuppetManifest=block/.//{tenter=separator} 294 295# 296# main 297# 298--_mtable-extend-PuppetManifest=main+comment 299--_mtable-extend-PuppetManifest=main+ignoreWhiteSpace 300--_mtable-extend-PuppetManifest=main+skipLiteral 301--_mtable-regex-PuppetManifest=main/<<?\|//{tenter=skipCollector} 302--_mtable-regex-PuppetManifest=main/\$//{tenter=var} 303--_mtable-extend-PuppetManifest=main+blockStart 304--_mtable-regex-PuppetManifest=main/\(//{tenter=skipArgs} 305--_mtable-regex-PuppetManifest=main/\{//{tenter=skipBlock} 306--_mtable-regex-PuppetManifest=main/.//{tenter=separator} 307 308# 309# class 310--_mtable-extend-PuppetManifest=classStart+comment 311--_mtable-regex-PuppetManifest=classStart/(::[a-z][_a-zA-Z0-9:]*|[a-z][_a-zA-Z0-9:]*)[ \t\n]*(\(|\{|inherits[ \t\n]+(::[a-z][_a-zA-Z0-9:]*|[a-z][_a-zA-Z0-9:]*))[ \t\n]*/\1/c/{scope=push}{{ 312 \3 _isstring { 313 . exch inherits: 314 /blockHead /endWithPop _tentercont 315 } { 316 \2 0 get ?( eq { 317 % for gathering signature 318 mark ?( 319 % {tenter=signature,blockHeadPopAtLast} 320 /signature /blockHeadPopAtLast _tentercont 321 } { 322 2 /start _matchloc _advanceto 323 /blockHead /endWithPop _tentercont 324 } ifelse 325 } ifelse 326}} 327 328# 329# resource 330# 331--_tabledef-PuppetManifest=resourceName 332--_tabledef-PuppetManifest=resourceNameInArray 333--_tabledef-PuppetManifest=resourceBody 334--_tabledef-PuppetManifest=resourceArray 335--_tabledef-PuppetManifest=resourceCollector 336 337# resourceBlock expects data on optscript: 338# 339# false RESOURCEBLOCK - 340# kind:name type:string true RESOURCEBLOCK - 341# 342--_mtable-extend-PuppetManifest=resourceBlock+ignoreWhiteSpace 343--_mtable-regex-PuppetManifest=resourceBlock/\}//{tleave}{{ 344 { pop pop } if 345}} 346--_mtable-regex-PuppetManifest=resourceBlock/'//{tenter=resourceName}{_advanceTo=0start} 347--_mtable-regex-PuppetManifest=resourceBlock/"//{tenter=resourceName}{_advanceTo=0start} 348--_mtable-regex-PuppetManifest=resourceBlock/\[//{tenter=resourceArray} 349--_mtable-regex-PuppetManifest=resourceBlock/\{//{tenter=block} 350--_mtable-extend-PuppetManifest=resourceBlock+comment 351--_mtable-regex-PuppetManifest=resourceBlock/.//{tenter=resourceBody}{scope=push}{placeholder} 352 353# resourceName expects data on optscript: 354# 355# false RESOURCENAME false 356# kind:name type:string true RESOURCENAME kind:name type:string true 357# 358--_mtable-regex-PuppetManifest=resourceName/'([^']+)'|"([^"]+)"//{tenter=resourceBody,end}{{ 359 dup { 360 1 index (typename) exch [ 3 1 roll ] 361 % kind:name type:string true [ (typename) type:string ] 362 << 363 4 index 364 % kind:name type:string true [ (typename) type:string ] << kind:name 365 1 exch dup 2 exch 366 >> 367 % kind:name type:string true [ (typename) type:string ] << 1 kind:name 2 kind:name >> 368 trymaketag 369 % kind:name type:string true [ (typename) type:string ] tag:int true % 370 % kind:name type:string true [ (typename) type:string ] false 371 { 372 dup _scopepush 373 exch typeref: 374 } { 375 pop 376 } ifelse 377 } { 378 << 1 /resource 2 /resource >> trymaketag { 379 _scopepush 380 } if 381 } ifelse 382}} 383--_mtable-regex-PuppetManifest=resourceName///{tquit} 384 385# resourceNameInArray expects data on optscript: 386# 387# false RESOURCENAMEINARRAY false 388# kind:name type:string true RESOURCENAMEINARRAY kind:name type:string true 389# 390--_mtable-regex-PuppetManifest=resourceNameInArray/'([^']+)'|"([^"]+)"///{tleave}{{ 391 dup { 392 % do the same as resourceName 393 1 index (typename) exch [ 3 1 roll ] 394 << 4 index 1 exch dup 2 exch >> trymaketag 395 { 396 dup _scoperef 397 exch typeref: 398 } { 399 pop 400 } ifelse 401 402 } { 403 << 1 /resource 2 /resource >> trymaketag { 404 _scoperef 405 } if 406 } ifelse 407}} 408--_mtable-regex-PuppetManifest=resourceNameInArray////{tquit} 409 410# --_mtable-extend-PuppetManifest=resourceBody+ignoreWhiteSpace 411# 412# Next pattern is just for optimization. 413# 414--_mtable-regex-PuppetManifest=resourceBody/[^\/#{'";}<]+// 415--_mtable-regex-PuppetManifest=resourceBody/'//{tenter=ssliteral} 416--_mtable-regex-PuppetManifest=resourceBody/"//{tenter=dsliteral} 417--_mtable-regex-PuppetManifest=resourceBody/\}//{tleave}{_advanceTo=0start}{scope=pop} 418--_mtable-regex-PuppetManifest=resourceBody/\{//{tenter=skipBlock} 419--_mtable-regex-PuppetManifest=resourceBody/;//{tleave}{scope=pop} 420--_mtable-regex-PuppetManifest=resourceBody/<<?\|//{tenter=skipCollector} 421--_mtable-extend-PuppetManifest=resourceBody+comment 422--_mtable-extend-PuppetManifest=resourceBody+any 423 424--_mtable-extend-PuppetManifest=resourceArray+comment 425--_mtable-extend-PuppetManifest=resourceArray+ignoreWhiteSpace 426--_mtable-regex-PuppetManifest=resourceArray/['"]//{tenter=resourceNameInArray}{_advanceTo=0start} 427--_mtable-regex-PuppetManifest=resourceArray/\]//{tleave} 428--_mtable-extend-PuppetManifest=resourceArray+any 429 430# 431# var 432# 433--_tabledef-PuppetManifest=varexpr 434--_mtable-regex-PuppetManifest=var/(::[a-zA-Z0-9_:]+|[a-zA-Z_][a-zA-Z0-9_:]*)[ \t\n]*=/\1/v/{tenter=varexpr,end}{{ 435 \1 0 get ?: eq not { 436 . _scoperef 437 } if 438}} 439 440--_mtable-extend-PuppetManifest=varexpr+comment 441--_mtable-regex-PuppetManifest=varexpr/'//{tenter=ssliteral,end} 442--_mtable-regex-PuppetManifest=varexpr/"//{tenter=dsliteral,end} 443--_mtable-regex-PuppetManifest=varexpr/\[//{tenter=skipArray,end} 444--_mtable-regex-PuppetManifest=varexpr/\{//{tenter=skipBlock,end} 445--_mtable-regex-PuppetManifest=varexpr/\(//{tenter=skipArgs,end} 446--_mtable-regex-PuppetManifest=varexpr/\$[a-zA-Z:][0-9a-zA-Z:]*// 447--_mtable-regex-PuppetManifest=varexpr/[0-9]+(\.[0-9]+(e([+-][0-9]+)))?// 448--_mtable-regex-PuppetManifest=varexpr/[a-zA-Z0-9:][0-9a-zA-Z:]*// 449--_mtable-regex-PuppetManifest=varexpr/[ \t]// 450--_mtable-regex-PuppetManifest=varexpr/\n//{tleave} 451--_mtable-extend-PuppetManifest=varexpr+any 452 453# 454# define 455# 456--_mtable-extend-PuppetManifest=defineStart+comment 457--_mtable-regex-PuppetManifest=defineStart/([a-z][_a-zA-Z0-9:]*)[ \n\t]*([({])/\1/d/{scope=push}{{ 458 \2 0 get ?( eq { 459 % for gathering signature 460 mark ?( 461 % {tenter=signature,blockHeadPopAtLast} 462 /signature /blockHeadPopAtLast _tentercont 463 } { 464 /block /endWithPop _tentercont 465 } ifelse 466}} 467 468# 469# case 470# 471--_tabledef-PuppetManifest=caseBlock 472 473--_mtable-extend-PuppetManifest=caseStart+comment 474--_mtable-extend-PuppetManifest=caseStart+ignoreWhiteSpace 475--_mtable-regex-PuppetManifest=caseStart/\{//{tenter=caseBlock} 476--_mtable-regex-PuppetManifest=caseStart/}//{tleave} 477--_mtable-extend-PuppetManifest=caseStart+any 478 479--_mtable-extend-PuppetManifest=caseBlock+comment 480--_mtable-extend-PuppetManifest=caseBlock+ignoreWhiteSpace 481--_mtable-extend-PuppetManifest=caseBlock+skipLiteral 482--_mtable-regex-PuppetManifest=caseBlock/://{tenter=blockHead} 483--_mtable-regex-PuppetManifest=caseBlock/}//{tleave}{_advanceTo=0start} 484--_mtable-extend-PuppetManifest=caseBlock+any 485 486# 487# if/elsif/else 488# 489--_mtable-extend-PuppetManifest=ifStart+comment 490--_mtable-extend-PuppetManifest=ifStart+ignoreWhiteSpace 491--_mtable-extend-PuppetManifest=ifStart+skipLiteral 492--_mtable-regex-PuppetManifest=ifStart/\{//{tenter=block,end} 493--_mtable-extend-PuppetManifest=ifStart+any 494 495# 496# node 497# 498--_mtable-extend-PuppetManifest=nodeStart+comment 499--_mtable-extend-PuppetManifest=nodeStart+ignoreWhiteSpace 500--_mtable-regex-PuppetManifest=nodeStart/'([^']+)'/\1/n/ 501--_mtable-regex-PuppetManifest=nodeStart/"([^"]+)"/\1/n/ 502--_mtable-regex-PuppetManifest=nodeStart/\{///{tenter=block,end} 503--_mtable-extend-PuppetManifest=nodeStart+any 504 505# 506# type 507# 508--_mtable-extend-PuppetManifest=typeStart+comment 509--_mtable-extend-PuppetManifest=typeStart+ignoreWhiteSpace 510--_mtable-regex-PuppetManifest=typeStart/([a-zA-Z][a-zA-Z0-9]*::[a-zA-Z][a-zA-Z0-9]+)[ \t\n]*=[ \t\n]*/\1/t/{tenter=varexpr,end} 511--_mtable-extend-PuppetManifest=typeStart+any 512