first draft degree parser
This commit is contained in:
parent
27d05f0712
commit
484cc4235f
192
degrees.py
192
degrees.py
|
|
@ -1,5 +1,5 @@
|
||||||
from lark import Lark, Transformer, v_args
|
from lark import Lark, Transformer, v_args
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,57 +13,57 @@ consist of groups of courses that must be taken. The groups have rules associate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
grammar = """
|
|
||||||
start: program
|
|
||||||
|
|
||||||
program: course_declaration*
|
|
||||||
|
|
||||||
course_declaration: "course" CNAME INT "prerequisites" (CNAME ","?)* "degree" CNAME "{" degree_rule* "}"
|
|
||||||
|
|
||||||
degree_rule: "take" ("all" | "at" INT "from") ("the" "following") "courses" course_list
|
|
||||||
|
|
||||||
course_list: (CNAME ","?)*
|
|
||||||
|
|
||||||
%import common.CNAME
|
|
||||||
%import common.INT
|
|
||||||
%import common.WS
|
|
||||||
%ignore WS
|
|
||||||
"""
|
|
||||||
|
|
||||||
class Course:
|
class Course:
|
||||||
def __init__(self, name, units, prerequisites, degree):
|
def __init__(self, name, units, prerequisites=[]):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.units = units
|
self.units = units
|
||||||
self.prerequisites = prerequisites
|
self.prerequisites = prerequisites
|
||||||
self.degree = degree
|
def __repr__(self):
|
||||||
|
return f"{self.name} ({self.units} units)"
|
||||||
|
|
||||||
class DegreeRule:
|
class DegreeRule:
|
||||||
def __init__(self, verb, n, course_list):
|
def __init__(self, rule_type, course_list):
|
||||||
self.verb = verb
|
self.rule_type = rule_type
|
||||||
self.n = n
|
if 'n' in rule_type.__dict__: self.n = rule_type.n
|
||||||
self.course_list = course_list
|
self.course_list = course_list
|
||||||
|
def __repr__(self):
|
||||||
|
return f"DegreeRule({self.rule_type}, {self.course_list})"
|
||||||
|
|
||||||
class Degree:
|
class Degree:
|
||||||
def __init__(self, name, degree_rules):
|
def __init__(self, name, degree_rules):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.degree_rules = degree_rules
|
self.degree_rules = degree_rules
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Degree({self.name}, {self.degree_rules})"
|
||||||
|
|
||||||
|
class RuleType():
|
||||||
|
def __init__(self,what,n=0):
|
||||||
|
self.what = what
|
||||||
|
self.n = n
|
||||||
|
def __repr__(self):
|
||||||
|
return "" #f"RuleType({self.what}, {self.n})"
|
||||||
|
|
||||||
class Rule:
|
class Rule:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TakeAll(Rule):
|
class TakeAll(Rule):
|
||||||
def __init__(self, courses):
|
def __repr__(self):
|
||||||
self.courses = courses
|
return f"Take all:"
|
||||||
|
|
||||||
class TakeN(Rule):
|
class TakeN(Rule):
|
||||||
def __init__(self, courses, n):
|
def __init__(self, n):
|
||||||
self.courses = courses
|
|
||||||
self.n = n
|
self.n = n
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Take {self.n} courses:"
|
||||||
|
|
||||||
class TakeNUnits(Rule):
|
class TakeNUnits(Rule):
|
||||||
def __init__(self, courses, n):
|
def __init__(self, n):
|
||||||
self.courses = courses
|
|
||||||
self.n = n
|
self.n = n
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Take {self.n} units:"
|
||||||
|
|
||||||
|
|
||||||
@v_args(inline=True)
|
@v_args(inline=True)
|
||||||
class DSLTransformer(Transformer):
|
class DSLTransformer(Transformer):
|
||||||
|
|
@ -71,38 +71,44 @@ class DSLTransformer(Transformer):
|
||||||
self.courses = {}
|
self.courses = {}
|
||||||
self.degrees = {}
|
self.degrees = {}
|
||||||
|
|
||||||
def course_declaration(self, name, units, prerequisites, degree):
|
def course_declaration(self, name, units):
|
||||||
return Course(name, int(units), prerequisites.children, degree)
|
#return Course(name, int(units), prerequisites.children)
|
||||||
|
self.courses[name.value] = Course(name.value, int(units))
|
||||||
|
|
||||||
def degree(self, name, required_courses):
|
'''def program(self, name, rules):
|
||||||
self.degrees[name] = Degree(name, required_courses)
|
self.degrees[name.value] = Degree(name.value, rules)
|
||||||
|
return self.degrees[name.value]'''
|
||||||
|
|
||||||
def take_all(self, courses):
|
def rule_type(self, items):
|
||||||
return TakeAll(courses)
|
what = items[0]
|
||||||
|
|
||||||
def take_n(self, courses, n):
|
|
||||||
return TakeN(courses, n)
|
|
||||||
|
|
||||||
def take_n_units(self, courses, n):
|
|
||||||
return TakeNUnits(courses, n)
|
|
||||||
|
|
||||||
def degree_rule(self, items):
|
|
||||||
verb = items[0]
|
|
||||||
n = None
|
n = None
|
||||||
course_list = items[-1]
|
if len(items) == 2:
|
||||||
if len(items) == 4:
|
n = int(items[1])
|
||||||
n = int(items[2])
|
return RuleType(what, n)
|
||||||
return DegreeRule(verb, n, course_list.children)
|
|
||||||
|
|
||||||
def course_list(self, items):
|
def take_all(self):
|
||||||
return items[:-1]
|
return TakeAll()
|
||||||
|
|
||||||
def program(self, items):
|
def take_n_courses(self, n):
|
||||||
courses = [item for item in items if isinstance(item, Course)]
|
return TakeN(n)
|
||||||
degrees = [item for item in items if isinstance(item, Degree)]
|
|
||||||
return courses, degrees
|
|
||||||
|
|
||||||
|
def take_n_units(self, n):
|
||||||
|
return TakeNUnits(n)
|
||||||
|
|
||||||
|
def degree_rule(self, rule_type, course_list):
|
||||||
|
return DegreeRule(rule_type, course_list)
|
||||||
|
|
||||||
|
def course_list(self, *courses):
|
||||||
|
return [c.value for c in courses]
|
||||||
|
|
||||||
|
def program(self, *items):
|
||||||
|
#print(items)
|
||||||
|
name = items[0].value
|
||||||
|
rules = items[1:]
|
||||||
|
self.degrees[name] = Degree(name, rules)
|
||||||
|
return self.degrees[name]
|
||||||
|
|
||||||
|
"""
|
||||||
dsl = DSLTransformer()
|
dsl = DSLTransformer()
|
||||||
dsl.course('CS101', 3)
|
dsl.course('CS101', 3)
|
||||||
dsl.course('CS102', 3, prerequisites=['CS101'])
|
dsl.course('CS102', 3, prerequisites=['CS101'])
|
||||||
|
|
@ -115,11 +121,65 @@ dsl.degree('CS', [
|
||||||
|
|
||||||
print(dsl.courses)
|
print(dsl.courses)
|
||||||
print(dsl.degrees)
|
print(dsl.degrees)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
grammar = """
|
||||||
|
start: _spec+
|
||||||
|
|
||||||
|
_spec: program | course_declaration
|
||||||
|
|
||||||
|
program: "program" PROGRAMNAME degree_rule*
|
||||||
|
|
||||||
|
degree_rule: "take" rule_type course_list
|
||||||
|
|
||||||
|
rule_type: "all from" -> take_all
|
||||||
|
| "at least" INT "units from" -> take_n_units
|
||||||
|
| "at least" INT "courses from" -> take_n_courses
|
||||||
|
|
||||||
|
course_declaration: "course" COURSECODE INT "units" ["prerequisites" (COURSECODE ","?)*]
|
||||||
|
|
||||||
|
course_list: (COURSECODE ","?)*
|
||||||
|
|
||||||
|
COURSECODE: ("A".."Z")+ INT+ ["A".."Z"]*
|
||||||
|
PROGRAMNAME: ("A".."Z" | "a".."z")+
|
||||||
|
%import common.INT
|
||||||
|
%import common.WS
|
||||||
|
%ignore WS
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dsl = """
|
||||||
|
course CSIS1 2 units
|
||||||
|
course CSIS2 4 units
|
||||||
|
course ACCT120 3 units
|
||||||
|
course ACCT20 4 units
|
||||||
|
course BUS1 3 units
|
||||||
|
course ENGL250 3 units
|
||||||
|
course ACCT105 3 units
|
||||||
|
course ACCT121 3 units
|
||||||
|
course BOT100 3 units
|
||||||
|
course BOT105B 3 units
|
||||||
|
|
||||||
|
program BusinessAccountingOption
|
||||||
|
take all from CSIS1, CSIS2
|
||||||
|
take at least 6 units from ACCT120, ACCT20
|
||||||
|
take at least 3 courses from BUS1, ENGL250, ACCT120, BOT100, ACCT121, BOT105B
|
||||||
|
"""
|
||||||
|
|
||||||
|
parser = Lark(grammar)
|
||||||
|
print(parser.parse(dsl).pretty())
|
||||||
|
|
||||||
|
print("\n\n\n")
|
||||||
|
|
||||||
|
|
||||||
parser = Lark(grammar)
|
parser = Lark(grammar)
|
||||||
transformer = DSLTransformer()
|
transformer = DSLTransformer()
|
||||||
|
|
||||||
|
|
@ -127,24 +187,19 @@ def parse_dsl(dsl):
|
||||||
tree = parser.parse(dsl)
|
tree = parser.parse(dsl)
|
||||||
return transformer.transform(tree)
|
return transformer.transform(tree)
|
||||||
|
|
||||||
dsl = """
|
|
||||||
course CS101 3 prerequisites none degree CS {
|
result = parse_dsl(dsl)
|
||||||
take all the following courses {
|
|
||||||
CS102, CS103
|
print(transformer.courses)
|
||||||
}
|
print()
|
||||||
take at least 6 from {
|
print(transformer.degrees)
|
||||||
MATH101, MATH102, MATH103
|
print()
|
||||||
}
|
[print(c) for c in transformer.courses]
|
||||||
}
|
print()
|
||||||
|
[print(d) for d in transformer.degrees]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
courses, degrees = parse_dsl(dsl)
|
|
||||||
print(courses)
|
|
||||||
print(degrees)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def compute_degree_progress(student_courses, degree):
|
def compute_degree_progress(student_courses, degree):
|
||||||
total_units_completed = 0
|
total_units_completed = 0
|
||||||
|
|
@ -162,3 +217,4 @@ def compute_degree_progress(student_courses, degree):
|
||||||
progress_percent = total_units_completed / total_required_units * 100 if total_required_units > 0 else 0
|
progress_percent = total_units_completed / total_required_units * 100 if total_required_units > 0 else 0
|
||||||
return progress_percent
|
return progress_percent
|
||||||
|
|
||||||
|
"""
|
||||||
Loading…
Reference in New Issue