From 238cbe0e71422e7f00b1e66c5a71d15a258d9c86 Mon Sep 17 00:00:00 2001 From: Trolli Schmittlauch Date: Mon, 26 Jun 2017 15:19:51 +0200 Subject: [PATCH] successfully parsing jobshop1 to list of JobShopProblem s --- src/JobShopParser/common.py | 20 +++++++ src/JobShopParser/jobshop1_parser.py | 87 ++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 5 deletions(-) diff --git a/src/JobShopParser/common.py b/src/JobShopParser/common.py index 778beda..0540572 100644 --- a/src/JobShopParser/common.py +++ b/src/JobShopParser/common.py @@ -1,3 +1,5 @@ +from typing import List, Tuple + grammar = """ # starting point for jobshop1 input file job_shop1 = skip_preface @@ -27,3 +29,21 @@ grammar = """ # task data for 1 job job_data = ' '* machine ' '+ duration (' '+ machine ' '+ duration)* trim_ws eol """ + +class ParseError(Exception): + """To be thrown when parsing goes wrong""" + + def __init__(self, message: str) -> None: + self.message = message + +class JobShopProblem: + + def __init__(self, jobs: int, machines: int, problem_data: List[List[Tuple[int, int]]], name: str = 'unnamed', description: str = '') -> None: + self.description = description + self.name = name + self.problem_data = problem_data + self.machines = machines + self.jobs = jobs + + def __unicode__() -> str: + return name diff --git a/src/JobShopParser/jobshop1_parser.py b/src/JobShopParser/jobshop1_parser.py index 2ffccab..d53f8cd 100644 --- a/src/JobShopParser/jobshop1_parser.py +++ b/src/JobShopParser/jobshop1_parser.py @@ -1,9 +1,86 @@ from arpeggio.cleanpeg import ParserPEG +from typing import List, Tuple, Sequence, Optional +import arpeggio -from common import grammar +from common import grammar, ParseError, JobShopProblem +#from . import JobShopProblem -parser = ParserPEG(grammar, "job_shop1", skipws=False,debug=True) +class JobShop1Visitor(arpeggio.PTNodeVisitor): -with open("./inputdata/jobshop1.txt") as datafile: - inputdata : str = datafile.read() - parse_tree = parser.parse(inputdata) + def visit_nonneg_num(self, node: arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> int: + if self.debug: + print("Converting non-negative integer", node.value) + return int(node.value) + + def visit_machine(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> int: + return int(node.value) + + def visit_duration(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> int: + return int(node.value) + + def visit_num_machines(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> int: + return int(node.value) + + def visit_num_jobs(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> int: + return int(node.value) + + def visit_job_data(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> List[Tuple[int, int]]: + if self.debug: + print("Job data:\nnode:", type(node), "children:", children) + job_numbers = list(filter(lambda x: type(x) is int, children)) + # job data needs to consist out of pairs of numbers + if len(job_numbers) % 2 ==1: + raise ParseError("Odd number of numbers in job data") + # returns list of (duration, machine) tuples + return list(zip(job_numbers[1::2], job_numbers[0::2])) + + def visit_problem_data(self, node: arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> JobShopProblem: + if self.debug: + print("problem_data\nchildren:", children) + problem_data: List[List[Tuple(int, int)]] = [ children[i] for i in range(2, len(children))] + return JobShopProblem(children[0], children[1], problem_data) + + def visit_problem_instance(self, node: arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> JobShopProblem: + if self.debug: + print("problem_instance\nchildren:", children) + problem: JobShopProblem = children[3] + problem.name = children[0] + problem.description = children[2] + return problem + + def visit_instance_list(self, node: arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> List[JobShopProblem]: + if self.debug: + print("instance_list\nchildren:", children) + return list(filter(lambda x: isinstance(x, JobShopProblem), children)) + + def visit_skip_preface(self, node: arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> List[JobShopProblem]: + if self.debug: + print("skip_preface\nchildren:", children) + return list(filter(lambda x: type(x) is list, children))[0] + + def visit_job_shop1(self, node: arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> List[JobShopProblem]: + if self.debug: + print("job_shop1\nchildren:", children) + + # ignore eol nodes + def visit_eol(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> None: + return None + + # ignore trim_ws nodes + def visit_trim_ws(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> None: + return None + + + #def visit_instance_list(self, node, children): + +def main(): + parser = ParserPEG(grammar, "job_shop1", skipws=False) + + with open("./inputdata/jobshop1.txt") as datafile: + inputdata : str = datafile.read() + parse_tree = parser.parse(inputdata) + result = arpeggio.visit_parse_tree(parse_tree, JobShop1Visitor(debug=True)) + print("\n\n\nResult:", result) + +if __name__ == "__main__": + main()