Пример #1
0
def unary_operator(tokens, precedences):
    if tokens.current.value not in ('-', '!', '?', '#'):
        raise ParserException('未知或未实现操作符 {0}'.format(tokens.current.value),
                              tokens.current.line_no)
    token = tokens.consume('OPERATOR')
    right = expression(tokens, precedences.get(token.value, 0))
    if right is not None:
        return ast.UnaryOperator(token.line_no, token.value, right)
    raise ParserException('操作符 {0} 右侧表达式缺失'.format(token.value), token.line_no)
Пример #2
0
def binary_operator(tokens, left, precedences):
    if tokens.current.value not in ('+', '-', '*', '/', '^', '%', '>', '>=',
                                    '<', '<=', '==', '!=', 'and', 'or'):
        raise ParserException('未知或未实现操作符 {0}'.format(tokens.current.value),
                              tokens.current.line_no)
    token = tokens.consume('OPERATOR')
    right = expression(tokens, precedences.get(token.value, 0))
    if right is not None:
        return ast.BinaryOperator(token.line_no, token.value, left, right)
    raise ParserException('操作符 {0} 右侧表达式缺失'.format(token.value), token.line_no)
Пример #3
0
def swap_statement(tokens, left):
    '''交换语句'''
    line_no = tokens.current.line_no
    tokens.consume('SWAP')
    right = expression(tokens)
    if isinstance(left, ast.Readonly) or isinstance(right, ast.Readonly):
        raise ParserException('不可将值赋予只读的关键词', tokens.current.line_no)
    tokens.consume('SEMICOLON')
    if right is not None:
        return ast.Swap(line_no, left, right)
    raise ParserException('交换语句右侧表达式缺失', token.line_no)
Пример #4
0
def assignment_statement(tokens, left):
    '''赋值语句'''
    line_no = tokens.current.line_no
    if isinstance(left, ast.Readonly):
        raise ParserException('不可将值赋予只读的关键词', tokens.current.line_no)
    tokens.consume('ASSIGN')
    right = expression(tokens)
    tokens.consume('SEMICOLON')
    if right is not None:
        return ast.Assignment(line_no, left, right)
    raise ParserException('赋值语句右侧表达式缺失', token.line_no)
Пример #5
0
def call_block_statement(tokens):
    token = tokens.consume('CALL')
    right = expression(tokens)
    tokens.consume('SEMICOLON')
    if right is not None:
        return ast.CallBlock(token.line_no, right)
    raise ParserException('操作符 {0} 右侧表达式缺失'.format(token.value), token.line_no)
Пример #6
0
def call(tokens, left, precedences):
    token = tokens.consume('CALL')
    right = expression(tokens, precedences.get(token.value, 0))
    if right is None:
        raise ParserException('右侧调用函数 {0} 缺失'.format(token.value),
                              token.line_no)
    return ast.Call(token.line_no, left, right)
Пример #7
0
def reload(tokens, left, precedences):
    token = tokens.consume('RELOAD')
    right = expression(tokens, precedences.get(token.value, 0))
    if right is None:
        raise ParserException('重装符 {0} 右侧表达式缺失'.format(token.value),
                              token.line_no)
    return ast.Reload(token.line_no, left, right)
Пример #8
0
def unfold_statement(tokens):
    '''展开语句'''
    token = tokens.consume('UNFOLD')
    right = expression(tokens)
    tokens.consume('SEMICOLON')
    if right is not None:
        return ast.Unfold(token.line_no, right)
    raise ParserException('操作符 {0} 右侧表达式缺失'.format(token.value), token.line_no)
Пример #9
0
def return_statement(tokens):
    '''返回语句'''
    if ParserScope.get_node_with('fun'):
        token = tokens.consume('RETURN')
        right = expression(tokens)
        if right is None:
            right = ast.Nothing(tokens.current.line_no)
        tokens.consume('SEMICOLON')
        return ast.Return(tokens.current.line_no, right)
    else:
        raise ParserException('在函数外使用return', tokens.current.line_no)
Пример #10
0
def subscript(tokens, left, precedences):
    token = tokens.consume('LBRACK')
    if tokens.current.name == 'ALWAYS':
        token = tokens.consume('ALWAYS')
        right = ast.Always(token.line_no)
    else:
        # 优先级永远低于括号内的
        right = expression(tokens)
    tokens.consume('RBRACK')
    if right is None:
        raise ParserException('下标不能为空', token.line_no)
    return ast.Subscript(token.line_no, left, right)
Пример #11
0
def table(tokens, precedences):
    start_token = tokens.consume('LBRACK')
    items = []
    while not tokens.is_end():
        if tokens.current.name == 'ALWAYS':
            token = tokens.consume('ALWAYS')
            tokens.consume('COLON')
            item = expression(tokens)
            if item is None:
                raise ParserException(
                    '映射右侧值表达式缺失'.format(tokens.current.value),
                    tokens.current.line_no)
            items.append(ast.AlwaysItem(token.line_no, item))
        elif tokens.current.name == 'UNFOLD':
            tokens.consume('UNFOLD')
            right = expression(tokens)
            if right is not None:
                items.append(ast.Unfold(right.line_no, right))
            else:
                raise ParserException(
                    '展开操作符 {0} 右侧表达式缺失'.format(tokens.current.value),
                    tokens.current.line_no)
        else:
            left = expression(tokens)
            if left is None:
                break
            if tokens.current.name == 'COLON':
                token = tokens.consume('COLON')
                right = expression(tokens)
                if right is None:
                    raise ParserException('映射右侧值表达式缺失', left.line_no)
                items.append(ast.DictItem(token.line_no, left, right))
            else:
                items.append(ast.ListItem(left.line_no, left))
        if tokens.current.name == 'COMMA':
            tokens.consume('COMMA')
        else:
            break
    tokens.consume('RBRACK')
    return ast.TableStatementNode(start_token.line_no, items)
Пример #12
0
def statements(tokens, scope):
    stmts = []
    while not tokens.is_end():
        parser, container = statement.get(
            tokens.current.name, [expression_statement, ('fun', 'program')])
        if scope not in container:
            raise ParserException(
                '{} 不能在 {} 中使用'.format(tokens.current.name, scope),
                tokens.current.line_no)
        stmt = parser(tokens)
        if stmt:
            stmts.append(stmt)
        else:
            break
    return stmts
Пример #13
0
def reduce(tokens, left, precedences):
    token = tokens.consume('REDUCE')
    right = expression(tokens, precedences.get(token.value, 0))
    if right is not None:
        return ast.Reduce(token.line_no, left, right)
    raise ParserException('操作符 {0} 右侧表达式缺失'.format(token.value), token.line_no)
Пример #14
0
def index(tokens, _):
    if ParserScope.get_node_with('loop'):
        token = tokens.consume('INDEX')
        return ast.Index(token.line_no)
    else:
        raise ParserException('在循环外使用index', tokens.current.line_no)
Пример #15
0
def variable(tokens, precedences):
    token = tokens.consume('AT')
    right = expression(tokens, precedences.get(token.value, 0))
    if right is not None:
        return ast.Variable(token.line_no, right)
    raise ParserException('{0} 右侧表达式缺失'.format(token.value), token.line_no)
Пример #16
0
def incorrect_always(tokens, _):
    raise ParserException('always只能用于Table声明或下标', tokens.current.line_no)