Skip to content

Instantly share code, notes, and snippets.

@WorryingWonton
Created June 4, 2018 07:12
Show Gist options
  • Select an option

  • Save WorryingWonton/67a9eafd754799dbf181e46c5fc70798 to your computer and use it in GitHub Desktop.

Select an option

Save WorryingWonton/67a9eafd754799dbf181e46c5fc70798 to your computer and use it in GitHub Desktop.
Tuple work-around for parse error caused by multiple inputs to a function in Java
#See the terminal symbol 'arg_list' in cbat_grammar
#I noticed that functions on CodingBat were always in the form 'function_name' '(' 'arg' (',' 'whitespace_token'? arg)* ')'
#My grammar originally didn't have a way to deal with this.
#It could deal with multiple arguments in an array or map, but multiple-
#comma separated arguments not in a container literal would cause Lark to fail.
#To get around this, I figured I could treate the parentheses around the function arguments as a tuple, so... that's what I've done.
#Thus far it seems to work, though it feels inelegant.
from lark import Transformer, Lark
cbat_grammar = """
?literal : string
| char
| array
| map
| int
| float
| boolean
| arg_list
array : "[" [literal ("," literal)*] "]"
map : "{" [kv_pair ("," kv_pair)*] "}"
kv_pair : literal ":" literal
string : ESCAPED_STRING
char : /'.'/
float : /-?[0-9]+.[0-9]*/
int : /-?[0-9]+/
boolean : /true|false/
arg_list : "(" [literal ("," literal)*] ")"
%import common.ESCAPED_STRING
%import common.WS
%ignore WS
"""
class ASTElement():
pass
class AtomicLiteral(ASTElement):
def __init__(self, scalar):
self.scalar = scalar
def to_rust_code(self):
return f'{self.scalar}'
class ArrayLiteral(ASTElement):
def __init__(self, arrayx):
self.arrayx = arrayx
self.item_type = None
def to_rust_code(self):
if len(self.arrayx) > 0:
string = 'vec!['
count = 0
for elem in self.arrayx:
if count < len(self.arrayx) - 1:
string += elem.to_rust_code() + ', '
count += 1
else:
string += elem.to_rust_code()
return string + ']'
else:
return f'Vec::<{self.item_type}>::new()'
class ArgList(ASTElement):
def __init__(self, args):
self.args = args
def to_rust_code(self):
string = ''
count = 0
for elem in self.args:
if count < len(self.args) - 1:
string += elem.to_rust_code() + ', '
count += 1
else:
string += elem.to_rust_code()
return string
class MapLiteral(ASTElement):
def __init__(self, mapx):
self.mapx = mapx
def to_rust_code(self):
string = '{let mut m = BTreeMap::new();\n'
for kv_pair in self.mapx:
string += f'm.insert({kv_pair[0].to_rust_code()}, {kv_pair[1].to_rust_code()});\n'
string += '}'
return string
class JTransformer(Transformer):
def int(self, int):
return AtomicLiteral(int[0].value)
def float(self, float):
return AtomicLiteral(float[0].value)
def boolean(self, boolean):
return AtomicLiteral(boolean[0].value)
def char(self, char):
return AtomicLiteral(char[0].value)
def string(self, string):
return AtomicLiteral(string[0].value)
def array(self, items):
return ArrayLiteral(items)
def map(self, items):
return MapLiteral([item.children for item in items])
def arg_list(self, items):
return ArgList(items)
# parser = Lark(cbat_grammar, start='literal')
# stuff = JTransformer().transform(parser.parse("[1, [2, [3], {3: [2, 2, 2], 5: 1}], true, false, \"Hello\", 'a', 1.2, 2.2222312312321]"))
# print(stuff.to_rust_code())
#
# stuff2 = JTransformer().transform(parser.parse("([1, 2], [1, 2])"))
# print(stuff2)
# print(stuff2.to_rust_code())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment