#
# puppetManifest.ctags --- multitable regex parser for Puppet's manifest file
#
#  Copyright (c) 2017, Red Hat, Inc.
#  Copyright (c) 2017, Masatake YAMATO
#
#  Author: Masatake YAMATO <yamato@redhat.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
#
# References:
#
# - https://github.com/puppetlabs/puppet-specifications/blob/master/language/intro.md
# - https://docs.puppet.com/puppet/5.1/lang_visual_index.html
#
--langdef=PuppetManifest{_autoFQTag}
--map-PuppetManifest=+.pp

#
# Kinds
#
--kinddef-PuppetManifest=c,class,classes
--kinddef-PuppetManifest=d,definition,definitions
--kinddef-PuppetManifest=n,node,nodes
--kinddef-PuppetManifest=r,resource,resources
--kinddef-PuppetManifest=v,variable,variables

#
# Separators
#
--_scopesep-PuppetManifest=/c:::
--_scopesep-PuppetManifest=*/*:::

#
# Tables
#
--_tabledef-PuppetManifest=main
--_tabledef-PuppetManifest=separator
--_tabledef-PuppetManifest=any
--_tabledef-PuppetManifest=ignoreWhiteSpace
--_tabledef-PuppetManifest=end
--_tabledef-PuppetManifest=endWithPop

--_tabledef-PuppetManifest=ssliteral
--_tabledef-PuppetManifest=dsliteral

--_tabledef-PuppetManifest=comment

--_tabledef-PuppetManifest=blockStart
--_tabledef-PuppetManifest=blockHead
--_tabledef-PuppetManifest=blockHeadPopAtLast
--_tabledef-PuppetManifest=block

--_tabledef-PuppetManifest=classStart
#--_tabledef-PuppetManifest=resourceBlock{args=end}
--_tabledef-PuppetManifest=resourceBlock

--_tabledef-PuppetManifest=skipLiteral
--_tabledef-PuppetManifest=skipBlock
--_tabledef-PuppetManifest=skipArray
--_tabledef-PuppetManifest=skipArgs
--_tabledef-PuppetManifest=skipCollector

--_tabledef-PuppetManifest=var

--_tabledef-PuppetManifest=defineStart
--_tabledef-PuppetManifest=caseStart
--_tabledef-PuppetManifest=ifStart

--_tabledef-PuppetManifest=nodeStart

#
# Utilities
#
--_mtable-regex-PuppetManifest=separator/[a-zA-Z0-9]//
--_mtable-regex-PuppetManifest=separator///{tleave}

--_mtable-regex-PuppetManifest=any/.//
--_mtable-regex-PuppetManifest=ignoreWhiteSpace/[ \t\n]+//
--_mtable-regex-PuppetManifest=end///{tleave}
--_mtable-regex-PuppetManifest=endWithPop///{tleave}{scope=pop}

--_mtable-regex-PuppetManifest=ssliteral/[^']*'//{tleave}
--_mtable-regex-PuppetManifest=ssliteral/[^']+//
--_mtable-regex-PuppetManifest=dsliteral/[^"]*"//{tleave}
--_mtable-regex-PuppetManifest=dsliteral/[^"]+//

#
# comment
#
--_tabledef-PuppetManifest=comment_multiline
--_tabledef-PuppetManifest=comment_oneline
--_mtable-regex-PuppetManifest=comment/\/\*//{tenter=comment_multiline}
--_mtable-regex-PuppetManifest=comment/\#//{tenter=comment_oneline}
--_mtable-regex-PuppetManifest=comment_multiline/\*\///{tleave}
--_mtable-extend-PuppetManifest=comment_multiline+any
--_mtable-regex-PuppetManifest=comment_oneline/\n//{tleave}
--_mtable-extend-PuppetManifest=comment_oneline+any

#
# skipLiteral
#
--_mtable-regex-PuppetManifest=skipLiteral/'//{tenter=ssliteral}
--_mtable-regex-PuppetManifest=skipLiteral/"//{tenter=dsliteral}

#
# skipBlock
#
--_mtable-extend-PuppetManifest=skipBlock+comment
--_mtable-extend-PuppetManifest=skipBlock+skipLiteral
--_mtable-regex-PuppetManifest=skipBlock/\{//{tenter=skipBlock}
--_mtable-regex-PuppetManifest=skipBlock/\}//{tleave}
--_mtable-extend-PuppetManifest=skipBlock+any

#
# skipArray
#
--_mtable-extend-PuppetManifest=skipArray+comment
--_mtable-extend-PuppetManifest=skipArray+skipLiteral
--_mtable-regex-PuppetManifest=skipArray/\[//{tenter=skipArray}
--_mtable-regex-PuppetManifest=skipArray/\]//{tleave}
--_mtable-extend-PuppetManifest=skipArray+any

#
# skipArgs
#
--_mtable-extend-PuppetManifest=skipArgs+comment
--_mtable-extend-PuppetManifest=skipArgs+skipLiteral
--_mtable-regex-PuppetManifest=skipArgs/\(//{tenter=skipArgs}
--_mtable-regex-PuppetManifest=skipArgs/\)//{tleave}
--_mtable-extend-PuppetManifest=skipArgs+any

#
# skipCollector
#
--_mtable-extend-PuppetManifest=skipCollector+comment
--_mtable-extend-PuppetManifest=skipCollector+skipLiteral
--_mtable-regex-PuppetManifest=skipCollector/<<?\|//{tenter=skipCollector}
--_mtable-regex-PuppetManifest=skipCollector/\|>>?//{tleave}
--_mtable-extend-PuppetManifest=skipCollector+any



#
# block
#
--_mtable-regex-PuppetManifest=blockStart/@?::[a-zA-Z0-9:_]+[ \t\n]*\{//{tenter=resourceBlock}
--_mtable-regex-PuppetManifest=blockStart/@?[a-zA-Z][a-zA-Z0-9:_]*[ \t\n]*\{//{tenter=resourceBlock}
--_mtable-regex-PuppetManifest=blockStart/class[ \t\n]+//{tenter=classStart}
--_mtable-regex-PuppetManifest=blockStart/define[ \t\n]+//{tenter=defineStart}
--_mtable-regex-PuppetManifest=blockStart/case[ \t\n]+//{tenter=caseStart}
--_mtable-regex-PuppetManifest=blockStart/(if|elsif|else|unless)[ \t\n]+//{tenter=ifStart}
--_mtable-regex-PuppetManifest=blockStart/node[ \t\n]+//{tenter=nodeStart}
--_mtable-regex-PuppetManifest=blockStart/\$//{tenter=var}


--_mtable-extend-PuppetManifest=blockHead+comment
--_mtable-extend-PuppetManifest=blockHead+ignoreWhiteSpace
--_mtable-regex-PuppetManifest=blockHead/\{//{tenter=block,end}
--_mtable-extend-PuppetManifest=blockHead+any

--_mtable-extend-PuppetManifest=blockHeadPopAtLast+comment
--_mtable-regex-PuppetManifest=blockHeadPopAtLast/\{//{tenter=block,endWithPop}
--_mtable-extend-PuppetManifest=blockHeadPopAtLast+any

--_mtable-extend-PuppetManifest=block+ignoreWhiteSpace
--_mtable-extend-PuppetManifest=block+blockStart
--_mtable-regex-PuppetManifest=block/<<?\|//{tenter=skipCollector}

# Following stack manipulation for handling following input.
# A {
#     "a": b => c;
#     "d": e => f;
# }
# B {
#     "g": h => i;
#     "j": k => k /* THIS COMMENT CANNOT BE IGNORED WELL */
# }
--_mtable-regex-PuppetManifest=block/;?[ \t\n]*\}//{tleave}
--_mtable-regex-PuppetManifest=block/;//{tjump=resourceBlock}{scope=pop}
#--_mtable-regex-PuppetManifest=block/;//{tleave}{scope=pop}
--_mtable-regex-PuppetManifest=block/://
--_mtable-extend-PuppetManifest=block+comment
--_mtable-extend-PuppetManifest=block+skipLiteral
--_mtable-regex-PuppetManifest=block/\{//{tenter=block}
--_mtable-regex-PuppetManifest=block/.//{tenter=separator}

#
# main
#
--_mtable-extend-PuppetManifest=main+comment
--_mtable-extend-PuppetManifest=main+ignoreWhiteSpace
--_mtable-extend-PuppetManifest=main+skipLiteral
--_mtable-regex-PuppetManifest=main/<<?\|//{tenter=skipCollector}
--_mtable-regex-PuppetManifest=main/\$//{tenter=var}
--_mtable-extend-PuppetManifest=main+blockStart
--_mtable-regex-PuppetManifest=main/\(//{tenter=skipArgs}
--_mtable-regex-PuppetManifest=main/\{//{tenter=skipBlock}
--_mtable-regex-PuppetManifest=main/.//{tenter=separator}

#
# class
#
# TODO: inherits:
#
--_mtable-extend-PuppetManifest=classStart+comment
--_mtable-regex-PuppetManifest=classStart/(::[a-z][_a-zA-Z0-9:]*)/\1/c/{tenter=blockHead,endWithPop}{scope=push}
--_mtable-regex-PuppetManifest=classStart/([a-z][_a-zA-Z0-9:]*)/\1/c/{tenter=blockHead,endWithPop}{scope=push}

#
# resource
#
--_tabledef-PuppetManifest=resourceName
--_tabledef-PuppetManifest=resourceNameInArray
--_tabledef-PuppetManifest=resourceBody
--_tabledef-PuppetManifest=resourceArray
--_tabledef-PuppetManifest=resourceCollector

--_mtable-extend-PuppetManifest=resourceBlock+ignoreWhiteSpace
--_mtable-regex-PuppetManifest=resourceBlock/\}//{tleave}
--_mtable-regex-PuppetManifest=resourceBlock/'//{tenter=resourceName}{_advanceTo=0start}
--_mtable-regex-PuppetManifest=resourceBlock/"//{tenter=resourceName}{_advanceTo=0start}
--_mtable-regex-PuppetManifest=resourceBlock/\[//{tenter=resourceArray}
--_mtable-regex-PuppetManifest=resourceBlock/\{//{tenter=block}
--_mtable-extend-PuppetManifest=resourceBlock+comment
--_mtable-regex-PuppetManifest=resourceBlock/.//{tenter=resourceBody}{scope=push}{placeholder}

--_mtable-regex-PuppetManifest=resourceName/'([^']+)'/\1/r/{tenter=resourceBody,end}{scope=push}
--_mtable-regex-PuppetManifest=resourceName/"([^"]+)"/\1/r/{tenter=resourceBody,end}{scope=push}
--_mtable-regex-PuppetManifest=resourceName///{tquit}
--_mtable-regex-PuppetManifest=resourceNameInArray/'([^']+)'/\1/r/{tleave}
--_mtable-regex-PuppetManifest=resourceNameInArray/"([^"]+)"/\1/r/{tleave}
--_mtable-regex-PuppetManifest=resourceNameInArray////{tquit}

# --_mtable-extend-PuppetManifest=resourceBody+ignoreWhiteSpace
#
# Next pattern is just for optimization.
#
--_mtable-regex-PuppetManifest=resourceBody/[^\/#{'";}<]+//
--_mtable-regex-PuppetManifest=resourceBody/'//{tenter=ssliteral}
--_mtable-regex-PuppetManifest=resourceBody/"//{tenter=dsliteral}
--_mtable-regex-PuppetManifest=resourceBody/\}//{tleave}{_advanceTo=0start}{scope=pop}
--_mtable-regex-PuppetManifest=resourceBody/\{//{tenter=skipBlock}
--_mtable-regex-PuppetManifest=resourceBody/;//{tleave}{scope=pop}
--_mtable-regex-PuppetManifest=resourceBody/<<?\|//{tenter=skipCollector}
--_mtable-extend-PuppetManifest=resourceBody+comment
--_mtable-extend-PuppetManifest=resourceBody+any

--_mtable-extend-PuppetManifest=resourceArray+comment
--_mtable-extend-PuppetManifest=resourceArray+ignoreWhiteSpace
--_mtable-regex-PuppetManifest=resourceArray/'//{tenter=resourceNameInArray}{_advanceTo=0start}
--_mtable-regex-PuppetManifest=resourceArray/"//{tenter=resourceNameInArray}{_advanceTo=0start}
--_mtable-regex-PuppetManifest=resourceArray/\]//{tleave}
--_mtable-extend-PuppetManifest=resourceArray+any

#
# var
#
--_tabledef-PuppetManifest=varexpr
--_mtable-regex-PuppetManifest=var/(::[a-zA-Z0-9_:]+)[ \t\n]*=/\1/v/{tenter=varexpr,end}
--_mtable-regex-PuppetManifest=var/([a-zA-Z_][a-zA-Z0-9_:]*)[ \t\n]*=/\1/v/{tenter=varexpr,end}{scope=ref}

--_mtable-extend-PuppetManifest=varexpr+comment
--_mtable-regex-PuppetManifest=varexpr/'//{tenter=ssliteral,end}
--_mtable-regex-PuppetManifest=varexpr/"//{tenter=dsliteral,end}
--_mtable-regex-PuppetManifest=varexpr/\[//{tenter=skipArray,end}
--_mtable-regex-PuppetManifest=varexpr/\{//{tenter=skipBlock,end}
--_mtable-regex-PuppetManifest=varexpr/\(//{tenter=skipArgs,end}
--_mtable-regex-PuppetManifest=varexpr/\$[a-zA-Z:][0-9a-zA-Z"]*//
--_mtable-regex-PuppetManifest=varexpr/[0-9]+(\.[0-9]+(e([+-][0-9]+)))?//
--_mtable-regex-PuppetManifest=varexpr/[a-zA-Z0-9:][0-9a-zA-Z:]*//
--_mtable-regex-PuppetManifest=varexpr/[ \t]//
--_mtable-regex-PuppetManifest=varexpr/\n//{tleave}
--_mtable-regex-PuppetManifest=varexpr/.//

#
# define
#
--_mtable-extend-PuppetManifest=defineStart+comment
--_mtable-regex-PuppetManifest=defineStart/([a-z][_a-zA-Z0-9:]*)[ \n\t]*\(/\1/d/{tenter=skipArgs,blockHeadPopAtLast}{scope=push}
--_mtable-regex-PuppetManifest=defineStart/([a-z][_a-zA-Z0-9:]*)[ \n\t]*\{/\1/d/{tenter=block,endWithPop}{scope=push}

#
# case
#
--_tabledef-PuppetManifest=caseBlock

--_mtable-extend-PuppetManifest=caseStart+comment
--_mtable-extend-PuppetManifest=caseStart+ignoreWhiteSpace
--_mtable-regex-PuppetManifest=caseStart/\{//{tenter=caseBlock}
--_mtable-regex-PuppetManifest=caseStart/}//{tleave}
--_mtable-extend-PuppetManifest=caseStart+any

--_mtable-extend-PuppetManifest=caseBlock+comment
--_mtable-extend-PuppetManifest=caseBlock+ignoreWhiteSpace
--_mtable-extend-PuppetManifest=caseBlock+skipLiteral
--_mtable-regex-PuppetManifest=caseBlock/://{tenter=blockHead}
--_mtable-regex-PuppetManifest=caseBlock/}//{tleave}{_advanceTo=0start}
--_mtable-extend-PuppetManifest=caseBlock+any

#
# if/elsif/else
#
--_mtable-extend-PuppetManifest=ifStart+comment
--_mtable-extend-PuppetManifest=ifStart+ignoreWhiteSpace
--_mtable-extend-PuppetManifest=ifStart+skipLiteral
--_mtable-regex-PuppetManifest=ifStart/\{//{tenter=block,end}
--_mtable-extend-PuppetManifest=ifStart+any

#
# node
#
--_mtable-extend-PuppetManifest=nodeStart+comment
--_mtable-extend-PuppetManifest=nodeStart+ignoreWhiteSpace
--_mtable-regex-PuppetManifest=nodeStart/'([^']+)'/\1/n/
--_mtable-regex-PuppetManifest=nodeStart/"([^"]+)"/\1/n/
--_mtable-regex-PuppetManifest=nodeStart/\{///{tenter=block,end}
--_mtable-extend-PuppetManifest=nodeStart+any
