Skip to content

Instantly share code, notes, and snippets.

@GoldsteinE
Created December 12, 2017 12:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GoldsteinE/b38f779c009f350ad4faad83325f8b0d to your computer and use it in GitHub Desktop.
Save GoldsteinE/b38f779c009f350ad4faad83325f8b0d to your computer and use it in GitHub Desktop.
structs.py
import re
class MakefileError(Exception):
pass
class MakefileHeaderError(MakefileError):
pass
class MakefileLinksError(MakefileError):
pass
class MakefileNamingError(MakefileError):
pass
class Goal:
def __init__(self, name, parents):
self.parents = parents
self.commands = []
self.name = name
def add_command(self, command):
self.commands.append(command.strip())
@classmethod
def parse_header(cls, string):
if ':' not in string:
raise HeaderError('Wrong goal header format, missing colon')
name_str, parents_str = string.split(':')
name = name_str.strip()
if not re.match('^[a-zA-Z0-9+-]+$', name):
raise MakefileNamingError('Wrong name: {}'.format(name))
parents = parents_str.split()
return cls(name, parents)
class Makefile:
def __init__(self):
self.goals = dict()
def add_goal(self, goal):
if goal.name in self.goals:
raise MakefileNamingError('Found name duplication: {}'.format(goal.name))
self.goals[goal.name] = goal
def check_loops(self, node):
def dfs(curr_node, visited):
if curr_node.name in visited:
raise MakefileLinksError('Found loop dependency')
for parent in curr_node.parents:
dfs(self.goals[parent], visited.union({curr_node.name}))
dfs(node, set())
def check(self):
for goal in self.goals.values():
for parent in goal.parents:
if parent not in self.goals:
raise MakefileLinksError('Found broken dependency: {}'.format(parent))
for goal in self.goals.values():
self.check_loops(goal)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment