Permalink
Browse files

Add get/set properties support.

  • Loading branch information...
1 parent e5acfc3 commit 13fdfa9b6f6adac5a1d531a9eb28f868827ac9f8 @rspivak committed May 17, 2012
View
@@ -147,6 +147,25 @@ def __init__(self, op, left, right):
def children(self):
return [self.left, self.right]
+class GetPropAssign(Node):
+ def __init__(self, prop_name, elements):
+ """elements - function body"""
+ self.prop_name = prop_name
+ self.elements = elements
+
+ def children(self):
+ return [self.prop_name] + self.elements
+
+class SetPropAssign(Node):
+ def __init__(self, prop_name, parameters, elements):
+ """elements - function body"""
+ self.prop_name = prop_name
+ self.parameters = parameters
+ self.elements = elements
+
+ def children(self):
+ return [self.prop_name] + self.parameters + self.elements
+
class VarStatement(Node):
pass
View
@@ -241,6 +241,9 @@ def next(self):
# Terminal types
'NUMBER', 'STRING', 'ID', 'REGEX',
+ # Properties
+ 'GETPROP', 'SETPROP',
+
# Comments
'LINE_COMMENT', 'BLOCK_COMMENT',
@@ -411,6 +414,16 @@ def t_STRING(self, token):
)
identifier = identifier_start + identifier_part
+ getprop = r'get' + r'(?=\s' + identifier + r')'
+ @ply.lex.TOKEN(getprop)
+ def t_GETPROP(self, token):
+ return token
+
+ setprop = r'set' + r'(?=\s' + identifier + r')'
+ @ply.lex.TOKEN(setprop)
+ def t_SETPROP(self, token):
+ return token
+
@ply.lex.TOKEN(identifier)
def t_ID(self, token):
token.type = self.keywords_dict.get(token.value, 'ID')
View
Oops, something went wrong.
View
@@ -308,9 +308,19 @@ def p_property_list(self, p):
# XXX: GET / SET
def p_property_assignment(self, p):
- """property_assignment : property_name COLON assignment_expr"""
+ """property_assignment \
+ : property_name COLON assignment_expr
+ | GETPROP property_name LPAREN RPAREN LBRACE function_body RBRACE
+ | SETPROP property_name LPAREN formal_parameter_list RPAREN \
+ LBRACE function_body RBRACE
+ """
if len(p) == 4:
p[0] = ast.Assign(left=p[1], op=p[2], right=p[3])
+ elif len(p) == 8:
+ p[0] = ast.GetPropAssign(prop_name=p[2], elements=p[6])
+ else:
+ p[0] = ast.SetPropAssign(
+ prop_name=p[2], parameters=p[4], elements=p[7])
def p_property_name(self, p):
"""property_name : identifier
@@ -431,7 +431,21 @@ def setUp(self):
for (o(); i < 3; i++) {
}
+ """,
+
+ # https://github.com/rspivak/slimit/issues/32
"""
+ Name.prototype = {
+ get fullName() {
+ return this.first + " " + this.last;
+ },
+ set fullName(name) {
+ var names = name.split(" ");
+ this.first = names[0];
+ this.last = names[1];
+ }
+ };
+ """,
]
def make_test_function(input, expected):
@@ -379,6 +379,31 @@ def assertMinified(self, source, expected):
# function call in FOR init
('for(o(); i < 3; i++) {}', 'for(o();i<3;i++){}'),
+
+ # https://github.com/rspivak/slimit/issues/32
+ ("""
+ Name.prototype = {
+ getPageProp: function Page_getPageProp(key) {
+ return this.pageDict.get(key);
+ },
+
+ get fullName() {
+ return this.first + " " + this.last;
+ },
+
+ set fullName(name) {
+ var names = name.split(" ");
+ this.first = names[0];
+ this.last = names[1];
+ }
+ };
+ """,
+ ('Name.prototype={getPageProp:function Page_getPageProp(key){'
+ 'return this.pageDict.get(key);},'
+ 'get fullName(){return this.first+" "+this.last;},'
+ 'set fullName(name){var names=name.split(" ");this.first=names[0];'
+ 'this.last=names[1];}};')
+ ),
]
@@ -1,6 +1,6 @@
###############################################################################
#
-# Copyright (c) 2011 Ruslan Spivak
+# Copyright (c) 2011-2012 Ruslan Spivak
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -78,6 +78,36 @@ def visit_Assign(self, node):
return template % (
self.visit(node.left), node.op, self.visit(node.right))
+ def visit_GetPropAssign(self, node):
+ template = 'get %s() {\n%s\n%s}'
+ if getattr(node, '_parens', False):
+ template = '(%s)' % template
+ self.indent_level += 2
+ body = '\n'.join(
+ (self._make_indent() + self.visit(el))
+ for el in node.elements
+ )
+ self.indent_level -= 2
+ tail = self._make_indent()
+ return template % (self.visit(node.prop_name), body, tail)
+
+ def visit_SetPropAssign(self, node):
+ template = 'set %s(%s) {\n%s\n%s}'
+ if getattr(node, '_parens', False):
+ template = '(%s)' % template
+ if len(node.parameters) > 1:
+ raise SyntaxError(
+ 'Setter functions must have one argument: %s' % node)
+ params = ','.join(self.visit(param) for param in node.parameters)
+ self.indent_level += 2
+ body = '\n'.join(
+ (self._make_indent() + self.visit(el))
+ for el in node.elements
+ )
+ self.indent_level -= 2
+ tail = self._make_indent()
+ return template % (self.visit(node.prop_name), params, body, tail)
+
def visit_Number(self, node):
return node.value
@@ -79,6 +79,28 @@ def visit_Assign(self, node):
return template % (
self.visit(node.left), node.op, self.visit(node.right))
+ def visit_GetPropAssign(self, node):
+ template = 'get %s(){%s}'
+ if getattr(node, '_parens', False):
+ template = '(%s)' % template
+ return template % (
+ self.visit(node.prop_name),
+ ''.join(self.visit(element) for element in node.elements)
+ )
+
+ def visit_SetPropAssign(self, node):
+ template = 'set %s(%s){%s}'
+ if getattr(node, '_parens', False):
+ template = '(%s)' % template
+ if len(node.parameters) > 1:
+ raise SyntaxError(
+ 'Setter functions must have one argument: %s' % node)
+ return template % (
+ self.visit(node.prop_name),
+ ''.join(self.visit(param) for param in node.parameters),
+ ''.join(self.visit(element) for element in node.elements)
+ )
+
def visit_Number(self, node):
return node.value
View
Oops, something went wrong.

2 comments on commit 13fdfa9

@fdev31
fdev31 commented on 13fdfa9 May 17, 2012

Works as expected ! Thanks :)

@rspivak
Owner

No problem. Thanks for filing the bug report.

Please sign in to comment.