# 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<> )+ rule hostgroup_if<> : 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 }} %%