diff options
author | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-10-09 19:08:08 +0400 |
---|---|---|
committer | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-10-09 19:08:08 +0400 |
commit | c25101f03aced0408ec9e5d5b8f3c1b0bad91a29 (patch) | |
tree | c857a5f8f79e1fb4198807a992171328f19b74ad | |
parent | 408b85900ac1c84c3224f478da8f290c92ca328a (diff) |
Grammar extended to accommodate do notation.
-rw-r--r-- | src/pclc/parser/component.py | 53 | ||||
-rw-r--r-- | src/pclc/parser/expressions.py | 5 | ||||
-rw-r--r-- | src/pclc/parser/import_spec.py | 2 | ||||
-rw-r--r-- | src/pclc/parser/mappings.py | 13 | ||||
-rw-r--r-- | src/pclc/parser/pcl_lexer.py | 7 | ||||
-rw-r--r-- | src/pclc/parser/pcl_parser.py | 120 | ||||
-rw-r--r-- | src/pclc/visitors/first_pass_resolver_visitor.py | 3 |
7 files changed, 185 insertions, 18 deletions
diff --git a/src/pclc/parser/component.py b/src/pclc/parser/component.py index 229367b..b4ad6f3 100644 --- a/src/pclc/parser/component.py +++ b/src/pclc/parser/component.py @@ -27,7 +27,8 @@ class Component(Entity): outputs, configuration, declarations, - definition): + definition, + is_leaf): Entity.__init__(self, filename, lineno) self.identifier = identifier self.inputs = inputs @@ -35,6 +36,54 @@ class Component(Entity): self.configuration = configuration self.declarations = declarations self.definition = definition + self.is_leaf = is_leaf + + @staticmethod + def getLeafComponent(filename, + lineno, + identifier, + inputs, + outputs, + configuration, + do_commands): + class LeafDefinition(Entity): + def __init__(self): + self.filename = filename + self.lineno = do_commands[0].lineno + self.do_commands = do_commands + + def accept(self, visitor): + for cmd in self.do_commands: + cmd.accept(visitor) + + return Component(filename, + lineno, + identifier, + inputs, + outputs, + configuration, + list(), + LeafDefinition(), + True) + + @staticmethod + def getNodeComponent(filename, + lineno, + identifier, + inputs, + outputs, + configuration, + declarations, + definition): + return Component(filename, + lineno, + identifier, + inputs, + outputs, + configuration, + declarations, + definition, + False) def accept(self, visitor): visitor.visit(self) @@ -47,7 +96,7 @@ class Component(Entity): def __repr__(self): return "<Component:\n\tname = %s,\n\tinputs = %s,\n\toutputs = %s," \ - "\n\tconfiguration = %s,\n\tdeclarations = %s\n\tdefinition = %s" \ + "\n\tconfiguration = %s,\n\tdeclarations = %s,\n\tdefinition = %s," \ "\n\tentity = %s>" % \ (self.identifier.__repr__(), self.inputs.__repr__(), self.outputs.__repr__(), self.configuration.__repr__(), diff --git a/src/pclc/parser/expressions.py b/src/pclc/parser/expressions.py index bc430cd..b12411d 100644 --- a/src/pclc/parser/expressions.py +++ b/src/pclc/parser/expressions.py @@ -74,10 +74,13 @@ class StateIdentifier(Identifier): def __init__(self, filename, lineno, identifier): Identifier.__init__(self, filename, lineno, identifier) + def __str__(self): + return "@%s" % super(StateIdentifier, self).__str__() + def __repr__(self): return "<StateIdentifier: identifier = %s, entity = %s>" % \ (self.identifier.__repr__(), - super(Identifier, self).__repr__()) + super(StateIdentifier, self).__repr__()) class Expression(Entity): def __init__(self, filename, lineno, parent_expr = None): diff --git a/src/pclc/parser/import_spec.py b/src/pclc/parser/import_spec.py index a785cf8..328480e 100644 --- a/src/pclc/parser/import_spec.py +++ b/src/pclc/parser/import_spec.py @@ -25,7 +25,7 @@ class Import(Entity): self.alias = alias def __str__(self): - return self.module_name + return str(self.module_name) def __repr__(self): return "<ImportSpec: module = [%s], alias = [%s], entity = %s>" % \ diff --git a/src/pclc/parser/mappings.py b/src/pclc/parser/mappings.py index e8e85e8..5094ace 100644 --- a/src/pclc/parser/mappings.py +++ b/src/pclc/parser/mappings.py @@ -73,3 +73,16 @@ class LiteralMapping(Entity): (self.literal.__repr__(), self.to.__repr__(), super(LiteralMapping, self).__repr__()) + +class ReturnMapping(Mapping): + def __init__(self, filename, lineno, from_, to_identifier): + Mapping.__init__(self, filename, lineno, from_, to_identifier) + + def __str__(self): + return "%s <- %s" % (self.to, self.from_) + + def __repr__(self): + return "<ReturnMapping: from = %s,\n\tto = %s\n\tentity = %s>" % \ + (self.from_.__repr__(), + self.to.__repr__(), + super(ReturnMapping, self).__repr__()) diff --git a/src/pclc/parser/pcl_lexer.py b/src/pclc/parser/pcl_lexer.py index 9e36dc0..5a1563b 100644 --- a/src/pclc/parser/pcl_lexer.py +++ b/src/pclc/parser/pcl_lexer.py @@ -33,6 +33,9 @@ reserved = { 'component' : 'COMPONENT', 'configuration' : 'CONFIGURATION', 'declare' : 'DECLARE', + 'do' : 'DO', + 'endif' : 'ENDIF', + 'else' : 'ELSE', 'first' : 'FIRST', 'import' : 'IMPORT', 'if' : 'IF', @@ -43,8 +46,10 @@ reserved = { 'or' : 'OR', 'output' : 'OUTPUTS', 'outputs' : 'OUTPUTS', + 'return' : 'RETURN', 'second' : 'SECOND', 'split' : 'SPLIT', + 'then' : 'THEN', 'top' : 'TOP', 'wire' : 'WIRE', 'with' : 'WITH', @@ -58,6 +63,7 @@ tokens = [ 'EQUALS', 'NOT_EQUALS', 'GT', 'LT', 'G_EQUAL', 'L_EQUAL', + 'LEFT_ARROW', 'QUALIFIED_IDENTIFIER', 'IDENTIFIER', 'COMPOSITION', 'FLOAT', @@ -81,6 +87,7 @@ class PCLLexer(object): t_LT = r'<' t_G_EQUAL = r'>=' t_L_EQUAL = r'<=' + t_LEFT_ARROW = r'<-' t_COMPOSITION = r'>>>' t_MAPS_TO = r'->' t_PARALLEL_WITH_TUPLE = r'\*\*\*' diff --git a/src/pclc/parser/pcl_parser.py b/src/pclc/parser/pcl_parser.py index 8750dc3..d874891 100644 --- a/src/pclc/parser/pcl_parser.py +++ b/src/pclc/parser/pcl_parser.py @@ -26,6 +26,7 @@ from pcl_lexer import tokens, PCLLexer from import_spec import Import from component import Component from declaration import Declaration +from command import Command, Function, Return, IfCommand from conditional_expressions import AndConditionalExpression, \ OrConditionalExpression, \ XorConditionalExpression, \ @@ -55,7 +56,8 @@ from expressions import Literal, \ from mappings import Mapping, \ TopMapping, \ BottomMapping, \ - LiteralMapping + LiteralMapping, \ + ReturnMapping from module import Module @@ -95,15 +97,27 @@ def p_import_spec(p): Identifier(p.parser.filename, p.lineno(4), p[4])) def p_component_definition(p): - '''component_definition : COMPONENT IDENTIFIER INPUTS scalar_or_tuple_identifier_comma_list OUTPUTS scalar_or_tuple_identifier_comma_list opt_configuration opt_declarations AS component_body_expression''' - p[0] = Component(p.parser.filename, - p.lineno(1), - Identifier(p.parser.filename, p.lineno(2), p[2]), - p[4], - p[6], - p[7], - p[8], - p[10]) + '''component_definition : COMPONENT IDENTIFIER INPUTS scalar_or_tuple_identifier_comma_list OUTPUTS scalar_or_tuple_identifier_comma_list opt_configuration opt_declarations AS arrow_expression + | COMPONENT IDENTIFIER INPUTS scalar_or_tuple_identifier_comma_list OUTPUTS scalar_or_tuple_identifier_comma_list opt_configuration DO do_command_list''' + lineno = p.lineno(1) + identifier = Identifier(p.parser.filename, p.lineno(2), p[2]) + if len(p) > 10: + p[0] = Component.getNodeComponent(p.parser.filename, + lineno, + identifier, + p[4], + p[6], + p[7], + p[8], + p[10]) + else: + p[0] = Component.getLeafComponent(p.parser.filename, + lineno, + identifier, + p[4], + p[6], + p[7], + p[9]) def p_opt_configuration(p): '''opt_configuration : CONFIGURATION identifier_comma_list @@ -155,9 +169,13 @@ def p_mapping(p): '''mapping : identifier_or_literal MAPS_TO identifier_or_qual_identifier''' p[0] = Mapping(p.parser.filename, p[1].lineno, p[1], p[3]) -def p_component_body(p): - '''component_body_expression : arrow_expression''' - p[0] = p[1] +##def p_body_expression_or_do_notation(p): +## '''body_expression_or_do_notation : opt_declarations AS arrow_expression +## | DO do_command_list''' +## if len(p) > 2: +## p[0] = [p[1], p[2]] +## else: +## p[0] = p[2] def p_arrow_expression(p): '''arrow_expression : composition_expression''' @@ -356,6 +374,77 @@ def p_unary_conditional_expression(p): else: p[0] = TerminalConditionalExpression(p[1]) +def p_do_command_list(p): + '''do_command_list : do_command do_command_list + | do_command''' + if len(p) > 2: + p[0] = [p[1]] + p[2] + else: + p[0] = [p[1]] + +def p_do_command(p): + '''do_command : identifier_or_qual_identifier LEFT_ARROW function + | function + | RETURN return_mappings + | IF conditional_expression THEN do_command_list ELSE do_command_list ENDIF''' + if len(p) > 4: + p[0] = IfCommand(p.parser.filename, p.lineno(1), p[2], p[4], p[6]) + elif len(p) > 3: + p[0] = Command(p.parser.filename, p[1].lineno, p[1], p[3]) + elif len(p) > 2: + p[0] = Return(p.parser.filename, p.lineno(1), p[2]) + else: + p[0] = Command(p.parser.filename, p[1].lineno, None, p[1]) + +def p_function(p): + '''function : identifier_or_qual_identifier '(' opt_function_args ')' ''' + p[0] = Function(p.parser.filename, p[1].lineno, p[1], p[3]) + +def p_opt_function_args(p): + '''opt_function_args : function_arg_list + | ''' + if len(p) > 0: + p[0] = p[1] + else: + p[0] = list() + +def p_function_arg_list(p): + '''function_arg_list : function_arg ',' function_arg_list + | function_arg''' + if len(p) > 2: + p[0] = [p[1]] + p[3] + else: + p[0] = [p[1]] + +def p_function_arg(p): + '''function_arg : identifier_or_literal + | state_identifier''' + p[0] = p[1] + +def p_return_mappings(p): + '''return_mappings : return_mapping_list + | '(' ')' ''' + if len(p) > 1: + p[0] = list() + else: + p[0] = p[1] + +def p_return_mapping_list(p): + '''return_mapping_list : return_mapping ',' return_mapping_list + | return_mapping''' + if len(p) > 2: + p[0] = [p[1]] + p[3] + else: + p[0] = [p[1]] + +def p_return_mapping(p): + '''return_mapping : identifier_or_qual_identifier LEFT_ARROW identifier_or_literal + | identifier_or_qual_identifier LEFT_ARROW state_identifier''' + p[0] = ReturnMapping(p.parser.filename, + p[1].lineno, + p[3], + p[1]) + def p_scalar_or_tuple_identifier_comma_list(p): '''scalar_or_tuple_identifier_comma_list : '(' identifier_comma_list ')' ',' '(' identifier_comma_list ')' | identifier_comma_list''' @@ -398,7 +487,10 @@ recovery_tokens = (')', 'PARALLEL_WITH_TUPLE', 'PARALLEL_WITH_SCALAR', 'AS', - 'DECLARE') + 'DECLARE', + 'DO', + 'IF', + 'RETURN') def p_error(token): if not token: diff --git a/src/pclc/visitors/first_pass_resolver_visitor.py b/src/pclc/visitors/first_pass_resolver_visitor.py index e7b1f3a..9ecbe24 100644 --- a/src/pclc/visitors/first_pass_resolver_visitor.py +++ b/src/pclc/visitors/first_pass_resolver_visitor.py @@ -122,6 +122,7 @@ class FirstPassResolverVisitor(ResolverVisitor): python_module_interface = [] if declarations: + print "\n".join(map(lambda d: str(d), declarations)) for decl in declarations: # Count occurrences of declaration identifiers try: @@ -305,6 +306,8 @@ class FirstPassResolverVisitor(ResolverVisitor): # Mark the import as not used for now ;) self._module.resolution_symbols['used_imports'][an_import.alias] = (an_import, False) + print self._errors + @multimethod(Component) def visit(self, component): # Component name *must* be the same as the file name |