summaryrefslogtreecommitdiffstats
path: root/librelogo/source/LibreLogo/LibreLogo.py
diff options
context:
space:
mode:
Diffstat (limited to 'librelogo/source/LibreLogo/LibreLogo.py')
-rw-r--r--librelogo/source/LibreLogo/LibreLogo.py33
1 files changed, 21 insertions, 12 deletions
diff --git a/librelogo/source/LibreLogo/LibreLogo.py b/librelogo/source/LibreLogo/LibreLogo.py
index 93c51d636312..06ccca3a6377 100644
--- a/librelogo/source/LibreLogo/LibreLogo.py
+++ b/librelogo/source/LibreLogo/LibreLogo.py
@@ -1874,9 +1874,6 @@ def __compil__(s):
globs = ""
functions = ["range", "__int__", "__float__", "Random", "Input", "__string__", "len", "round", "abs", "sin", "cos", "sqrt", "log10", "set", "list", "tuple", "re.sub", "re.search", "re.findall", "sorted", "min", "max"]
defaultfunc = ["Print"] # TODO handle all default procedures
- names ={key: 1 for key in functions + defaultfunc}
- names["range"] = names["re.sub"] = 3
- names["re.search"] = names["re.findall"] = 2
if len(subnames) > 0:
globs = "global %s" % ", ".join(subnames)
@@ -1909,17 +1906,29 @@ def __compil__(s):
operators = re.compile(r"(?iu)(%s)" % "(?:[ ]*([+*/<>]|//|==|<=|>=|<>|!=)[ ]*|[ ]*-[ ]+|(?<! )-[ ]*|[ ]*[*][*][ ]*)") # operators, eg. " - ", "-", "- "
atoms = re.compile(r"(?iu)(%s)" % "[0-9]+([.,][0-9]+)?|\w+([.]\w)?")
+ # store argument numbers of all subroutines in dictionary "names"
+ names = {key: 1 for key in functions + defaultfunc}
+ names["range"] = names["re.sub"] = 3
+ names["re.search"] = names["re.findall"] = 2
+
+ # match a function header
+ search_funcdef = re.compile(r"(^|\n) *(def (\w+))(\([^\n]*\):) *(?=\n)")
+
+ # "multiline" lambda function to process function headers: add commas to argument list and
+ # add {"subroutine_name": argument_count} into names using a temporary array
+ # (instead of using global variable "names" and a new global function to process the matching patterns)
+ # for example: "def f(x y z):" -> "def f(x,y,z):" and names = {"f": 3}
+ process_funcdef = lambda r: r.group(1) + r.group(2) + \
+ [chsp.sub(", ", r.group(4)), names.update({r.group(3): len(re.findall(r"\w+", r.group(4)))})][0]
+ # process all function headers calling process_funcdef for every matching
+ # (before parsing Logo expressions line by line, we need to know about all functions,
+ # because functions can be defined in any order, ie. their calls can be before
+ # their definitions)
+ s = search_funcdef.sub(process_funcdef, s)
+
+ # process line by line
for i in s.split("\n"):
i = i.strip()
- # store argument numbers of subroutines in names
- if i[0:4] == 'def ':
- s = func.search(i)
- if s.group(3) == '():':
- names[s.group(2)] = 0
- else:
- s2 = len(chsp.findall(s.group(3))) + 1
- i = s.group(1) + chsp.sub(", ", s.group(3))
- names[s.group(2)] = s2
# convert Logo expressions to Python ones using regex based tokenization
# tokens: {startpos: endpos} dictionaries for subroutine names, operators and other tokens