Example #1
0
class SpecFileParser(SpecModelParser):
	'''
	A spec parser
	'''
	def __init__(self, writer):
		self.token_list = None
		self.set_model_writer(writer)
		self.MANIPULATORS = [
				SpecIfParser,
				SpecDefinitionParser,
				SpecGlobalParser,
				SpecDefineParser,
				SpecBuildParser,
				SpecChangelogParser,
				SpecCheckParser,
				SpecCleanParser,
				SpecDescriptionParser,
				SpecFilesParser,
				SpecInstallParser,
				SpecPackageParser,
				SpecPrepParser,
				SpecPreParser,
				SpecPostParser,
				SpecPreunParser,
				SpecPostunParser,
				SpecPretransParser,
				SpecPosttransParser,
				SpecTriggerParser,
				SpecTriggerinParser,
				SpecTriggerpreinParser,
				SpecTriggerunParser,
				SpecTriggerpostunParser,
				SpecVerifyscriptParser
			]

	def init(self, f):
		'''
		Init parser
		@param f: FILE or a string to init parser from
		@type f: FILE or a string
		@return: None
		@rtype: None
		'''
		self.token_list = SpecTokenList(f)

	@staticmethod
	def section_beginning_callback(obj, token_list):
		'''
		A callback for L{SpecTokenList} used to check whether next token is
		a section token
		@param obj: self instance
		@type obj: L{SpecModelParser} instance
		@param token_list: token list to be used
		@type token_list: L{SpecTokenList}
		@return: section parser to be used for parsing the upcoming section
		@rtype: L{SpecModelParser}
		'''
		return obj.section_beginning(token_list)

	def section_beginning(self, token_list):
		'''
		Check whether next token is a section token
		@param token_list: token list to be used
		@type token_list: L{SpecTokenList}
		@return: section parser to be used to parse the upcoming section
		@rtype: L{SpecModelParser}
		'''
		for parser in self.MANIPULATORS:
			ret = parser.section_beginning(token_list)
			if ret is not None:
				return parser

		return None # Not found

	@staticmethod
	def section_beginning_callback_no_if(obj, token_list):
		'''
		A callback for L{SpecTokenList} used to check whether next token is
		a section token, skip %ifs
		@param obj: self instance
		@type obj: L{SpecModelParser} instance
		@param token_list: token list to be used
		@type token_list: L{SpecTokenList}
		@return: section parser to be used for parsing the upcoming section
		@rtype: L{SpecModelParser}
		'''
		return obj.section_beginning_no_if(token_list)

	def section_beginning_no_if(self, token_list):
		'''
		Check whether next token is a section token, skip %if
		@param token_list: token list to be used
		@type token_list: L{SpecTokenList}
		@return: section parser to be used to parse the upcoming section
		@rtype: L{SpecModelParser}
		'''
		for parser in self.MANIPULATORS:
			ret = parser.section_beginning(token_list)
			if ret is not None and not issubclass(ret, SpecStIf):
				return parser

		return None # Not found

	def parse_loop(self, token_list, parent, allowed):
		'''
		Main parse loop to get list of parsed sections
		@param token_list: a list of tokens to be used
		@type token_list: L{SpecTokenList}
		@param parent: parent section
		@type parent: L{SpecSection}
		@param allowed: allowed sections to be parsed, section parsers
		@type allowed: list of L{SpecSectionParser}
		@return: list of parsed sections
		@rtype: L{SpecSection}
		'''
		ret = []

		found = True
		while found:
			found = False
			token = token_list.touch()
			SpecDebug.debug("- parsing round: '%s'" % str(token))

			if token.is_eof():
				break

			for t in allowed:
				section = t.parse(token_list, parent, allowed, self)
				if section:
					found = True
					SpecDebug.debug("- adding parsed section '%s'" % type(section))
					ret.append(section)
					break

			if not found:
				SpecDebug.debug("- unparsed token '%s' on line %s" % (str(token), str(token.line)))

		return ret

	def parse_preamble(self):
		'''
		Parse preamble of a spec file
		@return: parsed sections in preamble
		@rtype: list of L{SpecSection}
		'''
		allowed = [ SpecIfParser, SpecDefinitionParser, SpecGlobalParser ]

		ret = self.parse_loop(self.token_list, None, allowed)
		unparsed = self.token_list.touch()
		SpecDebug.debug("-- preamble finished with token '%s' on line %d" % (str(unparsed), unparsed.line))
		return ret

	def parse_loop_section(self):
		'''
		Parse sections after preamble
		@return: list of parsed sections
		@rtype: list of L{SpecSection}
		'''
		allowed = copy.deepcopy(self.MANIPULATORS)
		return self.parse_loop(self.token_list, None, allowed)

	def parse(self):
		'''
		Main parser entry point - parse provided spec file
		@return: None
		@rtype:
		@raise SpecBadToken: when an unexpected token is reached
		'''
		self.get_model_writer().append_items(self.parse_preamble())
		self.get_model_writer().append_items(self.parse_loop_section())

		eof = self.token_list.touch()
		if not eof.is_eof():
			raise SpecBadToken("Unexpected symbol '" + str(eof.token) + "' on line " + str(eof.line))