7f645807创建于 2025年10月27日历史提交
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

// The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.

package std.ast

import std.collection.ArrayList

public func parsePattern(input: Tokens): Pattern {
    /* Get node info from flatbuffer */
    let node = unsafe {
        try {
            parse(input, {
                p: CPointer<UInt8> => return CJ_AST_ParsePattern(match (MACRO_OBJECT.get()) {
                    case Some(ptr) => ptr
                    case None => CPointer<Unit>()
                }, p, CPointer<Int64>())
            })
        } catch (e: Exception) {
            throw ParseASTException("\n" + e.message + "parsing pattern error.")
        }
    }
    /* Get decl info from flatbuffer */
    var astNode = generatePatternAST(node.GetRootAsPattern())
    return astNode
}

public func parsePatternFragment(input: Tokens, startFrom!: Int64 = 0): (Pattern, Int64) {
    let (node, count) = unsafe {
        try {
            parseFragment(
                input,
                startFrom,
                {
                    p: CPointer<UInt8>, sizeRef: CPointer<Int64> => return CJ_AST_ParsePattern(
                        match (MACRO_OBJECT.get()) {
                            case Some(ptr) => ptr
                            case None => CPointer<Unit>()
                        }, p, sizeRef)
                }
            )
        } catch (e: Exception) {
            throw ParseASTException("\n" + e.message + "parsing pattern fragment error.")
        }
    }
    var astNode = generatePatternAST(node.GetRootAsPattern())
    return (astNode, count)
}

func generatePatternAST(patternNode: Option<NodeFormat_Pattern>): Pattern {
    var pattern = match (patternNode) {
        case Some(v) => v
        case None => throw ParseASTException("generatePatternAST: get pattern")
    }
    var nodeBase = match (pattern.GetBase()) {
        case Some(v) => v
        case None => throw ParseASTException("generatePatternAST: get nodeBase")
    }
    var astKind: String = nodeBase.GetAstKind()
    var astNode = match (astKind) {
        case "var_pattern" => createVarPattern(pattern)
        case "const_pattern" => createConstPattern(pattern)
        case "tuple_pattern" => createTuplePattern(pattern)
        case "enum_pattern" => createEnumPattern(pattern)
        case "var_or_enum_pattern" => createVarOrEnumPattern(pattern, nodeBase.GetBegin())
        case "type_pattern" => createTypePattern(pattern)
        case "except_type_pattern" => createExceptTypePattern(pattern)
        case "effect_type_pattern" => createCommandTypePattern(pattern)
        case "wildcard_pattern" => createWildcardPattern(pattern, nodeBase.GetBegin())
        case _ => throw ParseASTException("Unsupported parse the pattern node: ${astKind}.\n")
    }
    addPositionInfo(astNode, nodeBase)
    return astNode
}

func createVarPattern(pattern: NodeFormat_Pattern): VarPattern {
    var varPattern = match (pattern.GetPatternAsVarPattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createVarPattern function: get varPattern")
    }
    var varDecl = match (varPattern.GetVarDecl()) {
        case Some(v) => v
        case None => throw ParseASTException("In createVarPattern function: get varDecl")
    }
    var declBase = match (varDecl.GetBase()) {
        case Some(v) => v
        case None => throw ParseASTException("In createVarPattern function: get declBase")
    }
    var indentifier = Token(TokenKind.IDENTIFIER, declBase.GetIdentifier()).addPosition(declBase.GetIdentifierPos())
    return VarPattern(indentifier)
}

func createConstPattern(pattern: NodeFormat_Pattern): ConstPattern {
    var constPattern = match (pattern.GetPatternAsConstPattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createConstPattern function: get constPattern")
    }
    var exprNode = generateExprAST(constPattern.GetLiteral())
    var litConstExpr = match (exprNode as LitConstExpr) {
        case Some(v) => v
        case None => throw ParseASTException("In createConstPattern function: get litConstExpr")
    }
    return ConstPattern(litConstExpr)
}

func createWildcardPattern(_: NodeFormat_Pattern, pos: NodeFormat_Position): WildcardPattern {
    var keyWord = Tokens().append(Token(TokenKind.WILDCARD).addPosition(pos))
    return WildcardPattern(keyWord)
}

func createVarOrEnumPattern(pattern: NodeFormat_Pattern, pos: NodeFormat_Position): VarOrEnumPattern {
    var varOrEnumPattern = match (pattern.GetPatternAsVarOrEnumPattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createVarOrEnumPattern function: get varOrEnumPattern")
    }
    var identifier = Token(TokenKind.IDENTIFIER, varOrEnumPattern.GetIdentifier()).addPosition(pos)
    /* Need to support? generatePatternAST(varOrEnumPattern.GetPattern()) */
    return VarOrEnumPattern(identifier)
}

func createExceptTypePattern(pattern: NodeFormat_Pattern): ExceptTypePattern {
    var exceptTypePattern = match (pattern.GetPatternAsExceptTypePattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createExceptTypePattern function: get exceptTypePattern")
    }
    var p = generatePatternAST(exceptTypePattern.GetPattern())
    var colon: Token = Token(TokenKind.COLON).addPosition(exceptTypePattern.GetColonPos())
    var types: ArrayList<TypeNode> = ArrayList<TypeNode>()
    for (tp in exceptTypePattern.GetTypes()) {
        types.add(generateTypeAST(tp))
    }
    var bitOr = Tokens()
    for (pos in exceptTypePattern.GetBitOrPosVec()) {
        bitOr.append(Token(TokenKind.BITOR).addPosition(pos))
    }
    return ExceptTypePattern(p, colon, types, bitOr)
}

func createCommandTypePattern(pattern: NodeFormat_Pattern): CommandTypePattern {
    var commandTypePattern = match (pattern.GetPatternAsCommandTypePattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createCommandTypePattern function: get commandTypePattern")
    }
    var p = generatePatternAST(commandTypePattern.GetPattern())
    var colon: Token = Token(TokenKind.COLON).addPosition(commandTypePattern.GetColonPos())
    var types: ArrayList<TypeNode> = ArrayList<TypeNode>()
    for (tp in commandTypePattern.GetTypes()) {
        types.add(generateTypeAST(tp))
    }
    var bitOr = Tokens()
    for (pos in commandTypePattern.GetBitOrPosVec()) {
        bitOr.append(Token(TokenKind.BITOR).addPosition(pos))
    }
    return CommandTypePattern(p, colon, types, bitOr)
}

func createTypePattern(pattern: NodeFormat_Pattern): TypePattern {
    var typePattern = match (pattern.GetPatternAsTypePattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createTypePattern function: get typePattern")
    }
    var p = generatePatternAST(typePattern.GetPattern())
    var colon: Token = Token(TokenKind.COLON).addPosition(typePattern.GetColonPos())
    var ty: TypeNode = generateTypeAST(typePattern.GetType())
    return TypePattern(p, colon, ty)
}

func createEnumPattern(pattern: NodeFormat_Pattern): EnumPattern {
    var enumPattern = match (pattern.GetPatternAsEnumPattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createEnumPattern function: get enumPattern")
    }
    var exprNode = match (enumPattern.GetRef()) {
        case Some(v) => generateExprAST(v)
        case None => throw ParseASTException("EnumPattern's constructor is not a RefExpr")
    }
    var lParen: Token = Token(TokenKind.LPAREN).addPosition(enumPattern.GetLeftParenPos())
    var patterns: ArrayList<Pattern> = ArrayList<Pattern>()
    for (p in enumPattern.GetPatterns()) {
        patterns.add(generatePatternAST(p))
    }
    let commas = Tokens()
    for (commaPos in enumPattern.GetCommaPosVec()) {
        commas.append(Token(TokenKind.COMMA).addPosition(commaPos))
    }
    var rParen: Token = Token(TokenKind.RPAREN).addPosition(enumPattern.GetRightParenPos())
    return EnumPattern(exprNode, lParen, patterns, commas, rParen)
}

func createTuplePattern(pattern: NodeFormat_Pattern): TuplePattern {
    var tuplePattern = match (pattern.GetPatternAsTuplePattern()) {
        case Some(v) => v
        case None => throw ParseASTException("In createTuplePattern function: get tuplePattern")
    }
    var lParen: Token = Token(TokenKind.LPAREN).addPosition(tuplePattern.GetLeftParenPos())
    var patterns: ArrayList<Pattern> = ArrayList<Pattern>()
    for (p in tuplePattern.GetPatterns()) {
        patterns.add(generatePatternAST(p))
    }
    let commas = Tokens()
    for (commaPos in tuplePattern.GetCommaPosVec()) {
        commas.append(Token(TokenKind.COMMA).addPosition(commaPos))
    }
    var rParen: Token = Token(TokenKind.RPAREN).addPosition(tuplePattern.GetRightParenPos())
    return TuplePattern(lParen, patterns, commas, rParen)
}