aboutsummaryrefslogtreecommitdiff
path: root/steuermann/specfile.exy
blob: 4353069d0705a187872b2a94fdbcf999db58f980 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

# Parse a Steuermann Spec file
#
# This is an exyapps grammer in specfile.exy
import nodes

%%
parser specfile:
    ignore: "[ \r\t\n]+"
    ignore: "#.*\n"

    token END: "$"
    token HOSTGROUP: "HOSTGROUP"
    token IF: "IF"
    token TABLE: "TABLE"
    token HOST : "HOST"
    token CMD: "CMD"
    token OPT: "OPT"
    token AFTER: "AFTER"
    token RUN: "RUN"
    token LOCAL: "LOCAL"
    token IMPORT: "IMPORT"
    token DEBUG: "DEBUG"
    token name: "[a-zA-Z0-9_.-]+"
    token STAR: "\*"
    token cmdname: "[a-zA-Z0-9_.-]+"
    token tablename: "[a-zA-Z0-9_.-]+"
    token wildname: "[@]{0,1}[*?a-zA-Z0-9_.-]+"
    token string: '"[^"]*"'
    token SLASH: "/"
    token COLON: ":"
    token hostgroup: "@[a-zA-Z0-9_.-]+"

    # watch carefully:  none of the keywords are "END" on a line by themselves
    token CONDITIONS: 'CONDITIONS[^"]*\n[\s]*END[ \t]*\n'

    rule start: table_list END {{ return table_list }}

    rule table_list:  table_section +

    rule table_section:
        DEBUG string {{ print "-->debug: %s"%string }}
        | hostgroup_def
        | CONDITIONS {{ nodes.declare_conditions( CONDITIONS, self._scanner.filename ) }}
        | TABLE tablename {{ table_name = tablename }} HOST {{ hostlist = [ ] }}
		    ( 
			    name {{ hostlist.append(name) }} 
                | hostgroup {{ hostlist = hostlist + nodes.get_hostgroup( hostgroup ) }}
		    )+  
	        command_list  
            # command_list is a list of (command, pos) where command is the text from the file and pos is the location in the file
                {{ self.data.add_command_list( table_name, hostlist, command_list )  }}
        | IMPORT string {{ self.data.import_list.append( string[1:-1] ) }}

    ##
    rule hostgroup_def :
        HOSTGROUP hostgroup {{ nodes.define_hostgroup( hostgroup) }}
            ( hostgroup_if<<hostgroup>> )+ 

    rule hostgroup_if<<hg>> :
        IF name 
            {{ accept_nodes = nodes.check_condition(name, self._scanner.filename ) }}
            COLON ( 
                name {{ if accept_nodes : nodes.add_hostgroup( hg, name ) }}
            )+  

    rule command_list:  
	# one or more commands, appended together into a list
        {{ cmlist = [ ] }} 
        command {{ cmlist.append( command ) }} 
        [ 
		command_list {{ cmlist += command_list }} 
	] 
        {{ return cmlist }} 
   	| {{ return [ ] }}

    rule command: 
	# a single command, including any number of AFTER clauses
        CMD  {{ cmd_pos = self._scanner.get_pos() }} 
    	    cmdname  {{ cmd_name=cmdname; script=cmdname; x_after_clause = [ ] }} 
            [ RUN string {{ script = string[1:-1]; script_type='r' }} 
		| LOCAL string {{ script = string[1:-1]; script_type='l' }} 
	    ]
            ( {{ after_pos = self._scanner.get_pos() }} 
		AFTER optword after_spec {{ x_after_clause.append( (after_spec, optword, after_pos) ) }}
	    )*
            {{ return ( cmd_name, script, script_type, x_after_clause, cmd_pos ) }}  

    # in the AFTER clause, you can say OPT to mean the node is optional (not an error if it does not exist)
    rule optword:
        OPT {{ return 0 }}
        | {{ return 1 }}

    rule after_spec: 
        wildname {{ rval = wildname }} 
        [ COLON  wildname {{ rval = rval + ':' + wildname }} ]
        [ SLASH  wildname {{ rval = rval + '/' + wildname }} ]
        {{ return rval }}

%%