def parse_expression(self, scope): """Parse an expression. Expressions may contain other forms as well, a expression is the 'other' type of sentence. They must match a known of sentence in the scope. :param scope: The scope the expression is being parsed within. :return: A Sentence.""" token = next(self._token_stream) if isinstance(token, ValueToken): return Sentence([token]) elif not isinstance(token, FirstToken): raise ParseError('Cannot begin a sentence with \"' + repr(token) + '\"') elif 'Define' == token.text: self._token_stream.push_back(token) return self.parse_definition(scope) node = Sentence([token]) part_match = scope.new_matcher() if not part_match.next(token): self._token_stream.push_back(token) raise ParseError('Sentence not matched.', node) for token in self._token_stream: if isinstance(token, FirstToken): self._token_stream.push_back(token) if part_match.next(): node.append(self.parse_expression(scope)) elif node.ends_with_dot() and part_match.has_end(): return node else: raise ParseError('Sentence not matched.', node) elif isinstance(token, WordToken): if part_match.next(token): node.append(token) elif node.ends_with_dot() and part_match.has_end(): self._token_stream.push_back(token) return node else: raise ParseError('Sentence not matched.', node) elif isinstance(token, PeriodToken): if part_match.has_end(): node.append(token) return node else: raise ParseError('Sentence not matched.', node) elif isinstance(token, ValueToken): if part_match.next(): node.append(Sentence([token])) else: raise ParseError('Sentence not matched.', node) else: raise ValueError('Unknown Token Kind: {}'.format(type(token))) if isinstance(node[-1], Sentence) and part_match.has_end(): return node raise ParseError('Sentence not matched.', node)
def parse_definition(self, outer_scope): """Parse a definition from the incomming tokens. This is technically a kind of expression, but there are a few special rules that may force it to become seperate. This is temporary as it is just the fastest way I can get this to work. I hope. 'Define Function or variable name. to be Body. .'""" token = next(self._token_stream) if 'Define' != token.text: raise ParseError('Invalid start of definition: ' + str(token)) node = Sentence(token) ptr = outer_scope.new_matcher() if not ptr.next(token): self._token_stream.push_back(item) raise ParseError('Sentence not matched.', node) inner_scope = None for item in self._token_stream: if isinstance(item, FirstToken): self._token_stream.push_back(item) if ptr.next(): if inner_scope is None: signature = self.parse_signature() node.append(signature) inner_scope = outer_scope.new_define_scope(signature) else: node.append(self.parse_expression(inner_scope)) elif node.ends_with_dot() and ptr.has_end(): return node else: raise ParseError('Sentence not matched.', node) elif isinstance(item, WordToken): if ptr.next(item): node.append(item) elif node.ends_with_dot() and ptr.has_end(): self._token_stream.push_back(item) return node else: raise ParseError('Sentence not matched.', node) elif isinstance(item, PeriodToken): if ptr.has_end(): node.append(item) return node else: raise ParseError('Sentence not matched.', node) elif isinstance(item, ValueToken): if ptr.next(): node.append(Sentence(item)) else: raise ParseError('Sentence not matched.', node) else: raise TypeError('Parser.parse_definition: Unexpected type' + str(type(item))) if node.ends_with_dot() and ptr.has_end(): return node raise ParseError('Sentence not matched.', node)
def test_ends_with_dot_period(self): has_period = Sentence( [FirstToken('Short'), WordToken('sentence'), PeriodToken()]) self.assertTrue(has_period.ends_with_dot()) no_period = Sentence([FirstToken('Word')]) self.assertFalse(no_period.ends_with_dot()) super_has_period = Sentence([FirstToken('Run'), has_period]) self.assertTrue(super_has_period.ends_with_dot()) super_no_period = Sentence([FirstToken('Run'), no_period]) self.assertFalse(super_no_period.ends_with_dot())