Skip to content

Commit

Permalink
escape_and_scoping (#18)
Browse files Browse the repository at this point in the history
* Change scoping to include all scopes above current one

* Implement escaping

* Updated docs
  • Loading branch information
Ahhhhmed committed Apr 17, 2018
1 parent ad7f7a9 commit 0b30725
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 5 deletions.
8 changes: 7 additions & 1 deletion docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ The :code:`while` is not a part of :code:`for` snippet.
Parser creates an implicit :code:`block` snippet at the beginning.
:code:`block` snippet is implemented as a list of sub-snippets in new lines.

Escape sequence
"""""""""""""""

Homotopy uses escape sequence to enable operator usage in snippets.
Character after :code:`\` will always be a part of snippet and not recognised as an operator.
Syntax tree
^^^^^^^^^^^
Expand Down Expand Up @@ -290,7 +296,7 @@ Accessing outer parameters can be done in the following way:
]
The snippet above would create a public empty constructor. :code:`{{?###}}` binds to the same value as :code:`{{?###}}`
from the snippet above the current one. Note that only on level above can be accessed.
from the snippet above the current one.

Utilities
^^^^^^^^^
Expand Down
10 changes: 7 additions & 3 deletions homotopy/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,11 @@ def __getitem__(self, item):
:param item: Variable name
:return: Variable value if it exists. Empty string otherwise
"""
if len(self.stack) < 2 or item not in self.stack[-2]:
return ""
i = 2
while i <= len(self.stack):
if item in self.stack[-i]:
return self.stack[-i][item]

return self.stack[-2][item]
i += 1

return ""
11 changes: 11 additions & 0 deletions homotopy/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Parser:
in_operator = '>'
out_operator = '<'
and_operator = '&'
escape_character = '\\'

@staticmethod
def parse(snippet_text):
Expand All @@ -21,8 +22,18 @@ def parse(snippet_text):
stack = []
current_match = []
last_operator = Parser.in_operator
in_escape_sequence = False

for c in snippet_text + "\0":
if in_escape_sequence and c != "\0":
current_match.append(c)
in_escape_sequence = False
continue

if c == Parser.escape_character:
in_escape_sequence = True
continue

if c in Parser.parameter_chars or c in ["\0", Parser.in_operator, Parser.out_operator, Parser.and_operator]:
if last_operator == Parser.in_operator:
stack.append(SimpleSnippet("".join(current_match)))
Expand Down
2 changes: 1 addition & 1 deletion test/testCompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def test_compile(self, mock_provider):
'>',
st.SimpleSnippet('inner')
))),
'param: test, inside: test in: in: >>>'
'param: test, inside: test in: test in: >>>'
)


Expand Down
19 changes: 19 additions & 0 deletions test/testParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,22 @@ def test_into(self):
'>',
SimpleSnippet('if')
))

def test_escape(self):
self.assertEqual(parser.parse(r"i\>4"), SimpleSnippet("i>4"))
self.assertEqual(parser.parse("ignore\\"), SimpleSnippet("ignore"))

self.assertEqual(parser.parse(r"i\\>4"),
CompositeSnippet(
SimpleSnippet("i\\"),
'>',
SimpleSnippet("4")
)
)

self.assertEqual(parser.parse(r"if$i\>4"),
CompositeSnippet(
SimpleSnippet("if"),
'$',
SimpleSnippet("i>4")
))

0 comments on commit 0b30725

Please sign in to comment.