Permalink
Browse files

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

…nctions.
  • Loading branch information...
1 parent 709ddfa commit eef4b3b85c71635554beff59f9ba045a91568553 @jonashaag jonashaag committed Jun 13, 2010
Showing with 222 additions and 79 deletions.
  1. +51 −52 nodes.py
  2. +35 −0 operators.py
  3. +41 −27 parser.py
  4. BIN tests/d_parser_mach_gen.g.d_parser.dat
  5. +1 −0 tests/d_parser_mach_gen.g.md5
  6. +46 −0 tests/test.py
  7. +48 −0 tests/test_function.py
View
103 nodes.py
@@ -1,33 +1,41 @@
+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
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
@@ -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
@@ -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
-
-#""")
Binary file not shown.
@@ -0,0 +1 @@
+��&1�)V�k��=�
View
@@ -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
@@ -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()

0 comments on commit eef4b3b

Please sign in to comment.