add library parse function fpr jobshop1

- also extract common semantic analysis (Visitor) code
This commit is contained in:
Trolli Schmittlauch 2017-06-26 16:05:49 +02:00
parent 238cbe0e71
commit 8c1d6e12be
2 changed files with 56 additions and 45 deletions

View file

@ -1,4 +1,5 @@
from typing import List, Tuple from typing import List, Tuple, Sequence, Optional, Union
import arpeggio
grammar = """ grammar = """
# starting point for jobshop1 input file # starting point for jobshop1 input file
@ -45,5 +46,44 @@ class JobShopProblem:
self.machines = machines self.machines = machines
self.jobs = jobs self.jobs = jobs
def __unicode__() -> str: def __str__() -> str:
return name return name
class JobShopVisitor(arpeggio.PTNodeVisitor):
"""contains visitor functions needed for both jobshop1 (list of instances)
and jobshop2 (single instance without name & description) input data"""
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)

View file

@ -1,44 +1,12 @@
from arpeggio.cleanpeg import ParserPEG from arpeggio.cleanpeg import ParserPEG
from typing import List, Tuple, Sequence, Optional from typing import List, Tuple, Sequence, Optional, Union
import arpeggio import arpeggio
from common import grammar, ParseError, JobShopProblem from common import grammar, ParseError, JobShopProblem, JobShopVisitor
#from . import JobShopProblem #from . import JobShopProblem
class JobShop1Visitor(arpeggio.PTNodeVisitor): class JobShop1Visitor(JobShopVisitor):
"""instanciated for semantic analysis of parse_tree"""
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: def visit_problem_instance(self, node: arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> JobShopProblem:
if self.debug: if self.debug:
@ -70,17 +38,20 @@ class JobShop1Visitor(arpeggio.PTNodeVisitor):
def visit_trim_ws(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> None: def visit_trim_ws(self, node:arpeggio.ParseTreeNode, children: arpeggio.SemanticActionResults) -> None:
return None return None
def parse_jobshop1_file(filename: Union[str, bytes]) -> List[JobShopProblem]:
"""Open file with jobshop1-formatted data (multiple problem instances),
parse it and return list of JobShopProblem s"""
#def visit_instance_list(self, node, children): with open(filename) as datafile:
inputdata: str = datafile.read()
parse_tree = parser.parse(inputdata)
return arpeggio.visit_parse_tree(parse_tree, JobShop1Visitor())
def main(): def main():
parser = ParserPEG(grammar, "job_shop1", skipws=False) print(parse_jobshop1_file("inputdata/jobshop1.txt"))
with open("./inputdata/jobshop1.txt") as datafile: parser = ParserPEG(grammar, "job_shop1", skipws=False)
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__": if __name__ == "__main__":
main() main()