Skip to content

Commit

Permalink
FIX: Resolve parsing issue where functions were not correctly identif…
Browse files Browse the repository at this point in the history
…ied and word prefixes were interpreted as Python keywords (#14)
  • Loading branch information
jfcarter2358 committed May 26, 2023
1 parent bfe59e2 commit 321cb95
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 9 deletions.
2 changes: 1 addition & 1 deletion calligraphy_scripting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

from calligraphy_scripting import runner

__version__ = "1.1.3"
__version__ = "1.1.4"
107 changes: 101 additions & 6 deletions calligraphy_scripting/parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pylint: disable=C0301, R1702, R0912, R0914, R0915, W1401
# pylint: disable=C0301, R1702, R0912, R0914, R0915, W1401, C0206
"""Module to parse Calligraphy scripts into token representation"""

from __future__ import annotations
Expand Down Expand Up @@ -233,7 +233,7 @@ def determine_language(
assignment_pattern = r"^[ \t]*\(?((?:[a-zA-Z0-9_]+\s*,?\s*)+)\)?[ \t]$"

lines = [line for line in code.split("\n") if len(line.strip()) > 0]
variables = ["env.", "shellopts."]
variables = ["env", "shellopts"]
langs = []
imports = get_imports(code)
functions = get_functions(code)
Expand All @@ -244,20 +244,22 @@ def determine_language(
if stripped.startswith("#") or stripped.startswith('"""'):
langs.append("COMMENT")
continue

parts = get_parts(stripped)
for keyword in keywords:
if stripped.startswith(keyword):
if parts[0] == keyword:
is_python = True
break
for var in variables:
if stripped.startswith(var):
if parts[0] == var:
is_python = True
break
for imp in imports:
if stripped.startswith(imp):
if parts[0] == imp:
is_python = True
break
for func in functions:
if stripped.startswith(func):
if parts[0] == func:
is_python = True
break
if not is_python:
Expand Down Expand Up @@ -393,3 +395,96 @@ def handle_line_breaks(code: str) -> str:
output += token
char_idx += 1
return output, inline_indices


def get_in_depths(ignore: str, depths: dict) -> bool:
"""Determine if all depths other than ignore key are 0
Args:
ignore (str): Key to not check for depth
depths (dict): Depths dictionary to check
Returns:
bool: Are all other depths 0
"""

for key in depths:
if key == ignore:
continue
if depths[key] > 0:
return True
return False


def get_parts(line: str) -> list[str]:
"""Get parts of line broken by spaces and special characters
Args:
line (str): Line of code to split
Returns:
list[str]: List of split out tokens
"""

output = []
buffer = ""
depths = {
"double_quote": 0,
"single_quote": 0,
"colon": 0,
"paren": 0,
"brace": 0,
"bracket": 0,
}
chars = {
"double_quote": {"char": '"'},
"single_quote": {"char": "'"},
"colon": {"char": ":"},
"paren": {"start": "(", "end": ")"},
"brace": {"start": "{", "end": "}"},
"bracket": {"start": "[", "end": "]"},
}

look_behind = ""
for idx, token in enumerate(line):
if idx > 0:
look_behind = line[idx - 1]
if token in [" ", "."]:
if buffer != "":
output.append(buffer)
buffer = ""
continue
special = False
for key in depths:
if not get_in_depths(key, depths):
if key in ["double_quote", "single_quote", "colon"]:
if token == chars[key]["char"] and look_behind != "\\":
if not key in ["colon"]:
buffer += token
if depths[key] == 0:
depths[key] += 1
else:
depths[key] -= 1
output.append(buffer)
buffer = ""
special = True
else:
if token == chars[key]["start"]:
if depths[key] == 0:
output.append(buffer)
buffer = ""
depths[key] += 1
buffer += chars[key]["start"]
special = True
elif token == chars[key]["end"]:
depths[key] -= 1
buffer += chars[key]["end"]
if depths[key] == 0:
output.append(buffer)
buffer = ""
special = True
if not special:
buffer += token
if buffer != "":
output.append(buffer)
return output
1 change: 1 addition & 0 deletions calligraphy_scripting/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,5 @@ def transpile(lines: list[str], langs: list[str], inline_indices: list[str]) ->
output += f'{line[:inline_idx[1]]}shell("{base64_cmd}", get_stdout=True, silent={raw[0]=="?"}, format_dict={{**globals(), **locals()}}){line[inline_idx[2]:]}\n'

output = output.replace("<CALLIGRAPHY_NEWLINE>", "\n")

return output
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "calligraphy-scripting"
version = "1.1.3"
version = "1.1.4"
description = "A hybrid language for a modern approach to shell scripting"
authors = ["John Carter <jfcarter2358@gmail.com>"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion tests/data/cli.version.out
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Calligraphy: 1.1.3
Calligraphy: 1.1.4

0 comments on commit 321cb95

Please sign in to comment.