Skip to content

Commit

Permalink
Merge pull request hedyorg#189 from Felienne/issue184
Browse files Browse the repository at this point in the history
Beautifies error messages, addressing issue 184
  • Loading branch information
fpereiro authored Mar 2, 2021
2 parents 84075bb + 5fb1e7f commit 9610500
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 14 deletions.
8 changes: 7 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ def before_request():
if not os.getenv('HEROKU_RELEASE_CREATED_AT'):
logging.warning('Cannot determine release; enable Dyno metadata by running "heroku labs:enable runtime-dyno-metadata -a <APP_NAME>"')


@app.route('/parse', methods=['POST'])
def parse():
body = request.json
Expand Down Expand Up @@ -123,6 +122,13 @@ def parse():
error_template = hedy_errors[E.error_code]
response["Code"] = "# coding=utf8\n" + E.arguments['fixed_code']
response["Warning"] = error_template.format(**E.arguments)
elif E.args[0] == "Parse":
error_template = hedy_errors[E.error_code]
# Localize the names of characters
# Localize the names of characters
if 'character_found' in E.arguments:
E.arguments['character_found'] = hedy_errors[E.arguments['character_found']]
response["Error"] = error_template.format(**E.arguments)
else:
error_template = hedy_errors[E.error_code]
response["Error"] = error_template.format(**E.arguments)
Expand Down
15 changes: 13 additions & 2 deletions coursedata/texts/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ui:
assignment_header: "Assignment"
ClientErrorMessages:
Transpile_warning: "Warning!"
Transpile_error: "The server couldn't translate this Hedy program to Python."
Transpile_error: "We can't run your program."
Connection_error: "We couldn't reach the server."
Other_error: "Oops! Maybe we made a little mistake."
Execute_error: "Something went wrong while running the program."
Expand All @@ -27,8 +27,19 @@ HedyErrorMessages:
Incomplete: "Oops! You forgot a bit of code! On line {line_number}, you need to enter text behind {incomplete_command}."
Invalid: "{invalid_command} is not a Hedy level {level} command. Did you mean {guessed_command}?"
Invalid Space: "Oops! You started a line with a space on line {line_number}. Spaces confuse computers, can you remove it?"
Parse: "The code you entered is not valid Hedy code. The error is: {parse_error}."
Parse: "The code you entered is not valid Hedy code. There is a mistake on line {location[0]}, at position {location[1]}. You typed {character_found}, but that is not allowed."
VarUndefined: "You tried to print {name}, but you did not instantiate it."
space: "a space"
comma: "a comma"
question mark: "a question mark"
newline: "a new line"
period: "a period"
exclamation mark: "an exclamation mark"
dash: "a dash"
star: "a star"
single quotes: "a single quote"
double quotes: "double quotes"
slash: "a slash"
Auth:
create_account: "Create account"
create_account_explanation: "Having your own account allows you to save your programs."
Expand Down
15 changes: 13 additions & 2 deletions coursedata/texts/es.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ui:
assignment_header: "Asignación"
ClientErrorMessages:
Transpile_warning: "Atención!"
Transpile_error: "El servidor no puede traducir este programa de Hedy a Python."
Transpile_error: "El servidor no puede traducir este programa."
Connection_error: "No pudimos conectarnos con el servidor."
Other_error: "Oops! Posiblemente hicimos un pequeño error."
Execute_error: "Algo estuvo mal mientras se ejecuto el programa."
Expand All @@ -27,8 +27,19 @@ HedyErrorMessages:
Incomplete: "Oops! Has olvidado algo de código! En la línea {line_number}, debes agregar texto después de {incomplete_command}."
Invalid: "{invalid_command} no es un comando de Hedy en nivel {level}. {guessed_command}?"
Invalid Space: "Oops! Has comenzado una línea con un espacio en la línea {line_number}. Los espacios confunden a las computadoras, ¿podrías quitarlos?"
Parse: "El servidor no puede traducir este programa de Hedy a Python. Error: {parse_error}"
Parse: "El servidor no puede traducir este programa de Hedy. Hay un error en la línea {location[0]}, carácter {location[1]}. Tu has ingresado {character_found}, pero eso no está permitido."
VarUndefined: "Intentaste imprimir {name}, pero no lo instanciaste."
space: "un espacio"
comma: "una coma"
question mark: "un signo de interrogación"
newline: "un salto de línea"
period: "un punto"
exclamation mark: "un signo de exclamación"
dash: "un guión"
star: "un asterisco"
single quotes: "una comilla simple"
double quotes: "una comilla doble"
slash: "una barra"
Auth:
create_account: "Crear cuenta"
create_account_explanation: "Con tu cuenta puedes salvar tus programas."
Expand Down
16 changes: 14 additions & 2 deletions coursedata/texts/fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ui:
assignment_header: "Exercice"
ClientErrorMessages:
Transpile_warning: "Attention!"
Transpile_error: "Le serveur n’a pas pu traduire ce code Hedy en Python."
Transpile_error: "Le serveur n’a pas pu traduire ce code."
Connection_error: "Nous n’avons pas réussi à contacter le serveur."
Other_error: "Oups! Nous avons rencontré une erreur."
Execute_error: "Quelque chose s’est mal passé en exécutant ce programme."
Expand All @@ -38,8 +38,20 @@ HedyErrorMessages:
Peux tu le supprimer?
Parse: >
Le code saisi n’est pas du Hedy valide.
L’erreur rencontrée est: {parse_error}.
L’erreur rencontrée est:
There is a mistake on line {location[0]}, at position {location[1]}. You typed {character_found}, but that is not allowed.
VarUndefined: "Tu as essayé d’afficher {name}, mais tu ne l’as pas initialisé."
space: "a space"
comma: "a comma"
question mark: "a question mark"
newline: "a new line"
period: "a period"
exclamation mark: "an exclamation mark"
dash: "a dash"
star: "a star"
single quotes: "a single quote"
double quotes: "double quotes"
slash: "a slash"
Auth:
create_account: "Create account"
create_account_explanation: "Having your own account allows you to save your programs."
Expand Down
13 changes: 12 additions & 1 deletion coursedata/texts/nl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,19 @@ HedyErrorMessages:
Incomplete: "Let op, je bent een stukje code vergeten. Op regel {line_number} moet er achter {incomplete_command} nog tekst komen."
Invalid: "{invalid_command} is geen commando in Hedy level {level}. Bedoelde je {guessed_command}?"
Invalid Space: "Oeps! Regel {line_number} begint met een spatie. Computers kunnen niet zo goed tegen spaties, kun je 'm weghalen?"
Parse: "De code die jij intypte is geen geldige Hedy code. De foutmelding is: {parse_error}."
Parse: "De code die jij intypte is geen geldige Hedy code. Er zit een foutje op regel {location[0]}, op positie {location[1]}. Jij typte {character_found}, maar dat mag op die plek niet."
VarUndefined: "Je probeerde de naam {name} te printen, maar die heb je niet ingesteld."
space: "een spatie"
comma: "een komma"
question mark: "een vraagteken"
newline: "een enter"
period: "een punt"
exclamation mark: "een uitroepteken"
dash: "een streepje"
star: "een sterretje"
single quotes: "een hoge komma"
double quotes: "twee hoge komma's"
slash: "een schuin streepje"
Auth:
create_account: "Maak een account"
create_account_explanation: "Met een account je kunt jouw programma's opslaan."
Expand Down
15 changes: 13 additions & 2 deletions coursedata/texts/pt_br.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ui:
assignment_header: "Tarefa"
ClientErrorMessages:
Transpile_warning: "Aviso!"
Transpile_error: "O servidor não pode traduzir este programa Hedy para Python."
Transpile_error: "O servidor não pode traduzir este programa."
Connection_error: "Nós não pudemos contactar o servidor."
Other_error: "Opa! Talvez nós fizemos alguma coisa errada."
Execute_error: "Alguma coisa deu errado enquanto o programa era executado."
Expand All @@ -27,8 +27,19 @@ HedyErrorMessages:
Incomplete: "Opa! Você esqueceu um pedaço do código! Na linha {line_number}, você precisa entrar com texto após {incomplete_command}."
Invalid: "{invalid_command} não é um commando Hedy do nível {level}. Você quis dizer {guessed_command}?"
Invalid Space: "Opa! Você começou uma linha com um espaço na linha {line_number}. Espaços confundem os computadores, você poderia removê-lo?"
Parse: "O código que você enivou não é um código Hedy válido. O erro é: {parse_error}."
Parse: "O código que você enviou não é um código Hedy válido. O erro é: {parse_error}. O erro é na linha {location[0]}, posição {location[1]}. Você escreveu {character_found}, mas isso não é permitido."
VarUndefined: "Você tentou printar {name}, mas você não o instanciou."
space: "um espaço"
comma: "uma vírgula"
question mark: "um ponto de interrogação"
newline: "uma nova linha"
period: "um ponto"
exclamation mark: "um ponto de exclamação"
dash: "uma meia-risca"
star: "um asterisco"
single quotes: "aspas simples"
double quotes: "aspas duplas"
slash: "uma barra"
Auth:
create_account: "Create account"
create_account_explanation: "Having your own account allows you to save your programs."
Expand Down
67 changes: 64 additions & 3 deletions hedy.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from lark import Lark
from lark.exceptions import VisitError, LarkError
from lark.exceptions import VisitError, LarkError, UnexpectedEOF
from lark import Tree, Transformer, Visitor
from lark.indenter import Indenter
import sys
Expand Down Expand Up @@ -660,7 +660,60 @@ def repair(input_string):
#the only repair we can do now is remove leading spaces, more can be added!
return '\n'.join([x.lstrip() for x in input_string.split('\n')])

def translate_characters(s):
# this method is used to make it more clear to kids what is meant in error messages
# for example ' ' is hard to read, space is easier
# this could (should?) be localized so we can call a ' "Hoge komma" for example (Felienne, dd Feb 25, 2021)
if s == ' ':
return 'space'
elif s == ',':
return 'comma'
elif s == '?':
return 'question mark'
elif s == '\\n':
return 'newline'
elif s == '.':
return 'period'
elif s == '!':
return 'exclamation mark'
elif s == '*':
return 'star'
elif s == "'":
return 'single quotes'
elif s == '"':
return 'double quotes'
elif s == '/':
return 'slash'
elif s == '-':
return 'dash'
elif s >= 'a' and s <= 'z' or s >= 'A' and s <= 'Z':
return s
else:
return s

def filter_and_translate_terminals(list):
# in giving error messages, it does not make sense to include
# ANONs, and some things like EOL need kid friendly translations
new_terminals = []
for terminal in list:
if terminal[:4] == "ANON":
continue

if terminal == "EOL":
new_terminals.append("Newline")
break

#not translated or filtered out? simply add as is:
new_terminals.append(terminal)

return new_terminals

def beautify_parse_error(error_message):

character_found = error_message.split("'")[1]
character_found = translate_characters(character_found)

return character_found

def transpile_inner(input_string, level):
if level <= 6:
Expand All @@ -674,8 +727,16 @@ def transpile_inner(input_string, level):
lookup_table = AllAssignmentCommands().transform(abstract_syntaxtree)

except Exception as e:
# TODO: if all else fails, here we could translate Lark error messages into more sensible texts!
raise HedyException('Parse', level=level, parse_error=e.args[0]) from e
try:
location = e.line, e.column
characters_expected = str(e.allowed)
character_found = beautify_parse_error(e.args[0])
# print(e.args[0])
# print(location, character_found, characters_expected)
raise HedyException('Parse', level=level, location=location, character_found=character_found, characters_expected=characters_expected) from e
except UnexpectedEOF:
# this one can't be beautified (for now), so give up :)
raise e

is_valid = IsValid().transform(program_root)
if not is_valid[0]:
Expand Down
15 changes: 14 additions & 1 deletion tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def test_two_lines_start_with_spaces(self):


def test_transpile_empty(self):
with self.assertRaises(hedy.HedyException) as context:
with self.assertRaises(Exception) as context:
result = hedy.transpile("", 1)

def test_transpile_ask(self):
Expand Down Expand Up @@ -422,6 +422,19 @@ def test_pront_should_suggest_print(self):
self.assertEqual('print', str(context.exception.arguments['guessed_command']))


def test_parser_errors_should_be_caught_and_beautified(self):
program = """option is ask Rock Paper or Scissors?
print 'Player 2 ' option
if option is Scissors
print 'Its a tie!'"""

with self.assertRaises(Exception) as context:
result = hedy.transpile(program, 4)
self.assertEqual('Parse', str(context.exception))




class TestsLevel5(unittest.TestCase):
#print should still work
def test_print_with_var(self):
Expand Down

0 comments on commit 9610500

Please sign in to comment.