Skip to content

Commit

Permalink
Removed support for sublevels (hedyorg#935)
Browse files Browse the repository at this point in the history
  • Loading branch information
boryanagoncharenko authored Oct 9, 2021
1 parent 2a8d544 commit 6192553
Show file tree
Hide file tree
Showing 11 changed files with 35 additions and 325 deletions.
12 changes: 2 additions & 10 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,11 @@ def parse():
return "body.code must be a string", 400
if 'level' not in body:
return "body.level must be a string", 400
if 'sublevel' in body and not isinstance(body ['sublevel'], int):
return "If present, body.sublevel must be an integer", 400
if 'adventure_name' in body and not isinstance(body ['adventure_name'], str):
return "if present, body.adventure_name must be a string", 400

code = body ['code']
level = int(body ['level'])
sublevel = body.get ('sublevel') or 0

# Language should come principally from the request body,
# but we'll fall back to browser default if it's missing for whatever
Expand All @@ -284,7 +281,7 @@ def parse():
try:
hedy_errors = TRANSLATIONS.get_translations(lang, 'HedyErrorMessages')
with querylog.log_time('transpile'):
transpile_result = hedy.transpile(code, level, sublevel)
transpile_result = hedy.transpile(code, level)
python_code = transpile_result.code
has_turtle = transpile_result.has_turtle

Expand Down Expand Up @@ -663,12 +660,7 @@ def adventure_page(adventure_name, level):
@app.route('/hedy/<level>', methods=['GET'], defaults={'step': 1})
@app.route('/hedy/<level>/<step>', methods=['GET'])
def index(level, step):
# Sublevel requested
if re.match ('\d+-\d+', level):
pass
# If level has a dash, we keep it as a string
# Normal level requested
elif re.match ('\d', level):
if re.match('\d', level):
try:
g.level = level = int(level)
except:
Expand Down
10 changes: 2 additions & 8 deletions coursedata/course/hedy/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,11 @@ course:
- level: "1"
- level: "2"
- level: "3"
-
level: "4"
subs:
- sub: "1"
- level: "4"
- level: "5"
- level: "6"
- level: "7"
-
level: "8"
subs:
- sub: "1"
- level: "8"
- level: "9"
- level: "10"
- level: "11"
Expand Down
12 changes: 1 addition & 11 deletions courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def course(self):
def max_level(self):
return len(self.course)

def get_default_text(self, level, sublevel=0):
def get_default_text(self, level):

"""Return the 1-based Assignment from this course."""
level_ix = int(level) - 1
Expand All @@ -72,16 +72,6 @@ def validate_course(self, course):
expected_value = str(level_i + 1)
actual_value = level.get('level')

# Check for sub levels
subs = level.get('subs')
if (subs):
for sub_i, sub in enumerate(subs):
expected_sub = str(sub_i + 1)
actual_sub = sub.get('sub')
if expected_sub != actual_sub:
raise RuntimeError(f'Expected \'sub: "{expected_sub}"\' but got "{actual_sub}" in {self.course_name}-{self.language}')


if expected_value != actual_value:
raise RuntimeError(f'Expected \'level: "{expected_value}"\' but found "{actual_value}" in {self.course_name}-{self.language}')

Expand Down
1 change: 0 additions & 1 deletion grammars/level4-1-Additions.lark

This file was deleted.

4 changes: 0 additions & 4 deletions grammars/level8-1-Additions.lark

This file was deleted.

98 changes: 29 additions & 69 deletions hedy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from lark.exceptions import LarkError, UnexpectedEOF, UnexpectedCharacters
from lark import Tree, Transformer, visitors
from os import path
import sys
import utils
from collections import namedtuple
import hashlib
Expand Down Expand Up @@ -1096,68 +1095,29 @@ def merge_grammars(grammar_text_1, grammar_text_2):
return '\n'.join(merged_grammar)


def create_grammar(level, sub):
# Load Lark grammars relative to directory of current file
script_dir = path.abspath(path.dirname(__file__))

# Load Lark grammars relative to directory of current file
script_dir = path.abspath(path.dirname(__file__))

# we start with creating the grammar for level 1
grammar_text_1 = get_full_grammar_for_level(1)
def create_grammar(level):
# start with creating the grammar for level 1
result = get_full_grammar_for_level(1)

if sub:
#grep
if level == 1:
# this is a level 1 sublevel, so get the sublevel grammar and return
grammar_text_sub = get_additional_rules_for_level(1, sub)
grammar_text = merge_grammars(grammar_text_1, grammar_text_sub)
return grammar_text

grammar_text_2 = get_additional_rules_for_level(2)

#start at 1 and keep merging new grammars in
new = merge_grammars(grammar_text_1, grammar_text_2)

for i in range(3, level+1):
grammar_text_i = get_additional_rules_for_level(i)
new = merge_grammars(new, grammar_text_i)

# get grammar for the sublevel and merge it
grammar_text_sub = get_additional_rules_for_level(level, sub)
new = merge_grammars(new, grammar_text_sub)

# ready? Save to file to ease debugging
# this could also be done on each merge for performance reasons
filename = "level" + str(level) + "-" + str(sub) + "-Total.lark"
loc = path.join(script_dir, "grammars-Total", filename)
file = open(loc, "w", encoding="utf-8")
file.write(new)
file.close()
else:
#grep
if level == 1:
grammar_text = get_full_grammar_for_level(level)
return grammar_text

grammar_text_2 = get_additional_rules_for_level(2)
# then keep merging new grammars in
for i in range(2, level+1):
grammar_text_i = get_additional_rules_for_level(i)
result = merge_grammars(result, grammar_text_i)

#start at 1 and keep merging new grammars in
new = merge_grammars(grammar_text_1, grammar_text_2)
# ready? Save to file to ease debugging
# this could also be done on each merge for performance reasons
save_total_grammar_file(level, result)

for i in range(3, level+1):
grammar_text_i = get_additional_rules_for_level(i)
new = merge_grammars(new, grammar_text_i)
return result

# ready? Save to file to ease debugging
# this could also be done on each merge for performance reasons
filename = "level" + str(level) + "-Total.lark"
loc = path.join(script_dir, "grammars-Total", filename)
file = open(loc, "w", encoding="utf-8")
file.write(new)
file.close()

return new
def save_total_grammar_file(level, grammar):
# Load Lark grammars relative to directory of current file
script_dir = path.abspath(path.dirname(__file__))
filename = "level" + str(level) + "-Total.lark"
loc = path.join(script_dir, "grammars-Total", filename)
file = open(loc, "w", encoding="utf-8")
file.write(grammar)
file.close()

def get_additional_rules_for_level(level, sub = 0):
script_dir = path.abspath(path.dirname(__file__))
Expand All @@ -1179,36 +1139,36 @@ def get_full_grammar_for_level(level):
PARSER_CACHE = {}


def get_parser(level, sub):
def get_parser(level):
"""Return the Lark parser for a given level.
Uses caching if Hedy is NOT running in development mode.
"""
key = str(level) + "." + str(sub)
key = str(level)
existing = PARSER_CACHE.get(key)
if existing and not utils.is_debug_mode():
return existing
grammar = create_grammar(level, sub)
grammar = create_grammar(level)
ret = Lark(grammar, regex=True)
PARSER_CACHE[key] = ret
return ret

ParseResult = namedtuple('ParseResult', ['code', 'has_turtle'])

def transpile(input_string, level, sub = 0):
def transpile(input_string, level):
try:
transpile_result = transpile_inner(input_string, level, sub)
transpile_result = transpile_inner(input_string, level)
return transpile_result
except ParseException as ex:
# This is the 'fall back' transpilation
# that should surely be improved!!
# we retry HedyExceptions of the type Parse (and Lark Errors) but we raise Invalids

#try 1 level lower
if level > 1 and sub == 0:
if level > 1:
try:
new_level = level - 1
result = transpile_inner(input_string, new_level, sub)
result = transpile_inner(input_string, new_level)
except (LarkError, HedyException) as innerE:
# Parse at `level - 1` failed as well, just re-raise original error
raise ex
Expand Down Expand Up @@ -1327,7 +1287,7 @@ def preprocess_blocks(code):
def contains_blanks(code):
return (" _ " in code) or (" _\n" in code)

def transpile_inner(input_string, level, sub=0):
def transpile_inner(input_string, level):
number_of_lines = input_string.count('\n')

#parser is not made for huge programs!
Expand All @@ -1337,7 +1297,7 @@ def transpile_inner(input_string, level, sub=0):
input_string = input_string.replace('\r\n', '\n')
punctuation_symbols = ['!', '?', '.']
level = int(level)
parser = get_parser(level, sub)
parser = get_parser(level)

if contains_blanks(input_string):
raise CodePlaceholdersPresentException()
Expand Down Expand Up @@ -1391,7 +1351,7 @@ def transpile_inner(input_string, level, sub=0):
#the error here is a space at the beginning of a line, we can fix that!
fixed_code = repair(input_string)
if fixed_code != input_string: #only if we have made a successful fix
result = transpile_inner(fixed_code, level, sub)
result = transpile_inner(fixed_code, level)
raise InvalidSpaceException(level, line, result.code)
elif args == 'print without quotes':
# grammar rule is ignostic of line number so we can't easily return that here
Expand Down
8 changes: 1 addition & 7 deletions hedyweb.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,7 @@ def get_translations(self, language, section):

def render_code_editor_with_tabs(request, course, level_number, menu, translations, version, loaded_program, adventures, adventure_name):

sublevel = None
if isinstance (level_number, str) and re.match ('\d+-\d+', level_number):
sublevel = int (level_number [level_number.index ('-') + 1])
level_number = int (level_number [0:level_number.index ('-')])

defaults = course.get_default_text(level_number, sublevel)
defaults = course.get_default_text(level_number)

if not defaults:
abort(404)
Expand All @@ -51,7 +46,6 @@ def render_code_editor_with_tabs(request, course, level_number, menu, translatio
# Meta stuff
arguments_dict['course'] = course
arguments_dict['level_nr'] = str(level_number)
arguments_dict['sublevel'] = str(sublevel) if (sublevel) else None
arguments_dict['lang'] = course.language
arguments_dict['level'] = defaults.level
arguments_dict['prev_level'] = int(level_number) - 1 if int(level_number) > 1 else None
Expand Down
2 changes: 0 additions & 2 deletions static/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ function runit(level, lang, cb) {
url: '/parse',
data: JSON.stringify({
level: level,
sublevel: window.State.sublevel ? window.State.sublevel : undefined,
code: code,
lang: lang,
read_aloud : !!$('#speak_dropdown').val(),
Expand Down Expand Up @@ -208,7 +207,6 @@ function tryPaletteCode(exampleCode) {


window.saveit = function saveit(level, lang, name, code, cb) {
if (window.State.sublevel) return window.modal.alert ('Sorry, you cannot save programs when in a sublevel.');
error.hide();

if (reloadOnExpiredSession ()) return;
Expand Down
1 change: 0 additions & 1 deletion templates/code-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ <h2>{{ commands_title }}</h2>
window.State = {};
window.State.lang = "{{ lang }}";
window.State.level = "{{ level }}";
window.State.sublevel = {{ sublevel or 0 }};
window.State.level_title = "{{ level_title }}";
window.State.adventure_name = "{{ adventure_name }}";
// A copy of window.State.adventure_name but that we don't overwrite when changing tabs. Useful for loading/saving programs when changing tabs.
Expand Down
1 change: 0 additions & 1 deletion templates/view-program-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ <h1>{{loaded_program.name}}</h1>
window.State = {};
window.State.lang = "{{ lang }}";
window.State.level = "{{ level }}";
window.State.sublevel = {{ sublevel or 0 }};
window.State.level_title = "{{ level_title }}";
</script>
<script src="{{static('/js/syntaxModesRules.js')}}" type="text/javascript" crossorigin="anonymous"></script>
Expand Down
Loading

0 comments on commit 6192553

Please sign in to comment.