/*
* 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 open class Pattern <: Node {
init() {
super()
}
public open func toTokens(): Tokens {
Tokens()
}
public open func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
}
protected open func dump(_: UInt16): String {
""
}
}
private func getTypePatternTokens(
pattern: Pattern,
colon: Token,
types: ArrayList<TypeNode>,
bitOr: Tokens
): Tokens {
let ret = Tokens().append(pattern).append(colon)
for (i in 0..types.size - 1) {
ret.append(types[i]).append(bitOr[i])
}
ret.append(types[types.size - 1])
ret
}
private func traverseTypePatternChildren(v: Visitor, pattern: Pattern, types: ArrayList<TypeNode>): Unit {
pattern.traverse(v)
for (ty in types) {
ty.traverse(v)
}
}
public class ConstPattern <: Pattern {
init(litConstExpr: LitConstExpr) {
litConstExpr_ = litConstExpr
}
public init(inputs: Tokens) {
try {
match (parsePattern(inputs) as ConstPattern) {
case Some(v) =>
this.begin_ = v.beginPos
this.end_ = v.endPos
this.litConstExpr_ = v.litConstExpr_
case None => throw ASTException("Cannot construct the 'ConstPattern' node.")
}
} catch (e: ParseASTException) {
if (e.message == String.empty) {
throw ASTException("Cannot construct the 'ConstPattern' node.")
} else {
throw ASTException(e.message)
}
}
}
public init() {}
private var litConstExpr_: LitConstExpr = LitConstExpr()
public mut prop litConstExpr: LitConstExpr {
get() {
litConstExpr_
}
set(v) {
litConstExpr_ = v
}
}
public func toTokens(): Tokens {
Tokens().append(litConstExpr_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
if (v.needBreakTraverse()) {
return
}
litConstExpr_.traverse(v)
return
}
protected func dump(indent: UInt16): String {
var ret: String = "ConstPattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getIndent(currentIndent) + "-litConstExpr: "
ret += litConstExpr_.dump(currentIndent)
ret += getIndent(indent) + "}\n"
ret
}
}
public class WildcardPattern <: Pattern {
public init(keyword: Tokens) {
if (keyword.size == 0) {
throw ASTException("Cannot construct the 'WildcardPattern' node. (Empty Input)")
}
keyWord_ = keyword[0]
checkTokenType(keyWord_, WILDCARD)
this.begin_ = keyWord_.pos
this.end_ = Position(begin_.fileID, begin_.line, begin_.column + Int32(keyWord_.value.size))
}
public init() {}
private var keyWord_: Token = Token(TokenKind.WILDCARD)
public mut prop wildcard: Token {
get() {
keyWord_
}
set(v) {
checkTokenType(v, WILDCARD)
keyWord_ = v
}
}
public func toTokens(): Tokens {
Tokens().append(keyWord_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
return
}
protected func dump(indent: UInt16): String {
var ret: String = "WildcardPattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getTokenIndent("-wildcard", keyWord_, currentIndent)
ret += getIndent(indent) + "}\n"
ret
}
}
public class VarPattern <: Pattern {
public init(identifier: Token) {
identifier_ = identifier
checkTokenType(identifier_, IDENTIFIER)
this.begin_ = identifier_.pos
this.end_ = Position(begin_.fileID, begin_.line, begin_.column + Int32(identifier_.value.size))
}
public init() {}
private var identifier_: Token = Token(TokenKind.IDENTIFIER, "")
public mut prop identifier: Token {
get() {
identifier_
}
set(v) {
checkTokenType(v, IDENTIFIER)
identifier_ = v
}
}
public func toTokens(): Tokens {
Tokens().append(identifier_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
return
}
protected func dump(indent: UInt16): String {
var ret: String = "VarPattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getTokenIndent("-identifier", identifier_, currentIndent)
ret += getIndent(indent) + "}\n"
ret
}
}
public class VarOrEnumPattern <: Pattern {
public init(identifier: Token) {
identifier_ = identifier
checkTokenType(identifier_, IDENTIFIER)
this.begin_ = identifier_.pos
this.end_ = Position(begin_.fileID, begin_.line, begin_.column + Int32(identifier_.value.size))
}
public init() {}
private var identifier_ = Token(TokenKind.IDENTIFIER, "")
public mut prop identifier: Token {
get() {
identifier_
}
set(v) {
checkTokenType(v, IDENTIFIER)
identifier_ = v
}
}
public func toTokens(): Tokens {
Tokens().append(identifier_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
return
}
protected func dump(indent: UInt16): String {
var ret: String = "VarOrEnumPattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getTokenIndent("-identifier", identifier_, currentIndent)
ret += getIndent(indent) + "}\n"
ret
}
}
public class ExceptTypePattern <: Pattern {
init(pattern: Pattern, colon: Token, types: ArrayList<TypeNode>, bitOr: Tokens) {
pattern_ = pattern
colon_ = colon
types_ = types
bitOr_ = bitOr
}
public init() {}
public init(inputs: Tokens) {
try {
let tokens = Tokens()
tokens
.append(quote(try {} catch))
.append(Token(LPAREN))
.append(inputs)
.append(Token(RPAREN))
.append(Token(LCURL))
.append(Token(RCURL));
let tryExpr = (parseExpr(tokens) as TryExpr).getOrThrow().catchPatterns[0]
var exceptTypePa = (tryExpr as ExceptTypePattern).getOrThrow()
match (exceptTypePa as ExceptTypePattern) {
case Some(v) =>
this.begin_ = v.beginPos
this.end_ = v.endPos
this.pattern_ = v.pattern_
this.colon_ = v.colon_
this.types_ = v.types_
this.bitOr_ = v.bitOr_
case None => throw ASTException("Cannot construct the 'ExceptTypePattern' node.")
}
} catch (e: ParseASTException | NoneValueException) {
if (e.message == String.empty) {
throw ASTException("Cannot construct the 'ExceptTypePattern' node.")
} else {
throw ASTException(e.message)
}
}
}
private var pattern_: Pattern = Pattern()
private var colon_: Token = Token(TokenKind.COLON)
private var types_: ArrayList<TypeNode> = ArrayList<TypeNode>()
private var bitOr_: Tokens = Tokens()
public mut prop pattern: Pattern {
get() {
pattern_
}
set(v) {
pattern_ = v
}
}
public mut prop colon: Token {
get() {
colon_
}
set(v) {
checkTokenType(v, COLON)
colon_ = v
}
}
public mut prop types: ArrayList<TypeNode> {
get() {
types_
}
set(v) {
types_ = v
}
}
public func toTokens(): Tokens {
if (bitOr_.size == 0) {
bitOr_ = Tokens(Array(types_.size - 1, repeat: Token(TokenKind.BITOR)))
}
getTypePatternTokens(pattern_, colon_, types_, bitOr_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
if (v.needBreakTraverse()) {
return
}
traverseTypePatternChildren(v, pattern_, types_)
return
}
protected func dump(indent: UInt16): String {
var ret: String = "ExceptTypePattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getIndent(currentIndent) + "-pattern: "
ret += pattern_.dump(currentIndent)
ret += getTokenIndent("-colon", colon_, currentIndent)
ret += dumpNodes("-types", types_, currentIndent)
ret += getIndent(indent) + "}\n"
ret
}
}
public class CommandTypePattern <: Pattern {
init(pattern: Pattern, colon: Token, types: ArrayList<TypeNode>, bitOr: Tokens) {
pattern_ = pattern
colon_ = colon
types_ = types
bitOr_ = bitOr
}
public init() {}
public init(inputs: Tokens) {
try {
let tokens = Tokens()
tokens.append(quote(try {})).append(Token(HANDLE)).append(Token(LPAREN)).append(inputs).append(Token(RPAREN)).append(
Token(LCURL)).append(Token(RCURL));
let commandTyPattern = (parseExpr(tokens) as TryExpr).getOrThrow().handlers[0].commandPattern_
match (commandTyPattern as CommandTypePattern) {
case Some(v) =>
this.begin_ = v.beginPos
this.end_ = v.endPos
this.pattern_ = v.pattern_
this.colon_ = v.colon_
this.types_ = v.types_
this.bitOr_ = v.bitOr_
case None => throw ASTException("Cannot construct the 'CommandTypePattern' node.")
}
} catch (e: ParseASTException | NoneValueException) {
if (e.message == String.empty) {
throw ASTException("Cannot construct the 'CommandTypePattern' node.")
} else {
throw ASTException(e.message)
}
}
}
private var pattern_: Pattern = Pattern()
private var colon_: Token = Token(TokenKind.COLON)
private var types_: ArrayList<TypeNode> = ArrayList<TypeNode>()
private var bitOr_: Tokens = Tokens()
public mut prop pattern: Pattern {
get() {
pattern_
}
set(v) {
pattern_ = v
}
}
public mut prop colon: Token {
get() {
colon_
}
set(v) {
checkTokenType(v, COLON)
colon_ = v
}
}
public mut prop types: ArrayList<TypeNode> {
get() {
types_
}
set(v) {
types_ = v
}
}
public func toTokens(): Tokens {
if (bitOr_.size == 0) {
bitOr_ = Tokens(Array(types_.size - 1, repeat: Token(TokenKind.BITOR)))
}
getTypePatternTokens(pattern_, colon_, types_, bitOr_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
if (v.needBreakTraverse()) {
return
}
traverseTypePatternChildren(v, pattern_, types_)
return
}
protected func dump(indent: UInt16): String {
var ret: String = "CommandTypePattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getIndent(currentIndent) + "-pattern: "
ret += pattern_.dump(currentIndent)
ret += getTokenIndent("-colon", colon_, currentIndent)
ret += dumpNodes("-types", types_, currentIndent)
ret += getIndent(indent) + "}\n"
ret
}
}
public class TypePattern <: Pattern {
init(pattern: Pattern, colon: Token, ty: TypeNode) {
pattern_ = pattern
colon_ = colon
type_ = ty
}
public init() {}
public init(inputs: Tokens) {
try {
match (parsePattern(inputs) as TypePattern) {
case Some(v) =>
this.begin_ = v.beginPos
this.end_ = v.endPos
this.pattern_ = v.pattern_
this.colon_ = v.colon_
this.type_ = v.type_
case None => throw ASTException("Cannot construct the 'TypePattern' node.")
}
} catch (e: ParseASTException) {
if (e.message == String.empty) {
throw ASTException("Cannot construct the 'TypePattern' node.")
} else {
throw ASTException(e.message)
}
}
}
private var pattern_: Pattern = Pattern()
private var colon_: Token = Token(TokenKind.COLON)
private var type_: TypeNode = TypeNode()
public mut prop pattern: Pattern {
get() {
pattern_
}
set(v) {
pattern_ = v
}
}
public mut prop colon: Token {
get() {
colon_
}
set(v) {
checkTokenType(v, COLON)
colon_ = v
}
}
public mut prop patternType: TypeNode {
get() {
type_
}
set(v) {
type_ = v
}
}
public func toTokens(): Tokens {
Tokens().append(pattern_).append(colon_).append(type_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
if (v.needBreakTraverse()) {
return
}
pattern_.traverse(v)
type_.traverse(v)
return
}
protected func dump(indent: UInt16): String {
var ret: String = "TypePattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getIndent(currentIndent) + "-pattern: "
ret += pattern_.dump(currentIndent)
ret += getTokenIndent("-colon", colon_, currentIndent)
ret += getIndent(currentIndent) + "-patternType: "
ret += type_.dump(currentIndent)
ret += getIndent(indent) + "}\n"
ret
}
}
public class EnumPattern <: Pattern {
init(constructor: Expr, lParen: Token, patterns: ArrayList<Pattern>, commas: Tokens, rParen: Token) {
constructor_ = constructor
lParen_ = lParen
patterns_ = patterns
commas_ = commas
rParen_ = rParen
}
public init() {}
public init(inputs: Tokens) {
try {
match (parsePattern(inputs) as EnumPattern) {
case Some(v) =>
this.begin_ = v.beginPos
this.end_ = v.endPos
this.constructor_ = v.constructor_
this.lParen_ = checkValid(v.lParen_)
this.patterns_ = v.patterns_
this.commas_ = v.commas_
this.rParen_ = checkValid(v.rParen_)
case None => throw ASTException("Cannot construct the 'EnumPattern' node.")
}
} catch (e: ParseASTException) {
if (e.message == String.empty) {
throw ASTException("Cannot construct the 'EnumPattern' node.")
} else {
throw ASTException(e.message)
}
}
}
private var constructor_: Expr = Expr()
private var lParen_: Token = Token(TokenKind.LPAREN)
private var patterns_: ArrayList<Pattern> = ArrayList<Pattern>()
private var commas_: Tokens = Tokens()
private var rParen_: Token = Token(TokenKind.RPAREN)
public mut prop constructor: Expr {
get() {
constructor_
}
set(v) {
constructor_ = v
}
}
public mut prop lParen: Token {
get() {
lParen_
}
set(v) {
checkTokenType(v, LPAREN)
lParen_ = v
}
}
public mut prop patterns: ArrayList<Pattern> {
get() {
patterns_
}
set(v) {
patterns_ = v
}
}
public mut prop commas: Tokens {
get() {
commas_
}
set(v) {
checkTokensType(v, COMMA)
commas_ = v
}
}
public mut prop rParen: Token {
get() {
rParen_
}
set(v) {
checkTokenType(v, RPAREN)
rParen_ = v
}
}
public func toTokens(): Tokens {
var ret = Tokens().append(constructor_)
if (!patterns_.isEmpty()) {
ret.append(lParen_)
for (i in 0..patterns_.size - 1) {
let comma = if (i >= commas.size) {
Token(COMMA)
} else {
commas[i]
}
ret.append(patterns_[i]).append(comma)
}
ret.append(patterns_[patterns_.size - 1]).append(rParen_)
}
ret
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
if (v.needBreakTraverse()) {
return
}
constructor_.traverse(v)
for (p in patterns_) {
p.traverse(v)
}
return
}
protected func dump(indent: UInt16): String {
var ret: String = "EnumPattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
ret += getIndent(currentIndent) + "-constructor: "
ret += constructor_.dump(currentIndent)
for (i in 0..patterns_.size) {
ret += getIndent(currentIndent) + "-patterns: ${i}, "
ret += patterns_[i].dump(currentIndent)
}
ret += getIndent(indent) + "}\n"
ret
}
}
public class TuplePattern <: Pattern {
init(lParen: Token, patterns: ArrayList<Pattern>, commas: Tokens, rParen: Token) {
lParen_ = lParen
patterns_ = patterns
commas_ = commas
rParen_ = rParen
}
public init() {}
public init(inputs: Tokens) {
try {
match (parsePattern(inputs) as TuplePattern) {
case Some(v) =>
this.begin_ = v.beginPos
this.end_ = v.endPos
this.lParen_ = v.lParen_
this.patterns_ = v.patterns_
this.commas_ = v.commas_
this.rParen_ = v.rParen_
case None => throw ASTException("Cannot construct the 'TuplePattern' node.")
}
} catch (e: ParseASTException) {
if (e.message == String.empty) {
throw ASTException("Cannot construct the 'TuplePattern' node.")
} else {
throw ASTException(e.message)
}
}
}
private var lParen_: Token = Token(TokenKind.LPAREN)
private var patterns_: ArrayList<Pattern> = ArrayList<Pattern>()
private var commas_: Tokens = Tokens()
private var rParen_: Token = Token(TokenKind.RPAREN)
public mut prop lParen: Token {
get() {
lParen_
}
set(v) {
checkTokenType(v, LPAREN)
lParen_ = v
}
}
public mut prop patterns: ArrayList<Pattern> {
get() {
patterns_
}
set(v) {
patterns_ = v
}
}
public mut prop commas: Tokens {
get() {
commas_
}
set(v) {
checkTokensType(v, COMMA)
commas_ = v
}
}
public mut prop rParen: Token {
get() {
rParen_
}
set(v) {
checkTokenType(v, RPAREN)
rParen_ = v
}
}
public func toTokens(): Tokens {
var ret = Tokens().append(lParen_)
if (!patterns_.isEmpty()) {
for (i in 0..patterns_.size - 1) {
let comma = if (i >= commas.size) {
Token(COMMA)
} else {
commas[i]
}
ret.append(patterns_[i]).append(comma)
}
ret.append(patterns_[patterns_.size - 1])
}
ret.append(rParen_)
}
public func traverse(v: Visitor): Unit {
v.visit(this)
super.traverse(v)
if (v.needBreakTraverse()) {
return
}
for (p in patterns_) {
p.traverse(v)
}
return
}
protected func dump(indent: UInt16): String {
var ret: String = "TuplePattern {\n"
currentIndent = indent
if (indent != 0 || beginNode) {
currentIndent++
}
for (i in 0..patterns_.size) {
ret += getIndent(currentIndent) + "-patterns: ${i}, "
ret += patterns_[i].dump(currentIndent)
}
ret += getIndent(indent) + "}\n"
ret
}
}