Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Node refactoring, some work on if statements, started testcase for fu…

…nctions.
  • Loading branch information...
commit eef4b3b85c71635554beff59f9ba045a91568553 1 parent 709ddfa
@jonashaag jonashaag authored
View
103 nodes.py
@@ -1,5 +1,19 @@
+import pprint
+from gpyconf._internal.dicts import ordereddict
+
+
class Node(object):
- pass
+ eval_first = False
+
+ def __init__(self):
+ self.children = ordereddict()
+
+ def __repr__(self):
+ return '<%r \n{%s}>' % (
+ type(self).__name__,
+ pprint.pformat([(name, child) for name, child in
+ self.children.iteritems()])[1:-1]
+ )
class Expression(Node):
pass
@@ -7,27 +21,21 @@ class Expression(Node):
class Declaration(Expression):
def __init__(self, name, type):
Expression.__init__(self)
- self.name = name
- self.type = type
-
- def __repr__(self):
- return '<%s at 0x%x = %r as %r>' % (type(self).__name__, id(self), self.name, self.type)
+ self.children['name'] = name
+ self.children['type'] = type
class Identifier(Expression):
def __init__(self, name):
Expression.__init__(self)
- self.name = name
+ self.children['name'] = name
def __repr__(self):
- return '<%s at 0x%x = %r>' % (type(self).__name__, id(self), self.name)
+ return '`%s`' % repr(self.children['name'])[1:-1]
class Literal(Expression):
def __init__(self, value):
Expression.__init__(self)
- self.value = value
-
- def __repr__(self):
- return '<%s at 0x%x = %r>' % (type(self).__name__, id(self), self.value)
+ self.children['value'] = value
class String(Literal):
pass
@@ -38,74 +46,65 @@ class Number(Literal):
class Assignment(Expression):
def __init__(self, name, value):
Expression.__init__(self)
- self.name = name
- self.value = value
-
- def __repr__(self):
- return '<%s at 0x%x = %r <- %r>' % (type(self).__name__, id(self), self.name, self.value)
+ self.children['name'] = name
+ self.children['value'] = value
class Definition(Node):
def __init__(self, decl, value):
Node.__init__(self)
- self.decl = decl
- self.value = value
-
- def __repr__(self):
- return '<%s at 0x%x = %r <- %r>' % (type(self).__name__, id(self), self.decl, self.value)
+ self.children['decl'] = decl
+ self.children['value'] = value
class Block(Node):
def __init__(self, statements):
Node.__init__(self)
- self.statements = statements
-
- def __repr__(self):
- return '<%s at 0x%x = %r>' % (type(self).__name__, id(self), self.statements)
+ self.children['statements'] = statements
class DeclarationBlock(Node):
def __init__(self, decls):
Node.__init__(self)
- self.decls = decls
-
- def __repr__(self):
- return '<%s at 0x%x = %r>' % (type(self).__name__, id(self), self.decls)
-
+ self.children['decls'] = decls
class Function(Expression):
def __init__(self, return_type, signature, block):
Expression.__init__(self)
- self.return_type = return_type
- self.signature = signature
- self.block = block
-
- def __repr__(self):
- return '<%s at 0x%x = %r(%r): %r>' % (type(self).__name__, id(self),
- self.return_type, self.signature, self.block)
+ self.children['return_type'] = return_type
+ self.children['signature'] = signature
+ self.children['block'] = block
class Call(Expression):
def __init__(self, name, argument_list):
Expression.__init__(self)
- self.name = name
- self.argument_list = argument_list
-
- def __repr__(self):
- return '<%s at 0x%x = %r(%r)>' % (type(self).__name__, id(self),
- self.name, self.argument_list)
+ self.children['name'] = name
+ self.children['argument_list'] = argument_list
class Return(Node):
def __init__(self, expr):
Node.__init__(self)
- self.expr = expr
-
- def __repr__(self):
- return '<%s at 0x%x = %r>' % (type(self).__name__, id(self), self.expr)
+ self.children['expr'] = expr
class ObjectTypeDeclaration(Node):
def __init__(self, name, decl_block):
Node.__init__(self)
- self.name = name
- self.decl_block = decl_block
+ self.children['name'] = name
+ self.children['decl_block'] = decl_block
- def __repr__(self):
- return '<%s at 0x%x = %r, %r>' % (type(self).__name__, id(self), self.name, self.decl_block)
+class If(Node):
+ def __init__(self, expr, block, else_block=None):
+ Node.__init__(self)
+ self.children['expr'] = expr
+ self.children['block'] = block
+ self.children['else_block'] = else_block
+class LogicalExpression(Node):
+ def __init__(self, nodes):
+ Node.__init__(self)
+ self.children['nodes'] = nodes
+ print "CHILDREN", nodes
+ def __repr__(self):
+ return ''.join((
+ ('(' if self.eval_first else ''),
+ ' '.join(repr(expr) for expr in self.children['nodes']),
+ (')' if self.eval_first else '')
+ ))
View
35 operators.py
@@ -0,0 +1,35 @@
+from itertools import count
+
+class _OP(object):
+ def __init__(self):
+ self._symbols = dict()
+
+ def __getattr__(self, symbol_):
+ symbol = self._symbols.get(symbol_)
+ if symbol is None:
+ self._symbols[symbol_] = symbol = self._make_symbol(symbol_)
+ return symbol
+
+ def _make_symbol(self, symbol):
+ class _symbol(object):
+ def __repr__(self):
+ return symbol
+ return _symbol()
+OP = _OP()
+
+OPERATORS = {
+ 'not' : OP.NOT,
+ 'or' : OP.OR,
+ 'and' : OP.AND,
+ 'is' : OP.EQUAL,
+ '<' : OP.SMALLER,
+ '>' : OP.BIGGER,
+ '<=' : OP.SMALLER_EQUAL,
+ '>=' : OP.BIGGER_EQUAL,
+ '&' : OP.BINARY_AND,
+ '|' : OP.BINARY_OR,
+ 'xor' : OP.XOR
+}
+
+def for_symbol(symbol):
+ return OPERATORS[symbol]
View
68 parser.py
@@ -1,6 +1,7 @@
from dparser import Parser
+from itertools import starmap
-import nodes, preprocessor
+import nodes, preprocessor, operators
def d_program(t):
''' program: stuff '''
@@ -17,6 +18,7 @@ def d_statement(t):
| definition
| return_statement
| type_declaration
+ | if_statemenet
'''
return t[0]
@@ -32,15 +34,48 @@ def d_assignment(t):
''' assignment: identifier '<-' expression '''
return nodes.Assignment(t[0], t[2])
+def d_if_statement(t):
+ ''' if_statemenet: 'if' expression ':' block ('else:' block)? '''
+ return nodes.If(t[1], t[3], t[4][0] if t[4] else None)
+
def d_expression(t):
- ''' expression: literal
- | identifier
- | assignment
- | function
- | call
+ ''' expression: '('? _expression ')'? '''
+ if len(t) == 1:
+ return t[0]
+ else:
+ expr = t[1]
+ expr.eval_first = True
+ return expr
+
+def d__expression(t):
+ ''' _expression: literal
+ | identifier
+ | assignment
+ | function
+ | call
+ | logical_expression
'''
return t[0]
+def d_logical_expression(t):
+ ''' logical_expression: expression (logical_operator expression)*
+ '''
+ return nodes.LogicalExpression(t)
+
+def d_logical_operator(t):
+ ''' logical_operator: 'is'
+ | 'and'
+ | 'or'
+ | '<'
+ | '>'
+ | '<='
+ | '>='
+ | '&'
+ | '|'
+ | 'xor'
+ '''
+ return operators.for_symbol(t[0])
+
def d_call(t):
'''
call: identifier '(' argument_list? ')'
@@ -107,24 +142,3 @@ def d_declaration_block(t):
def parse(s):
return Parser().parse(preprocessor.preprocess(s)).getStructure()
-
-from pprint import pprint
-pprint(parse('''
-a as Function <- String():
- 132
- "huhu"
- return huhu(1, 2, 3, fff)
-
-bubu <- a(3, "hallo")
-
-urgh as String <- vzvz(6336, String():
- 3544
-)
-
-Person <- Object:
- name as String
- age as Int'''))
-#print parser.parse("""String get_name(person as Person):
-# return person.name
-
-#""")
View
BIN  tests/d_parser_mach_gen.g.d_parser.dat
Binary file not shown
View
1  tests/d_parser_mach_gen.g.md5
@@ -0,0 +1 @@
+��&1�)V�k��=�
View
46 tests/test.py
@@ -0,0 +1,46 @@
+import unittest
+import pprint
+from itertools import izip
+
+from nodes import Node
+from parser import parse
+
+def is_same_ast(ast1, ast2):
+ if isinstance(ast1, Node):
+ if not isinstance(ast2, type(ast1)):
+ # not the same node types
+ return False
+ else:
+ return ast1.children == ast2.children
+ for ast1_item, ast2_item in izip(ast1, ast2):
+ if not is_same_ast(ast1_item, ast2_item):
+ return False
+ return True
+
+class Testcase(unittest.TestCase, object):
+ def setUp(self):
+ self.setup()
+
+ def setup(self):
+ pass
+
+ def assert_generates_ast(self, code, ast_):
+ def _prettyasts(_cache=[]):
+ if not _cache:
+ _cache.extend(map(pprint.pformat, (generated_ast, ast_)))
+ return _cache
+
+ generated_ast = self.parse(code)
+ self.assert_(
+ is_same_ast(generated_ast, ast_),
+ 'The parser generated\n\nbut you told me it should be\n\n'.join(_prettyasts())
+ )
+
+ def parse(self, code):
+ if code[0] == '\n':
+ code = code[1:]
+ lines = code.split('\n')
+ i = 0
+ while lines[0][i] == ' ':
+ i += 1
+ return parse('\n'.join(line[i:] for line in lines))
View
48 tests/test_function.py
@@ -0,0 +1,48 @@
+import unittest
+from test import Testcase
+
+from nodes import *
+from operators import OP
+
+_ = Identifier
+
+class FunctionTestcase(Testcase):
+ def test_definition(self):
+ self.assert_generates_ast('''
+ foo as Function <- String(a as Int, b as Float, c as Bool, d as Bool, e as Bool, f as Bool):
+ if c and e and (d or e) or f:
+ return a
+ else:
+ return b
+ ''',
+ [Definition(
+ Declaration(_('foo'), _('Function')),
+ Function(
+ _('String'),
+ [
+ Declaration(_('a'), _('Int')),
+ Declaration(_('b'), _('Float')),
+ Declaration(_('c'), _('Bool')),
+ Declaration(_('d'), _('Bool')),
+ Declaration(_('e'), _('Bool')),
+ Declaration(_('f'), _('Bool'))
+ ],
+ Block([
+ If(
+ LogicalExpression([
+ _('c'),
+ OP.AND,
+ LogicalExpression([_('d'), OP.OR, _('e')]),
+ OP.OR,
+ _('f')
+ ]),
+ Block([Return(_('a'))]),
+ Block([Return(_('b'))])
+ )
+ ])
+ )
+ )]
+ )
+
+if __name__ == '__main__':
+ unittest.main()
Please sign in to comment.
Something went wrong with that request. Please try again.