/*
* 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.
*/
package stdx.syntax
import std.collection.ArrayList
private func translateExprChild<T>(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
propInfo: PropInfo): T where T <: SyntaxTreeNode {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
return cast<T>(SyntaxNodeImplTranslator.translate(curNode, startPos + propInfo.offset, parentNode)).getOrThrow()
}
private func createExprTokenRange(pos: CodePosition, size: Int64): CodePositionRange {
return CodePositionRange(pos, pos + size)
}
private func createExprTokenRanges(positions: Array<CodePosition>, size: Int64): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (pos in positions) {
ret.add(createExprTokenRange(pos, size))
}
return ret.toArray()
}
sealed abstract class Expr <: SyntaxTreeNode {
init(nodePos: CodePositionRange, nodeImpl: SyntaxNodeImpl, parentNode: ?SyntaxTreeNode,
commentsPropInfo: Array<PropInfo>) {
super(nodePos, nodeImpl, parentNode, commentsPropInfo)
}
init(nodeImpl: SyntaxNodeImpl, hasComment!: Bool = true) {
super(nodeImpl, hasComment: hasComment)
}
}
class ArrayLiteralPosInfos {
let lSquarePos: CodePosition
let rSquarePos: CodePosition
let commasPos: Array<CodePosition>
init(lSquarePos: CodePosition, rSquarePos: CodePosition, commasPos: Array<CodePosition>) {
this.lSquarePos = lSquarePos
this.rSquarePos = rSquarePos
this.commasPos = commasPos
}
}
class ArrayLiteralPropInfos {
let elementsPropInfo: PropInfo
init(elementsPropInfo: PropInfo) {
this.elementsPropInfo = elementsPropInfo
}
}
/**
* @brief Represents an literal of array type.
*
* The ArrayLiteral class is a subclass of Expr and is used to model array expressions.
* It contains an array of Expr objects.
*/
public class ArrayLiteral <: Expr {
private let startPos: CodePosition
private let posInfos: ArrayLiteralPosInfos
private let propInfos: ArrayLiteralPropInfos
/**
* @brief Gets the position range of the left square bracket in the code.
*
* @return A CodePositionRange representing the position range of the left square bracket.
*/
public func getLSquarePos(): CodePositionRange {
return createExprTokenRange(posInfos.lSquarePos, SyntaxNodeKind.LSquareToken.size)
}
/**
* @brief Gets the position range of the right square bracket in the code.
*
* @return A CodePositionRange representing the position range of the right square bracket.
*/
public func getRSquarePos(): CodePositionRange {
return createExprTokenRange(posInfos.rSquarePos, SyntaxNodeKind.RSquareToken.size)
}
/**
* @brief Gets the position ranges of the commas in the code.
*
* @return An ArrayList of CodePositionRange representing the position ranges of the commas.
*/
public func getCommasPos(): Array<CodePositionRange> {
return createExprTokenRanges(posInfos.commasPos, SyntaxNodeKind.CommaToken.size)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: ArrayLiteralPosInfos,
propInfos: ArrayLiteralPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new ArrayLiteral node.
*/
public init(elements: Array<Expr>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createArrayLiteralImpl(elements, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<ArrayLiteral>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief Array of expressions.
*
* This member variable stores an array of expressions of type Expr.
*/
public prop elements: Array<Expr> {
get() {
let lp = LocalParser((nodeImpl as NonTerminal).getOrThrow().children, propInfos.elementsPropInfo.offset,
index: propInfos.elementsPropInfo.index)
let exprs = ArrayList<Expr>()
let predictExpr = {
kind: SyntaxNodeKind => kind.isExpr()
}
while (lp.look(predictExpr)) {
if (let Some(node) <- lp.consume()) {
exprs.add(
cast<Expr>(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this)).getOrThrow())
lp.moveOffset(node)
}
lp.moveOffset(lp.lookAndConsume(SyntaxNodeKind.CommaToken))
}
exprs.toArray()
}
}
}
class AsExprPropInfos {
let srcValPropInfo: PropInfo
let targetTypeAnnotationPropInfo: PropInfo
init(srcValPropInfo: PropInfo, targetTypeAnnotationPropInfo: PropInfo) {
this.srcValPropInfo = srcValPropInfo
this.targetTypeAnnotationPropInfo = targetTypeAnnotationPropInfo
}
}
class AsExprPosInfos {
let asKeyWordPos: CodePosition
init(asKeyWordPos: CodePosition) {
this.asKeyWordPos = asKeyWordPos
}
}
/**
* @brief Represents an expression for type casting.
*
* The AsExpr class is a subclass of Expr and is used to model type casting expressions.
* It contains a source value expression and a target type annotation.
*/
public class AsExpr <: Expr {
private let startPos: CodePosition
private let propInfos: AsExprPropInfos
private let posInfos: AsExprPosInfos
/**
* @brief Retrieves the position range of the 'as' keyword.
*
* @return The position range representing the start and end positions of the 'as' keyword.
*/
public func getAsKeyWordPos(): CodePositionRange {
let endPos = posInfos.asKeyWordPos + SyntaxNodeKind.AsToken.size
return CodePositionRange(posInfos.asKeyWordPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfo: AsExprPosInfos,
propInfo: AsExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfo
this.propInfos = propInfo
}
/**
* @brief Initialize node with source value and target type.
*/
public init(srcVal: Expr, targetTypeAnnotation: TypeAnnotation, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createAsExprImpl(srcVal, targetTypeAnnotation, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<AsExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief Source expression for type casting.
*
* This member variable stores the source expression that needs to be type casted.
*/
public prop srcVal: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.srcValPropInfo)
}
}
/**
* @brief Target type annotation.
*
* This member variable stores the target type annotation to which the source value is casted.
*/
public prop targetTypeAnnotation: TypeAnnotation {
get() {
return translateExprChild<TypeAnnotation>(nodeImpl, startPos, this,
propInfos.targetTypeAnnotationPropInfo)
}
}
}
/**
* @brief Enumeration for different assignment operation kinds.
*
* The AssignOpKind enumeration represents various types of assignment operations
* that can be used in expressions. Each operation kind is an identifier that
* specifies the type of assignment to be performed.
*/
public enum AssignOpKind {
| AddAssign
| AndAssign
| Assign
| BitAndAssign
| BitOrAssign
| BitXorAssign
| DivAssign
| ExpAssign
| LShiftAssign
| ModAssign
| MulAssign
| OrAssign
| RShiftAssign
| SubAssign
| ...
}
class AssignExprPropInfos {
let lhsPropInfo: PropInfo
let rhsPropInfo: PropInfo
init(lhsPropInfo: PropInfo, rhsPropInfo: PropInfo) {
this.lhsPropInfo = lhsPropInfo
this.rhsPropInfo = rhsPropInfo
}
}
class AssignExprPosInfos {
let assignOpPos: CodePosition
init(assignOpPos: CodePosition) {
this.assignOpPos = assignOpPos
}
}
/**
* @brief Represents an assignment expression.
*
* The AssignExpr class is a subclass of Expr and is used to model assignment expressions.
* It contains an assignment operator kind and two operands: the left-hand side (lhs)
* and the right-hand side (rhs).
*/
public class AssignExpr <: Expr {
private let assignOpKind_: AssignOpKind
private let startPos: CodePosition
private let propInfos: AssignExprPropInfos
private let posInfos: AssignExprPosInfos
/**
* @brief Retrieves the position range of the assignment operator.
*
* @return The position range of the assignment operator as a CodePositionRange object.
*/
public func getAssignOpPos(): CodePositionRange {
let endPos = posInfos.assignOpPos + match (assignOpKind) {
case AddAssign => SyntaxNodeKind.AddAssignToken.size
case AndAssign => SyntaxNodeKind.AndAssignToken.size
case Assign => SyntaxNodeKind.AssignToken.size
case BitAndAssign => SyntaxNodeKind.BitAndAssignToken.size
case BitOrAssign => SyntaxNodeKind.BitOrAssignToken.size
case BitXorAssign => SyntaxNodeKind.BitXorAssignToken.size
case DivAssign => SyntaxNodeKind.DivAssignToken.size
case ExpAssign => SyntaxNodeKind.ExpAssignToken.size
case LShiftAssign => SyntaxNodeKind.LShiftAssignToken.size
case ModAssign => SyntaxNodeKind.ModAssignToken.size
case MulAssign => SyntaxNodeKind.MulAssignToken.size
case OrAssign => SyntaxNodeKind.OrAssignToken.size
case RShiftAssign => SyntaxNodeKind.RShiftAssignToken.size
case SubAssign => SyntaxNodeKind.SubAssignToken.size
case _ => 0
}
return CodePositionRange(posInfos.assignOpPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, assignOpKind_: AssignOpKind,
posInfos: AssignExprPosInfos, propInfos: AssignExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.assignOpKind_ = assignOpKind_
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new AssignExpr node.
*/
public init(assignOpKind: AssignOpKind, lhs: SyntaxTreeNode, rhs: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createAssignExprImpl(assignOpKind, lhs, rhs, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<AssignExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.assignOpKind_ = assignOpKind
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief Type of assignment operation.
*
* This member variable stores the kind of assignment operation specified by the
* AssignOpKind enumeration.
*/
public prop assignOpKind: AssignOpKind {
get() {
assignOpKind_
}
}
/**
* @brief Left-hand side expression.
*
* This member variable stores the left-hand side expression where the value is
* assigned.
*/
public prop lhs: SyntaxTreeNode {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.lhsPropInfo.index]
let offset = propInfos.lhsPropInfo.offset
cast<SyntaxTreeNode>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief Right-hand side expression.
*
* This member variable stores the right-hand side expression providing the value
* to be assigned.
*/
public prop rhs: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.rhsPropInfo)
}
}
}
/**
* @brief Enumeration for different atomic condition types.
*
* The AtomicCondition enumeration represents various types of atomic conditions
* that can be used in logical expressions. Each condition type is an identifier that
* specifies the structure and semantics of the condition, which can be a let pattern,
* an expression, a parenthesized condition, or other forms.
*/
public enum AtomicCondition {
| LetPatternCondition(LetPattern)
| Expression(Expr)
| ParenConditionConstructor(ParenCondition)
| ...
}
/**
* @brief Enumeration for different binary operation kinds.
*
* The BinaryOpKind enumeration represents various types of binary operations
* that can be performed on expressions. Each operation kind is an identifier that
* specifies the type of operation to be performed.
* */
public enum BinaryOpKind {
| Add
| And
| BitAnd
| BitOr
| BitXor
| Coalescing
| Composition
| Div
| Equal
| Exp
| Ge
| Gt
| Le
| LShift
| Lt
| Mod
| Mul
| NotEq
| Or
| Pipeline
| RShift
| Sub
| ...
}
class BinaryExprPropInfos {
let lhsPropInfo: PropInfo
let rhsPropInfo: PropInfo
init(lhsPropInfo: PropInfo, rhsPropInfo: PropInfo) {
this.lhsPropInfo = lhsPropInfo
this.rhsPropInfo = rhsPropInfo
}
}
class BinaryExprPosInfos {
let opPos: CodePosition
init(opPos: CodePosition) {
this.opPos = opPos
}
}
/**
* @brief Represents a binary expression.
*
* The BinaryExpr class is a subclass of Expr and is used to model binary expressions.
* It contains a binary operator kind and two operands: the left-hand side (lhs)
* and the right-hand side (rhs).
*/
public class BinaryExpr <: Expr {
private let opKInd_: BinaryOpKind
private let startPos: CodePosition
private let propInfos: BinaryExprPropInfos
private let posInfos: BinaryExprPosInfos
/**
* @brief Retrieves the position range of the operator in the code.
*
* @return CodePositionRange representing the start and end positions of the operator.
*/
public func getOperatorPos(): CodePositionRange {
let endPos = posInfos.opPos + match (opKind) {
case BinaryOpKind.Add => SyntaxNodeKind.AddToken.size
case BinaryOpKind.And => SyntaxNodeKind.AndToken.size
case BinaryOpKind.BitAnd => SyntaxNodeKind.BitAndToken.size
case BinaryOpKind.BitOr => SyntaxNodeKind.BitOrToken.size
case BinaryOpKind.BitXor => SyntaxNodeKind.BitXorToken.size
case BinaryOpKind.Coalescing => SyntaxNodeKind.CoalescingToken.size
case BinaryOpKind.Composition => SyntaxNodeKind.CompositionToken.size
case BinaryOpKind.Div => SyntaxNodeKind.DivToken.size
case BinaryOpKind.Equal => SyntaxNodeKind.EqualToken.size
case BinaryOpKind.Exp => SyntaxNodeKind.ExpToken.size
case BinaryOpKind.Ge => SyntaxNodeKind.GeToken.size
case BinaryOpKind.Gt => SyntaxNodeKind.GtToken.size
case BinaryOpKind.Le => SyntaxNodeKind.LeToken.size
case BinaryOpKind.LShift => SyntaxNodeKind.LShiftToken.size
case BinaryOpKind.Lt => SyntaxNodeKind.LtToken.size
case BinaryOpKind.Mod => SyntaxNodeKind.ModToken.size
case BinaryOpKind.Mul => SyntaxNodeKind.MulToken.size
case BinaryOpKind.NotEq => SyntaxNodeKind.NotEqToken.size
case BinaryOpKind.Or => SyntaxNodeKind.OrToken.size
case BinaryOpKind.Pipeline => SyntaxNodeKind.PipelineToken.size
case BinaryOpKind.RShift => SyntaxNodeKind.RShiftToken.size
case BinaryOpKind.Sub => SyntaxNodeKind.SubToken.size
case _ => 0
}
return CodePositionRange(posInfos.opPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, opKInd_: BinaryOpKind,
posInfos: BinaryExprPosInfos, propInfos: BinaryExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.opKInd_ = opKInd_
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with left expr, operator and right expr.
*/
public init(lhs: Expr, opKind: BinaryOpKind, rhs: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createBinaryExprImpl(lhs, opKind, rhs, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<BinaryExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
this.opKInd_ = opKind
}
public prop lhs: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.lhsPropInfo.index]
let offset = propInfos.lhsPropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
public prop opKind: BinaryOpKind {
get() {
opKInd_
}
}
public prop rhs: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.rhsPropInfo)
}
}
}
/**
* @brief Represents a break expression used to exit loops.
*/
public class BreakExpr <: Expr {
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
}
/**
* @brief Initialize node.
*/
public init(comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createBreakExprImpl(comments: comments))
}
}
class CallExprPropInfos {
let calleePropInfo: PropInfo
let argumentPropInfo: Array<PropInfo>
init(calleePropInfo: PropInfo, argumentPropInfo: Array<PropInfo>) {
this.calleePropInfo = calleePropInfo
this.argumentPropInfo = argumentPropInfo
}
}
class CallExprPosInfos {
let lParenPos: CodePosition
let rParenPos: CodePosition
let commasPos: Array<CodePosition>
init(lParenPos: CodePosition, rParenPos: CodePosition, commasPos: Array<CodePosition>) {
this.lParenPos = lParenPos
this.rParenPos = rParenPos
this.commasPos = commasPos
}
}
/**
* @brief Represents a function call expression.
*
* The CallExpr class is a subclass of Expr and is used to model function call expressions.
* It contains an array of arguments and a callee expression representing the function
* to be called.
*/
public class CallExpr <: Expr {
private let startPos: CodePosition
private let propInfos: CallExprPropInfos
private let posInfos: CallExprPosInfos
/**
* @brief Gets the position range of the left parenthesis in the code.
*
* @return A CodePositionRange representing the position range of the left parenthesis.
*/
public func getLParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.lParenPos, SyntaxNodeKind.LParenToken.size)
}
/**
* @brief Gets the position range of the right parenthesis in the code.
*
* @return A CodePositionRange representing the position range of the right parenthesis.
*/
public func getRParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.rParenPos, SyntaxNodeKind.RParenToken.size)
}
/**
* @brief Gets the position ranges of the commas in the arguments.
*
* @return An Array of PositionRange representing the position ranges of the commas.
*/
public func getCommasPos(): Array<CodePositionRange> {
return createExprTokenRanges(posInfos.commasPos, SyntaxNodeKind.CommaToken.size)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: CallExprPosInfos,
propInfos: CallExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with callee and arguments.
*/
public init(callee: Expr, arguments: Array<Argument>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createCallExprImpl(callee, arguments, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<CallExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
public prop arguments: Array<Argument> {
get() {
let arguments = ArrayList<Argument>()
for (propInfo in propInfos.argumentPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
arguments.add(
cast<Argument>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow())
}
arguments.toArray()
}
}
public prop callee: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.calleePropInfo.index]
let offset = propInfos.calleePropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class CatchPatternPropInfos {
let exceptionTypePropInfo: Array<PropInfo>
let patternPropInfo: PropInfo
init(exceptionTypePropInfo: Array<PropInfo>, patternPropInfo: PropInfo) {
this.exceptionTypePropInfo = exceptionTypePropInfo
this.patternPropInfo = patternPropInfo
}
}
class CatchPatternPosInfos {
let colonPos: Option<CodePosition>
let bitOrsPos: Array<CodePosition>
init(colonPos: Option<CodePosition>, bitOrsPos: Array<CodePosition>) {
this.colonPos = colonPos
this.bitOrsPos = bitOrsPos
}
}
/**
* @brief Represents a catch pattern in a try-catch expression.
* It defines the exception types and pattern used for matching.
*/
public class CatchPattern <: SyntaxTreeNode {
private let startPos: CodePosition
private let propInfos: CatchPatternPropInfos
private let posInfos: CatchPatternPosInfos
/**
* @brief Get the position of the colon.
*
* @return Option<CodePositionRange> representing the position of the colon.
*/
public func getColonPos(): Option<CodePositionRange> {
if (let Some(v) <- posInfos.colonPos) {
return (CodePositionRange(v, v + SyntaxNodeKind.ColonToken.size))
}
None
}
/**
* @brief Get the positions of bitwise 'or' operators in the code.
*
* @return Array<CodePositionRange> containing the positions of bitwise 'or' operators.
*/
public func getBitOrsPos(): Array<CodePositionRange> {
let bitOrsPos = ArrayList<CodePositionRange>()
for (bitOr in posInfos.bitOrsPos) {
bitOrsPos.add(CodePositionRange(bitOr, bitOr + SyntaxNodeKind.BitOrToken.size))
}
return bitOrsPos.toArray()
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: CatchPatternPosInfos,
propInfos: CatchPatternPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with exception types and pattern.
*/
public init(pattern: Pattern, exceptionType: Array<TypeAnnotation>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createCatchPatternImpl(pattern, exceptionType, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<CatchPattern>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The array of exception types that this catch pattern handles.
*/
public prop exceptionType: Array<TypeAnnotation> {
get() {
let types = ArrayList<TypeAnnotation>()
for (propInfo in propInfos.exceptionTypePropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
types.add(
cast<TypeAnnotation>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this))
.getOrThrow())
}
types.toArray()
}
}
/**
* @brief The pattern used for matching exceptions.
*/
public prop pattern: Pattern {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.patternPropInfo.index]
let offset = propInfos.patternPropInfo.offset
cast<Pattern>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class ConjunctionConditionPropInfos {
let condPropInfo: Array<PropInfo>
init(condPropInfo: Array<PropInfo>) {
this.condPropInfo = condPropInfo
}
}
class ConjunctionConditionPosInfos {
let andsPos: Array<CodePosition>
init(andsPos: Array<CodePosition>) {
this.andsPos = andsPos
}
}
/**
* @brief Represents a logical conjunction (AND) of atomic conditions.
*
* This class aggregates multiple atomic conditions that must all evaluate to true
* for the conjunction to be satisfied. It models a logical AND operation between
* its constituent atomic conditions.
*/
public class ConjunctionCondition <: SyntaxTreeNode {
private let startPos: CodePosition
private let propInfos: ConjunctionConditionPropInfos
private let posInfos: ConjunctionConditionPosInfos
/**
* @brief Retrieves the positions of 'AND' operators in the conjunction.
* @return An array of CodePositionRange objects for each 'AND' operator.
*/
public func getAndsPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.andsPos.size) {
let endPos = posInfos.andsPos[i] + SyntaxNodeKind.AndToken.size
ret.add(CodePositionRange(posInfos.andsPos[i], endPos))
}
ret.toArray()
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
posInfos: ConjunctionConditionPosInfos, propInfos: ConjunctionConditionPropInfos,
commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with conditions.
*/
public init(cond: Array<AtomicCondition>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createConjunctionConditionImpl(cond, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<ConjunctionCondition>(SyntaxNodeImplTranslator.translate(curNode, startPos, None))
.getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The array of atomic conditions in this conjunction.
*
* This member holds the list of AtomicConditions that are AND'ed together.
* For the entire conjunction to evaluate to true, all of these atomic conditions
* must individually evaluate to true.
*
* The array is immutable once initialized, ensuring the logical structure
* remains constant during evaluation. An empty array will result in the
* conjunction evaluating to true (vacuous truth).
*/
public prop cond: Array<AtomicCondition> {
get() {
let conds = ArrayList<AtomicCondition>()
for (propInfo in propInfos.condPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
let translateNode = SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)
if (let Some(target) <- cast<LetPattern>(translateNode)) {
conds.add(LetPatternCondition(target))
} else if (let Some(target) <- cast<ParenCondition>(translateNode)) {
conds.add(ParenConditionConstructor(target))
} else if (let Some(target) <- cast<Expr>(translateNode)) {
conds.add(Expression(target))
}
}
conds.toArray()
}
}
}
/**
* @brief Represents a continue expression used to skip to the next iteration of a loop.
*/
public class ContinueExpr <: Expr {
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
}
/**
* @brief Initialize node.
*/
public init(comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createContinueExprImpl(comments: comments))
}
}
class DisjunctionConditionPropInfos {
let condPropInfo: Array<PropInfo>
init(condPropInfo: Array<PropInfo>) {
this.condPropInfo = condPropInfo
}
}
class DisjunctionConditionPosInfos {
let orsPos: Array<CodePosition>
init(orsPos: Array<CodePosition>) {
this.orsPos = orsPos
}
}
/**
* @brief Represents a logical disjunction (OR) of conjunction conditions.
*
* This class aggregates multiple conjunction conditions where at least one must evaluate
* to true for the disjunction to be satisfied. It models a logical OR operation between
* its constituent conjunctions, forming a logical expression in disjunctive normal form (DNF).
*/
public class DisjunctionCondition <: SyntaxTreeNode {
private let startPos: CodePosition
private let propInfos: DisjunctionConditionPropInfos
private let posInfos: DisjunctionConditionPosInfos
/**
* @brief Get position ranges of all '||' (or) tokens.
* @return Array of ranges covering each '||' token in source order.
*/
public func getOrsPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.orsPos.size) {
let endPos = posInfos.orsPos[i] + SyntaxNodeKind.OrToken.size
ret.add(CodePositionRange(posInfos.orsPos[i], endPos))
}
ret.toArray()
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
posInfos: DisjunctionConditionPosInfos, propInfos: DisjunctionConditionPropInfos,
commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with conditions.
*/
public init(cond: Array<ConjunctionCondition>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createDisjunctionConditionImpl(cond, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<DisjunctionCondition>(SyntaxNodeImplTranslator.translate(curNode, startPos, None))
.getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The array of conjunction conditions in this disjunction.
*
* This member holds the list of ConjunctionConditions that are OR'ed together.
* For the entire disjunction to evaluate to true, at least one of these
* conjunction conditions must evaluate to true.
*
* The array is immutable once initialized, ensuring the logical structure
* remains constant during evaluation.
*/
public prop cond: Array<ConjunctionCondition> {
get() {
let conds = ArrayList<ConjunctionCondition>()
for (propInfo in propInfos.condPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
conds.add(
cast<ConjunctionCondition>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this))
.getOrThrow())
}
conds.toArray()
}
}
}
class DoWhileExprPosInfos {
let condLParenPos: CodePosition
let condRParenPos: CodePosition
let doKeyWordPos: CodePosition
let whileKeyWordPos: CodePosition
init(condLParenPos: CodePosition, condRParenPos: CodePosition, doKeyWordPos: CodePosition,
whileKeyWordPos: CodePosition) {
this.condLParenPos = condLParenPos
this.condRParenPos = condRParenPos
this.doKeyWordPos = doKeyWordPos
this.whileKeyWordPos = whileKeyWordPos
}
}
class DoWhileExprPropInfos {
let bodyPropInfo: PropInfo
let conditionPropInfo: PropInfo
init(bodyPropInfo: PropInfo, conditionPropInfo: PropInfo) {
this.bodyPropInfo = bodyPropInfo
this.conditionPropInfo = conditionPropInfo
}
}
/**
* @brief Represents a do-while loop expression.
* It consists of a loop body and a continuation condition.
*/
public class DoWhileExpr <: Expr {
private let startPos: CodePosition
private let propInfos: DoWhileExprPropInfos
private let posInfos: DoWhileExprPosInfos
/**
* @brief Get the position range of the 'do' keyword.
*/
public func getDoKeyWordPos(): CodePositionRange {
let endPos = posInfos.doKeyWordPos + SyntaxNodeKind.DoToken.size
CodePositionRange(posInfos.doKeyWordPos, endPos)
}
/**
* @brief Get the position range of the 'while' keyword.
*/
public func getWhileKeyWordPos(): CodePositionRange {
return createExprTokenRange(posInfos.whileKeyWordPos, SyntaxNodeKind.WhileToken.size)
}
/**
* @brief Get the position range of the left parenthesis in the condition.
*/
public func getCondLParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.condLParenPos, SyntaxNodeKind.LParenToken.size)
}
/**
* @brief Get the position range of the right parenthesis in the condition.
*/
public func getCondRParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.condRParenPos, SyntaxNodeKind.RParenToken.size)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: DoWhileExprPosInfos,
propInfos: DoWhileExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new DoWhileExpr node.
*/
public init(body: Block, condition: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createDoWhileExprImpl(body, condition, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<DoWhileExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The body of the loop as a block of code.
*/
public prop body: Block {
get() {
return translateExprChild<Block>(nodeImpl, startPos, this, propInfos.bodyPropInfo)
}
}
/**
* @brief The loop continuation condition as an expression.
*/
public prop condition: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.conditionPropInfo.index]
let offset = propInfos.conditionPropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class ForInExprPosInfos {
let forKeyWordPos: CodePosition
let inKeyWordPos: CodePosition
let lParenPos: CodePosition
let rParenPos: CodePosition
let whereKeyWordPos: Option<CodePosition>
init(forKeyWordPos: CodePosition, inKeyWordPos: CodePosition, lParenPos: CodePosition, rParenPos: CodePosition,
whereKeyWordPos: Option<CodePosition>) {
this.forKeyWordPos = forKeyWordPos
this.inKeyWordPos = inKeyWordPos
this.lParenPos = lParenPos
this.rParenPos = rParenPos
this.whereKeyWordPos = whereKeyWordPos
}
}
class ForInExprPropInfos {
let bodyPropInfo: PropInfo
let exprPropInfo: PropInfo
let patternPropInfo: PropInfo
let patternGuardPropInfo: Option<PropInfo>
init(bodyPropInfo: PropInfo, exprPropInfo: PropInfo, patternPropInfo: PropInfo,
patternGuardPropInfo: Option<PropInfo>) {
this.bodyPropInfo = bodyPropInfo
this.exprPropInfo = exprPropInfo
this.patternPropInfo = patternPropInfo
this.patternGuardPropInfo = patternGuardPropInfo
}
}
/**
* @brief Represents a for-in loop expression.
* It iterates over a collection using a specified pattern.
*/
public class ForInExpr <: Expr {
private let startPos: CodePosition
private let posInfos: ForInExprPosInfos
private let propInfos: ForInExprPropInfos
/**
* @brief Get the position range of the 'for' keyword.
*/
public func getForKeyWordPos(): CodePositionRange {
let endPos = posInfos.forKeyWordPos + SyntaxNodeKind.ForToken.size
CodePositionRange(posInfos.forKeyWordPos, endPos)
}
/**
* @brief Get the position range of the 'in' keyword.
*/
public func getInKeyWordPos(): CodePositionRange {
let endPos = posInfos.inKeyWordPos + SyntaxNodeKind.InToken.size
CodePositionRange(posInfos.inKeyWordPos, endPos)
}
/**
* @brief Get the position range of the 'where' keyword if present.
*/
public func getWhereKeyWordPos(): Option<CodePositionRange> {
if (let Some(v) <- posInfos.whereKeyWordPos) {
let endPos = v + SyntaxNodeKind.WhereToken.size
return CodePositionRange(v, endPos)
}
return None
}
/**
* @brief Get the position range of the left parenthesis.
*/
public func getLParenPos(): CodePositionRange {
let endPos = posInfos.lParenPos + SyntaxNodeKind.LParenToken.size
CodePositionRange(posInfos.lParenPos, endPos)
}
/**
* @brief Get the position range of the right parenthesis.
*/
public func getRParenPos(): CodePositionRange {
let endPos = posInfos.rParenPos + SyntaxNodeKind.RParenToken.size
CodePositionRange(posInfos.rParenPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: ForInExprPosInfos,
propInfos: ForInExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with loop body, range expr, iterator pattern and condition expr.
*/
public init(body: Block, expr: Expr, pattern: Pattern, patternGuard: Option<Expr>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createForInExprImpl(body, expr, pattern, patternGuard, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<ForInExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The body of the loop as a block of code.
*/
public prop body: Block {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.bodyPropInfo.index]
let offset = propInfos.bodyPropInfo.offset
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief The expression representing the collection to iterate over.
*/
public prop expr: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.exprPropInfo.index]
let offset = propInfos.exprPropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief The pattern used for destructuring the iterated values.
*/
public prop pattern: Pattern {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.patternPropInfo.index]
let offset = propInfos.patternPropInfo.offset
cast<Pattern>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief An optional guard expression for the pattern.
*/
public prop patternGuard: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.patternGuardPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
}
class IfExprPosInfos {
let ifKeyWordPos: CodePosition
let condLParenPos: CodePosition
let condRParenPos: CodePosition
let elseKeyWordPos: Option<CodePosition>
init(ifKeyWordPos: CodePosition, condLParenPos: CodePosition, condRParenPos: CodePosition,
elseKeyWordPos: Option<CodePosition>) {
this.ifKeyWordPos = ifKeyWordPos
this.condLParenPos = condLParenPos
this.condRParenPos = condRParenPos
this.elseKeyWordPos = elseKeyWordPos
}
}
class IfExprPropInfos {
let conditionPropInfo: PropInfo
let elseBlockPropInfo: Option<PropInfo>
let elseIfPropInfo: Option<PropInfo>
let ifBlockPropInfo: PropInfo
init(conditionPropInfo: PropInfo, elseBlockPropInfo: Option<PropInfo>, elseIfPropInfo: Option<PropInfo>,
ifBlockPropInfo: PropInfo) {
this.conditionPropInfo = conditionPropInfo
this.elseBlockPropInfo = elseBlockPropInfo
this.elseIfPropInfo = elseIfPropInfo
this.ifBlockPropInfo = ifBlockPropInfo
}
}
/**
* @brief Represents an if expression.
* It consists of a condition, optional else-if, and else blocks.
*/
public class IfExpr <: Expr {
private let startPos: CodePosition
private let propInfos: IfExprPropInfos
private let posInfos: IfExprPosInfos
/**
* @brief Get position range of 'if' keyword.
* @return Range covering the 'if' token.
*/
public func getIfKeyWordPos(): CodePositionRange {
let endPos = posInfos.ifKeyWordPos + SyntaxNodeKind.IfToken.size
CodePositionRange(posInfos.ifKeyWordPos, endPos)
}
/**
* @brief Get position range of left parenthesis for condition.
* @return Range covering the condition's left parenthesis.
*/
public func getCondLParenPos(): CodePositionRange {
let endPos = posInfos.condLParenPos + SyntaxNodeKind.LParenToken.size
CodePositionRange(posInfos.condLParenPos, endPos)
}
/**
* @brief Get position range of right parenthesis for condition.
* @return Range covering the condition's right parenthesis.
*/
public func getCondRParenPos(): CodePositionRange {
let endPos = posInfos.condRParenPos + SyntaxNodeKind.RParenToken.size
CodePositionRange(posInfos.condRParenPos, endPos)
}
/**
* @brief Get position range of 'else' keyword if present.
* @return Optional range covering the 'else' token.
*/
public func getElseKeyWordPos(): Option<CodePositionRange> {
if (let Some(v) <- posInfos.elseKeyWordPos) {
let endPos = v + SyntaxNodeKind.ElseToken.size
return CodePositionRange(v, endPos)
}
return None
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: IfExprPosInfos,
propInfos: IfExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new IfExpr node.
*/
public init(condition: DisjunctionCondition, elseBlock: Option<Block>, elseIf: Option<IfExpr>, ifBlock: Block,
comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createIfExprImpl(condition, elseBlock, elseIf, ifBlock, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<IfExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The condition of the if statement.
*/
public prop condition: DisjunctionCondition {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.conditionPropInfo.index]
let offset = propInfos.conditionPropInfo.offset
cast<DisjunctionCondition>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this))
.getOrThrow()
}
}
/**
* @brief The optional else block.
*/
public prop elseBlock: Option<Block> {
get() {
if (let Some(propInfo) <- propInfos.elseBlockPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief The optional else-if expression.
*/
public prop elseIf: Option<IfExpr> {
get() {
if (let Some(propInfo) <- propInfos.elseIfPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<IfExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief The block of code executed if the condition is true.
*/
public prop ifBlock: Block {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.ifBlockPropInfo.index]
let offset = propInfos.ifBlockPropInfo.offset
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
/**
* @brief Enumeration for increment or decrement operation kinds.
*
* The IncOrDecOpKind enumeration represents two types of operations:
* decrement (Decr) and increment (Incr).
*/
public enum IncOrDecOpKind {
| Decr
| Incr
| ...
}
class IncOrDecExprPropInfos {
let operandPropInfo: PropInfo
init(operandPropInfo: PropInfo) {
this.operandPropInfo = operandPropInfo
}
}
class IncOrDecExprPosInfos {
let opPos: CodePosition
init(opPos: CodePosition) {
this.opPos = opPos
}
}
/**
* @brief Represents an increment or decrement expression.
*
* The IncOrDecExpr class is a subclass of Expr and is used to model increment or
* decrement expressions. It contains an operation kind (kind) and an operand
* expression (operand).
*/
public class IncOrDecExpr <: Expr {
private let kind_: IncOrDecOpKind
private let startPos: CodePosition
private let propInfos: IncOrDecExprPropInfos
private let posInfos: IncOrDecExprPosInfos
/**
* @brief Retrieves the position range of the operator in the code.
*
* @return The position range of the operator.
*/
public func getOperatorPos(): CodePositionRange {
let endPos = posInfos.opPos + SyntaxNodeKind.IncrToken.size
return CodePositionRange(posInfos.opPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, kind_: IncOrDecOpKind,
posInfos: IncOrDecExprPosInfos, propInfos: IncOrDecExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.kind_ = kind_
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with operand and operator.
*/
public init(kind: IncOrDecOpKind, operand: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createIncOrDecExprImpl(kind, operand, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<IncOrDecExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
this.kind_ = kind
}
/**
* @brief Type of increment or decrement operation.
*
* This member variable stores the kind of operation specified by the
* IncOrDecOpKind enumeration, which can be either Decr (decrement) or Incr (increment).
*/
public prop kind: IncOrDecOpKind {
get() {
kind_
}
}
/**
* @brief Expression to be incremented or decremented.
*
* This member variable stores the operand expression that will be affected by
* the increment or decrement operation.
*/
public prop operand: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.operandPropInfo)
}
}
}
class IsExprPropInfos {
let srcValPropInfo: PropInfo
let targetTypeAnnotationPropInfo: PropInfo
init(srcValPropInfo: PropInfo, targetTypeAnnotationPropInfo: PropInfo) {
this.srcValPropInfo = srcValPropInfo
this.targetTypeAnnotationPropInfo = targetTypeAnnotationPropInfo
}
}
class IsExprPosInfos {
let isKeyWordPos: CodePosition
init(isKeyWordPos: CodePosition) {
this.isKeyWordPos = isKeyWordPos
}
}
/**
* @brief Represents an 'is' expression.
*
* The IsExpr class is a subclass of Expr and is used to model 'is' expressions.
* It contains a source value expression (srcVal) and a target type annotation
* (targetTypeAnnotation) to check the type of the source value.
*/
public class IsExpr <: Expr {
private let startPos: CodePosition
private let propInfos: IsExprPropInfos
private let posInfos: IsExprPosInfos
/**
* @brief Retrieves the position range of the 'is' keyword.
*
* @return The position range representing the start and end positions of the 'is' keyword.
*/
public func getIsKeyWordPos(): CodePositionRange {
let endPos = posInfos.isKeyWordPos + SyntaxNodeKind.IsToken.size
return CodePositionRange(posInfos.isKeyWordPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfo: IsExprPosInfos,
propInfo: IsExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfo
this.propInfos = propInfo
}
/**
* @brief Initialize node with source value and target type.
*/
public init(srcVal: Expr, targetTypeAnnotation: TypeAnnotation, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createIsExprImpl(srcVal, targetTypeAnnotation, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<IsExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief Source value expression.
*
* This member variable stores the expression representing the source value that
* will be checked against the target type.
*/
public prop srcVal: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.srcValPropInfo)
}
}
/**
* @brief Target type annotation.
*
* This member variable stores the type annotation representing the target type
* that the source value will be checked against.
*/
public prop targetTypeAnnotation: TypeAnnotation {
get() {
return translateExprChild<TypeAnnotation>(nodeImpl, startPos, this,
propInfos.targetTypeAnnotationPropInfo)
}
}
}
class LambdaPropInfos {
let bodyPropInfo: Option<PropInfo>
let paramsPropInfo: PropInfo
init(bodyPropInfo: Option<PropInfo>, paramsPropInfo: PropInfo) {
this.bodyPropInfo = bodyPropInfo
this.paramsPropInfo = paramsPropInfo
}
}
class LambdaPosInfos {
let lCurlPos: CodePosition
let rCurlPos: CodePosition
let doubleArrowPos: Option<CodePosition>
init(lCurlPos: CodePosition, rCurlPos: CodePosition, doubleArrowPos: Option<CodePosition>) {
this.lCurlPos = lCurlPos
this.rCurlPos = rCurlPos
this.doubleArrowPos = doubleArrowPos
}
}
/**
* @brief Represents a lambda function expression.
* It consists of a body and parameters.
*/
public class Lambda <: Expr {
private let startPos: CodePosition
private let propInfos: LambdaPropInfos
private let posInfos: LambdaPosInfos
/**
* @brief Gets the position range of the left curly brace in the lambda.
*
* @return A CodePositionRange representing the position range of the left curly brace.
*/
public func getLCurlPos(): CodePositionRange {
let endPos = posInfos.lCurlPos + SyntaxNodeKind.LCurlToken.size
return CodePositionRange(posInfos.lCurlPos, endPos)
}
/**
* @brief Gets the position range of the right curly brace in the lambda.
*
* @return A CodePositionRange representing the position range of the right curly brace.
*/
public func getRCurlPos(): CodePositionRange {
let endPos = posInfos.rCurlPos + SyntaxNodeKind.RCurlToken.size
return CodePositionRange(posInfos.rCurlPos, endPos)
}
/**
* @brief Gets the position range of the double arrow in thelambda.
*
* @return An Option of CodePositionRange representing the position range of the double arrow, if present.
*/
public func getDoubleArrowPos(): Option<CodePositionRange> {
if (let Some(doubleArrowPos) <- posInfos.doubleArrowPos) {
let endPos = doubleArrowPos + SyntaxNodeKind.DoubleArrowToken.size
return CodePositionRange(doubleArrowPos, endPos)
} else {
return None
}
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: LambdaPosInfos,
propInfos: LambdaPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new Lambda node.
*/
public init(body: Array<SyntaxTreeNode>, params: ParameterList, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createLambdaImpl(body, params, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<Lambda>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The body of the lambda as an array of syntax tree nodes.
*/
public prop body: Array<SyntaxTreeNode> {
get() {
let body = ArrayList<SyntaxTreeNode>()
if (let Some(propInfo) <- propInfos.bodyPropInfo) {
let lp = LocalParser((nodeImpl as NonTerminal).getOrThrow().children, propInfo.offset,
index: propInfo.index)
let predictExprOrDecl = {
kind: SyntaxNodeKind => kind.isExpr() || kind.isDecl()
}
while (lp.look(predictExprOrDecl)) {
if (let Some(node) <- lp.consume()) {
body.add(
cast<SyntaxTreeNode>(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this))
.getOrThrow())
lp.moveOffset(node)
}
}
}
body.toArray()
}
}
/**
* @brief The parameters of the lambda as an array of function parameters.
*/
public prop params: ParameterList {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.paramsPropInfo.index]
let offset = propInfos.paramsPropInfo.offset
cast<ParameterList>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class LetPatternPropInfo {
let exprPropInfo: PropInfo
let patternsPropInfo: Array<PropInfo>
init(exprPropInfo: PropInfo, patternsPropInfo: Array<PropInfo>) {
this.exprPropInfo = exprPropInfo
this.patternsPropInfo = patternsPropInfo
}
}
class LetPatternPosInfo {
let letKeyWordPos: CodePosition
let bitOrsPos: Array<CodePosition>
let backArrowPos: CodePosition
init(letKeyWordPos: CodePosition, bitOrsPos: Array<CodePosition>, backArrowPos: CodePosition) {
this.letKeyWordPos = letKeyWordPos
this.bitOrsPos = bitOrsPos
this.backArrowPos = backArrowPos
}
}
/**
* @brief Represents a let pattern binding expression.
* It binds a value (expr) to a pattern for destructuring.
*/
public class LetPattern <: SyntaxTreeNode {
private let startPos: CodePosition
private let propInfos: LetPatternPropInfo
private let posInfos: LetPatternPosInfo
/**
* @brief Retrieves the position of the 'LET' token.
* @return A CodePositionRange object representing the 'LET' token's position.
*/
public func getLetKeyWordPos(): CodePositionRange {
let endPos = posInfos.letKeyWordPos + SyntaxNodeKind.LetToken.size
CodePositionRange(posInfos.letKeyWordPos, endPos)
}
/**
* @brief Retrieves the positions of all 'BIT_OR' tokens.
* @return An array of CodePositionRange objects for each 'BIT_OR' token.
*/
public func getBitOrsPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.bitOrsPos.size) {
let endPos = posInfos.bitOrsPos[i] + SyntaxNodeKind.BitOrToken.size
ret.add(CodePositionRange(posInfos.bitOrsPos[i], endPos))
}
ret.toArray()
}
/**
* @brief Retrieves the position of the 'BACK_ARROW' token.
* @return A CodePositionRange object representing the 'BACK_ARROW' token's position.
*/
public func getBackArrowPos(): CodePositionRange {
let endPos = posInfos.backArrowPos + SyntaxNodeKind.BackArrowToken.size
CodePositionRange(posInfos.backArrowPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: LetPatternPosInfo,
propInfos: LetPatternPropInfo, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with source expr and patterns.
*/
public init(expr: Expr, patterns: Array<Pattern>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createLetPatternImpl(expr, patterns, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<LetPattern>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The expression whose value is to be bound to the pattern.
*/
public prop expr: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.exprPropInfo.index]
let offset = propInfos.exprPropInfo.offset
// might be SymbolRef or MemberAccess
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief The patterns to which the expression's value is bound.
*/
public prop patterns: Array<Pattern> {
get() {
let pats = ArrayList<Pattern>()
for (propInfo in propInfos.patternsPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
pats.add(cast<Pattern>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this))
.getOrThrow())
}
pats.toArray()
}
}
}
/**
* @brief Enumeration for different kinds of literal constants.
*
* The LitConstKind enumeration defines various types of literal constants used
* in expressions. Each kind specifies a particular type of literal value.
*/
public enum LitConstKind {
| BoolLiteral
| FloatLiteral
| IntergerLiteral
| RuneLiteral
| StringLiteral
| UnitLiteral
| ...
}
/**
* @brief Represents a literal constant expression.
*
* The LitConstExpr class is a subclass of Expr and is used to model literal
* constant expressions. It contains a kind specifying the type of literal
* constant and a raw value storing the actual value as a string.
*/
public open class LitConstExpr <: Expr {
private let startPos: CodePosition
private let kind_: LitConstKind
private let rawValue_: String
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, kind_: LitConstKind,
rawValue_: String, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.kind_ = kind_
this.rawValue_ = rawValue_
}
init(nodeImpl: SyntaxNodeImpl, kind_: LitConstKind, rawValue_: String, hasComment!: Bool = true) {
super(nodeImpl, hasComment: hasComment)
this.startPos = DEFAULT_START_POS
this.kind_ = kind_
this.rawValue_ = rawValue_
}
/**
* @brief Initialize a new LitConstExpr node.
*/
public init(kind: LitConstKind, rawValue: String, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createLitConstExprImpl(kind, rawValue, comments: comments))
let startPos = DEFAULT_START_POS
this.startPos = startPos
this.kind_ = kind
this.rawValue_ = rawValue
}
/**
* @brief Type of literal constant.
*
* This member variable stores the kind of literal constant specified by the
* LitConstKind enumeration.
*/
public prop kind: LitConstKind {
get() {
kind_
}
}
/**
* @brief Actual value of the literal constant.
*
* This member variable stores the actual value of the literal constant as a string.
*/
public prop rawValue: String {
get() {
rawValue_
}
}
}
/**
* @brief Represents a literal constant rune expression.
*
* The LitConstRuneExpr class is a subclass of Expr and is used to model literal
* constant rune expressions. It contains information about whether the literal
* is enclosed in single quotes, a kind specifying the type of literal constant
* rune, and a raw value storing the actual value as a string.
*/
public class LitConstRuneExpr <: LitConstExpr {
private let startPos: CodePosition
private let isSingleQuote_: Bool
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, rawValue_: String,
isSingleQuote_: Bool, commentsPropInfo: Array<PropInfo>) {
super(nodeImpl, startPos, parentNode, LitConstKind.RuneLiteral, rawValue_, commentsPropInfo)
this.startPos = startPos
this.isSingleQuote_ = isSingleQuote_
}
/**
* @brief Initialize a new LitConstRuneExpr node.
*/
public init(kind: LitConstKind, rawValue: String, isSingleQuote: Bool, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createLitConstRuneExprImpl(kind, rawValue, isSingleQuote, comments: comments), kind,
rawValue)
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<LitConstRuneExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.isSingleQuote_ = isSingleQuote
}
/**
* @brief Indicates whether the literal is enclosed in single quotes.
*
* This member variable stores a boolean value indicating whether the literal
* constant rune is enclosed in single quotes.
*/
public prop isSingleQuote: Bool {
get() {
isSingleQuote_
}
}
}
/**
* @brief Enumeration for different kinds of literal constant strings.
*
* The LitConstStrKind enumeration defines various types of literal constant
* strings used in expressions. Each kind specifies a particular type of string
* literal value.
*/
public enum LitConstStrKind {
| JStringLiteral
| MultiLineString
| MultiLineRawString
| StringLiteral
| ...
}
/**
* @brief Enumeration for different parts of a string literal.
*
* The StrLiteralPart enumeration defines the components that can make up a
* string literal. Each part can either be a literal constant part
* (LitConstPart) or an interpolation part (StrInterpolation).
*/
public enum StrLiteralPart {
| LitConstPart(LitConstExpr)
| StrInterpolation(StrInterpolationContent)
| ...
}
class LitConstStrExprPropInfos {
let strPartExprsPropInfo: PropInfo
init(strPartExprsPropInfo: PropInfo) {
this.strPartExprsPropInfo = strPartExprsPropInfo
}
}
/**
* @brief Represents a literal constant string expression.
*
* The LitConstStrExpr class is a subclass of Expr and is used to model literal
* constant string expressions. It contains information about the number of
* delimiters, whether the string is enclosed in single quotes, a kind
* specifying the type of literal constant string, a raw value storing the
* actual value as a string, and an array of string literal parts that make up
* the string.
*/
public class LitConstStrExpr <: LitConstExpr {
private let startPos: CodePosition
private let delimiterNum_: Int64
private let isSingleQuote_: Bool
private let strKind_: LitConstStrKind
private let propInfos: LitConstStrExprPropInfos
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, delimiterNum_: Int64,
isSingleQuote_: Bool, rawValue_: String, strKind_: LitConstStrKind, propInfos: LitConstStrExprPropInfos,
commentsPropInfo: Array<PropInfo>) {
super(nodeImpl, startPos, parentNode, LitConstKind.StringLiteral, rawValue_, commentsPropInfo)
this.startPos = startPos
this.delimiterNum_ = delimiterNum_
this.isSingleQuote_ = isSingleQuote_
this.strKind_ = strKind_
this.propInfos = propInfos
}
/**
* @brief Initialize a new LitConstStrExpr node.
*/
public init(kind: LitConstKind, rawValue: String, delimiterNum: Int64, isSingleQuote: Bool,
strKind: LitConstStrKind, strPartExprs: Array<StrLiteralPart>, comments!: Array<Comment> = []) {
super(
SyntaxNodeImplCreator.createLitConstStrExprImpl(kind, rawValue, delimiterNum, isSingleQuote, strKind,
strPartExprs, comments: comments), kind, rawValue)
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<LitConstStrExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.delimiterNum_ = delimiterNum
this.isSingleQuote_ = isSingleQuote
this.strKind_ = strKind
this.propInfos = redNode.propInfos
}
/**
* @brief Determines whether the object contains interpolation.
*
* @return true if the object contains interpolation, false otherwise.
*/
public func hasInterpolation(): Bool {
let strPartExpr = strPartExprs
for (i in 0..strPartExpr.size) {
match (strPartExpr[i]) {
case StrInterpolation(_) => return true
case _ => ()
}
}
return false
}
/**
* @brief Number of delimiters in the string.
* This member variable stores the number of delimiters used in the string
* literal constant.
*/
public prop delimiterNum: Int64 {
get() {
delimiterNum_
}
}
/**
* @brief Indicates whether the string is enclosed in single quotes.
* This member variable stores a boolean value indicating whether the string
* literal constant is enclosed in single quotes.
*/
public prop isSingleQuote: Bool {
get() {
isSingleQuote_
}
}
/**
* @brief Type of literal constant string.
* This member variable stores the kind of literal constant string specified by
* the LitConstStrKind enumeration.
*/
public prop strKind: LitConstStrKind {
get() {
strKind_
}
}
/**
* @brief Array of string literal parts.
* This member variable stores an array of StrLiteralPart objects that make up
* the string literal constant.
*/
public prop strPartExprs: Array<StrLiteralPart> {
get() {
let strPartExprs_ = ArrayList<StrLiteralPart>()
let lp = LocalParser((nodeImpl as NonTerminal).getOrThrow().children, propInfos.strPartExprsPropInfo.offset,
index: propInfos.strPartExprsPropInfo.index)
while (!lp.isEnd()) {
var impl = lp.consume().getOrThrow()
var currentPos = startPos + lp.offset
match (impl.kind) {
case SyntaxNodeKind.InterpolationExpr =>
if (let Some(interpol) <- cast<StrInterpolationContent>(
SyntaxNodeImplTranslator.translate(impl, startPos + lp.offset, this))) {
strPartExprs_.add(StrInterpolation(interpol))
}
case SyntaxNodeKind.LineStringLiteral | SyntaxNodeKind.MultiLineStringLiteral
| SyntaxNodeKind.MultiLineRawStringLiteral =>
if (let Some(litConst) <- cast<LitConstExpr>(
SyntaxNodeImplTranslator.translate(impl, startPos + lp.offset, this))) {
strPartExprs_.add(LitConstPart(litConst))
}
case _ => break
}
lp.offset.move(impl.offset)
}
strPartExprs_.toArray()
}
}
}
class MatchCasePropInfos {
let bodyPropInfo: PropInfo
let caseCondPropInfo: Option<PropInfo>
let patternGuardCondPropInfo: Option<PropInfo>
let patternsPropInfo: Array<PropInfo>
init(bodyPropInfo: PropInfo, caseCondPropInfo: Option<PropInfo>, patternGuardCondPropInfo: Option<PropInfo>,
patternsPropInfo: Array<PropInfo>) {
this.bodyPropInfo = bodyPropInfo
this.caseCondPropInfo = caseCondPropInfo
this.patternGuardCondPropInfo = patternGuardCondPropInfo
this.patternsPropInfo = patternsPropInfo
}
}
class MatchCasePosInfos {
let casePos: CodePosition
let bitOrsPos: Array<CodePosition>
let wherePos: Option<CodePosition>
let doubleArrowPos: CodePosition
init(casePos: CodePosition, bitOrsPos: Array<CodePosition>, wherePos: Option<CodePosition>,
doubleArrowPos: CodePosition) {
this.casePos = casePos
this.bitOrsPos = bitOrsPos
this.wherePos = wherePos
this.doubleArrowPos = doubleArrowPos
}
}
/**
* @brief Represents a match case in a match expression.
* It defines the patterns, conditions, and body for a match case.
*/
public class MatchCase <: SyntaxTreeNode {
private let startPos: CodePosition
private let propInfos: MatchCasePropInfos
private let posInfos: MatchCasePosInfos
/**
* @brief Gets the position range of the 'case' keyword in the code.
*
* @return A CodePositionRange representing the position range of the 'case' keyword.
*/
public func getCasePos(): CodePositionRange {
let endPos = posInfos.casePos + SyntaxNodeKind.CaseToken.size
return CodePositionRange(posInfos.casePos, endPos)
}
/**
* @brief Gets the position ranges of the bitwise OR operators in the code.
*
* @return An Array of CodePositionRange representing the position ranges of the bitwise OR operators.
*/
public func getBitOrsPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.bitOrsPos.size) {
let endPos = posInfos.bitOrsPos[i] + SyntaxNodeKind.BitOrToken.size
ret.add(CodePositionRange(posInfos.bitOrsPos[i], endPos))
}
ret.toArray()
}
/**
* @brief Gets the position range of the 'where' keyword in the code.
*
* @return An Option of CodePositionRange representing the position range of the 'where' keyword, if present.
*/
public func getWherePos(): Option<CodePositionRange> {
if (let Some(wherePos) <- posInfos.wherePos) {
let endPos = wherePos + SyntaxNodeKind.WhereToken.size
return CodePositionRange(wherePos, endPos)
}
return None
}
/**
* @brief Gets the position range of the double arrow (=>) in the code.
*
* @return A CodePositionRange representing the position range of the double arrow (=>).
*/
public func getDoubleArrowPos(): CodePositionRange {
let endPos = posInfos.doubleArrowPos + SyntaxNodeKind.DoubleArrowToken.size
return CodePositionRange(posInfos.doubleArrowPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: MatchCasePosInfos,
propInfos: MatchCasePropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with body, case condition, pattern guard condition and pattern.
*/
public init(patterns: Array<Pattern>, patternGuardCond: Option<Expr>, caseCond: Option<Expr>,
body: Array<SyntaxTreeNode>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createMatchCaseImpl(patterns, patternGuardCond, caseCond, body, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<MatchCase>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The body of the match case as an array of syntax tree nodes.
*/
public prop body: Array<SyntaxTreeNode> {
get() {
let bodys = ArrayList<SyntaxTreeNode>()
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.bodyPropInfo.index]
let offset = propInfos.bodyPropInfo.offset
let lp = LocalParser((curNode as NonTerminal).getOrThrow().children, offset)
while (!lp.isEnd()) {
if (let Some(node) <- lp.tryConsume()) {
bodys.add(
cast<SyntaxTreeNode>(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this))
.getOrThrow())
lp.moveOffset(node)
}
}
bodys.toArray()
}
}
/**
* @brief The optional condition for the match case.
*/
public prop caseCond: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.caseCondPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief The optional pattern guard condition.
*/
public prop patternGuardCond: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.patternGuardCondPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief The array of patterns for the match case.
*/
public prop patterns: Array<Pattern> {
get() {
let arguments = ArrayList<Pattern>()
for (propInfo in propInfos.patternsPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
arguments.add(
cast<Pattern>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow())
}
arguments.toArray()
}
}
}
class MatchExprPropInfos {
let matchCasesPropInfo: Array<PropInfo>
let selectorPropInfo: Option<PropInfo>
init(matchCasesPropInfo: Array<PropInfo>, selectorPropInfo: Option<PropInfo>) {
this.matchCasesPropInfo = matchCasesPropInfo
this.selectorPropInfo = selectorPropInfo
}
}
class MatchExprPosInfos {
let matchKeyWordPos: CodePosition
let selectorLParenPos: Option<CodePosition>
let selectorRParenPos: Option<CodePosition>
let matchCasesLCurlPos: CodePosition
let matchCasesRCurlPos: CodePosition
init(matchKeyWordPos: CodePosition, selectorLParenPos: Option<CodePosition>,
selectorRParenPos: Option<CodePosition>, matchCasesLCurlPos: CodePosition, matchCasesRCurlPos: CodePosition) {
this.matchKeyWordPos = matchKeyWordPos
this.selectorLParenPos = selectorLParenPos
this.selectorRParenPos = selectorRParenPos
this.matchCasesLCurlPos = matchCasesLCurlPos
this.matchCasesRCurlPos = matchCasesRCurlPos
}
}
/**
* @brief Represents a match expression.
* It matches a selector against multiple patterns.
*/
public class MatchExpr <: Expr {
private let startPos: CodePosition
private let propInfos: MatchExprPropInfos
private let posInfos: MatchExprPosInfos
/**
* @brief Gets the position range of the 'match' keyword in the code.
*
* @return A CodePositionRange representing the position range of the 'match' keyword.
*/
public func getMatchKeyWordPos(): CodePositionRange {
let endPos = posInfos.matchKeyWordPos + SyntaxNodeKind.MatchToken.size
return CodePositionRange(posInfos.matchKeyWordPos, endPos)
}
/**
* @brief Gets the position range of the left parenthesis in the selector in the code.
*
* @return An Option of CodePositionRange representing the position range of the left parenthesis in the selector, if present.
*/
public func getSelectorLParenPos(): Option<CodePositionRange> {
if (let Some(selectorLParenPos) <- posInfos.selectorLParenPos) {
let endPos = selectorLParenPos + SyntaxNodeKind.LParenToken.size
return CodePositionRange(selectorLParenPos, endPos)
}
return None
}
/**
* @brief Gets the position range of the right parenthesis in the selector in the code.
*
* @return An Option of CodePositionRange representing the position range of the right parenthesis in the selector, if present.
*/
public func getSelectorRParenPos(): Option<CodePositionRange> {
if (let Some(selectorRParenPos) <- posInfos.selectorRParenPos) {
let endPos = selectorRParenPos + SyntaxNodeKind.RParenToken.size
return CodePositionRange(selectorRParenPos, endPos)
}
return None
}
/**
* @brief Gets the position range of the left curly brace in the match cases in the code.
*
* @return A CodePositionRange representing the position range of the left curly brace in the match cases.
*/
public func getMatchCasesLCurlPos(): CodePositionRange {
let endPos = posInfos.matchCasesLCurlPos + SyntaxNodeKind.LCurlToken.size
return CodePositionRange(posInfos.matchCasesLCurlPos, endPos)
}
/**
* @brief Gets the position range of the right curly brace in the match cases in the code.
*
* @return A CodePositionRange representing the position range of the right curly brace in the match cases.
*/
public func getMatchCasesRCurlPos(): CodePositionRange {
let endPos = posInfos.matchCasesRCurlPos + SyntaxNodeKind.RCurlToken.size
return CodePositionRange(posInfos.matchCasesRCurlPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: MatchExprPosInfos,
propInfos: MatchExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new MatchExpr node.
*/
public init(matchCases: Array<MatchCase>, selector: Option<Expr>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createMatchExprImpl(matchCases, selector, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<MatchExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The cases of the match expression.
*/
public prop matchCases: Array<MatchCase> {
get() {
let matchCases = ArrayList<MatchCase>()
for (propInfo in propInfos.matchCasesPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
matchCases.add(
cast<MatchCase>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow())
}
matchCases.toArray()
}
}
/**
* @brief The optional selector expression.
*/
public prop selector: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.selectorPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
}
class MemberAccessPropInfos {
let basePropInfo: PropInfo
let fieldPropInfo: PropInfo
init(basePropInfo: PropInfo, fieldPropInfo: PropInfo) {
this.basePropInfo = basePropInfo
this.fieldPropInfo = fieldPropInfo
}
}
class MemberAccessPosInfos {
let dotPos: CodePosition
init(dotPos: CodePosition) {
this.dotPos = dotPos
}
}
/**
* @brief Represents a member access expression.
* It accesses a field of a base expression.
*/
public class MemberAccess <: Expr {
private let startPos: CodePosition
private let propInfos: MemberAccessPropInfos
private let posInfos: MemberAccessPosInfos
/**
* @brief Gets the position range of the dot in the code.
*
* @return A CodePositionRange representing the position range of the dot.
*/
public func getDotPos(): CodePositionRange {
let endPos = posInfos.dotPos + SyntaxNodeKind.DotToken.size
return CodePositionRange(posInfos.dotPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: MemberAccessPosInfos,
propInfos: MemberAccessPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new MemberAccess node.
*/
public init(base: SyntaxTreeNode, field: SymbolRef, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createMemberAccessImpl(base, field, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<MemberAccess>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The base expression.
*/
public prop base: SyntaxTreeNode {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.basePropInfo.index]
let offset = propInfos.basePropInfo.offset
cast<SyntaxTreeNode>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief The field being accessed as a reference expression.
*/
public prop field: SymbolRef {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.fieldPropInfo.index]
let offset = propInfos.fieldPropInfo.offset
cast<SymbolRef>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class OptionalExprPropInfos {
let basePropInfo: PropInfo
init(basePropInfo: PropInfo) {
this.basePropInfo = basePropInfo
}
}
class OptionalExprPosInfos {
let questionPos: CodePosition
init(questonPos: CodePosition) {
this.questionPos = questonPos
}
}
/**
* @brief Represents an optional expression.
* The OptionalExpr class is a subclass of Expr and is used to model optional
* expressions. It contains a base expression that may be optional.
*/
public class OptionalExpr <: Expr {
private let startPos: CodePosition
private let propInfos: OptionalExprPropInfos
private let posInfos: OptionalExprPosInfos
/**
* @brief Retrieves the position range of the question mark in the code.
*
* @return The position range of the question mark.
*/
public func getQuestionPos(): CodePositionRange {
let endPos = posInfos.questionPos + SyntaxNodeKind.QuestToken.size
return CodePositionRange(posInfos.questionPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: OptionalExprPosInfos,
propInfos: OptionalExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new OptionalExpr node.
*/
public init(base: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createOptionalExprImpl(base, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<OptionalExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief Base expression that may be optional.
* This member variable stores the base expression which can be made optional
* by this OptionalExpr.
*/
public prop base: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.basePropInfo)
}
}
}
class ParenConditionPropInfo {
let condPropInfo: PropInfo
init(condPropInfo: PropInfo) {
this.condPropInfo = condPropInfo
}
}
class ParenConditionPosInfo {
let lParenPos: CodePosition
let rParenPos: CodePosition
init(lParenPos: CodePosition, rParenPos: CodePosition) {
this.lParenPos = lParenPos
this.rParenPos = rParenPos
}
}
/**
* @brief Represents a parenthesized logical condition in an expression.
*
* This class encapsulates a disjunction condition within parentheses,
* which can be used to override the default precedence of logical operators
* and enforce a specific evaluation order in boolean expressions.
*/
public class ParenCondition <: SyntaxTreeNode {
private let startPos: CodePosition
private let propInfos: ParenConditionPropInfo
private let posInfos: ParenConditionPosInfo
/**
* @brief Get position range of left parenthesis.
* @return Range covering the left parenthesis token.
*/
public func getLParenPos(): CodePositionRange {
let endPos = posInfos.lParenPos + SyntaxNodeKind.LParenToken.size
CodePositionRange(posInfos.lParenPos, endPos)
}
/**
* @brief Get position range of right parenthesis.
* @return Range covering the right parenthesis token.
*/
public func getRParenPos(): CodePositionRange {
let endPos = posInfos.rParenPos + SyntaxNodeKind.RParenToken.size
CodePositionRange(posInfos.rParenPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: ParenConditionPosInfo,
propInfos: ParenConditionPropInfo, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with conditions.
*/
public init(cond: DisjunctionCondition, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createParenConditionImpl(cond, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<ParenCondition>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The disjunction condition enclosed in parentheses.
*
* This member holds the logical disjunction (OR) condition that is
* wrapped in parentheses. The parentheses indicate that this condition
* should be evaluated as a single unit before being combined with other
* logical expressions.
*/
public prop cond: DisjunctionCondition {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.condPropInfo.index]
let offset = propInfos.condPropInfo.offset
cast<DisjunctionCondition>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this))
.getOrThrow()
}
}
}
class ParenExprPropInfos {
let subExprPropInfo: PropInfo
init(subExprPropInfo: PropInfo) {
this.subExprPropInfo = subExprPropInfo
}
}
class ParenExprPosInfos {
let lParenPos: CodePosition
let rParenPos: CodePosition
init(lParenPos: CodePosition, rParenPos: CodePosition) {
this.lParenPos = lParenPos
this.rParenPos = rParenPos
}
}
/**
* @brief Represents an expression enclosed in parentheses.
*
* The ParenExpr class is a subclass of Expr and is used to model expressions
* that are enclosed in parentheses. It contains a value representing the
* expression inside the parentheses.
*/
public class ParenExpr <: Expr {
private let startPos: CodePosition
private let propInfos: ParenExprPropInfos
private let posInfos: ParenExprPosInfos
/**
* @brief Retrieves the position range of the left parenthesis.
*
* @return The CodePositionRange representing the left parenthesis.
*/
public func getLParenPos(): CodePositionRange {
let endPos = posInfos.lParenPos + SyntaxNodeKind.LParenToken.size
return CodePositionRange(posInfos.lParenPos, endPos)
}
/**
* @brief Retrieves the position range of the right parenthesis.
*
* @return The CodePositionRange representing the right parenthesis.
*/
public func getRParenPos(): CodePositionRange {
let endPos = posInfos.rParenPos + SyntaxNodeKind.RParenToken.size
return CodePositionRange(posInfos.rParenPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfo: ParenExprPosInfos,
propInfo: ParenExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfo
this.propInfos = propInfo
}
/**
* @brief Initialize node with expr in the parentheses.
*/
public init(subExpr: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createParenExprImpl(subExpr, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<ParenExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief Expression enclosed within parentheses.
*
* This member variable stores the expression that is enclosed within
* parentheses.
*/
public prop subExpr: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.subExprPropInfo.index]
let offset = propInfos.subExprPropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
/**
* @brief Enumeration for different kinds of ranges.
*
* The RangeKind enumeration defines various types of ranges used in
* expressions. Each kind specifies a particular type of range, such as
* exclusive or inclusive.
*/
public enum RangeKind {
| ClosedRangeOp
| RangeOp
| ...
}
class RangeExprPropInfos {
let startPropInfo: Option<PropInfo>
let stepPropInfo: Option<PropInfo>
let endPropInfo: Option<PropInfo>
init(startPropInfo: Option<PropInfo>, stepPropInfo: Option<PropInfo>, endPropInfo: Option<PropInfo>) {
this.startPropInfo = startPropInfo
this.stepPropInfo = stepPropInfo
this.endPropInfo = endPropInfo
}
}
class RangeExprPosInfos {
let rangeOpPos: CodePosition
let colonPos: Option<CodePosition>
init(rangeOpPos: CodePosition, colonPos: Option<CodePosition>) {
this.rangeOpPos = rangeOpPos
this.colonPos = colonPos
}
}
/**
* @brief Represents a range expression.
*
* The RangeExpr class is a subclass of Expr and is used to model range
* expressions. It contains a start expression, an end expression, a step
* expression, and a kind specifying the type of range (e.g., exclusive or
* inclusive).
*/
public class RangeExpr <: Expr {
private let kind_: RangeKind
private let startPos: CodePosition
private let propInfos: RangeExprPropInfos
private let posInfos: RangeExprPosInfos
/**
* @brief Retrieves the position range of the range operator.
*
* @return A CodePositionRange representing the start and end positions of the range operator.
*/
public func getRangeOpPos(): CodePositionRange {
let endPos = posInfos.rangeOpPos + match (kind) {
case RangeKind.ClosedRangeOp => SyntaxNodeKind.ClosedRangeOpToken.size
case RangeKind.RangeOp => SyntaxNodeKind.RangeOpToken.size
case _ => 0
}
return CodePositionRange(posInfos.rangeOpPos, endPos)
}
/**
* @brief Retrieves the position of the colon, if it exists.
*
* @return An Option containing a CodePositionRange of the colon's position, or None if not present.
*/
public func getColonPos(): Option<CodePositionRange> {
match (posInfos.colonPos) {
case Some(v) =>
let endPos = v + SyntaxNodeKind.ColonToken.size
CodePositionRange(v, endPos)
case _ => None
}
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, kind_: RangeKind,
posInfo: RangeExprPosInfos, propInfo: RangeExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.kind_ = kind_
this.startPos = startPos
this.posInfos = posInfo
this.propInfos = propInfo
}
/**
* @brief Initialize node with range start, kind, end and range step.
*/
public init(start: Option<Expr>, kind: RangeKind, end: Option<Expr>, step: Option<Expr>,
comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createRangeExprImpl(start, kind, end, step, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<RangeExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
this.kind_ = kind
}
/**
* @brief Optional end expression of the range.
*
* This member variable stores the optional end expression of the range.
* If the end is not specified, this will be None.
*/
public prop end: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.endPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief Type of range (e.g., exclusive or inclusive).
*
* This member variable stores the kind of range specified by the RangeKind
* enumeration.
*/
public prop kind: RangeKind {
get() {
kind_
}
}
/**
* @brief Optional start expression of the range.
*
* This member variable stores the optional start expression of the range.
* If the start is not specified, this will be None.
*/
public prop start: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.startPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief Optional step expression for the range.
*
* This member variable stores the optional step expression for the range.
* If the step is not specified, this will be None.
*/
public prop step: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.stepPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
}
class ReturnExprPropInfos {
let retValPropInfo: Option<PropInfo>
init(retValPropInfo: Option<PropInfo>) {
this.retValPropInfo = retValPropInfo
}
}
class ReturnExprPosInfos {
let returnKeyWordPos: CodePosition
init(returnKeyWordPos: CodePosition) {
this.returnKeyWordPos = returnKeyWordPos
}
}
/**
* @brief Represents a return expression.
* It returns a value from a function.
*/
public class ReturnExpr <: Expr {
private let startPos: CodePosition
private let propInfos: ReturnExprPropInfos
private let posInfos: ReturnExprPosInfos
/**
* @brief Retrieves the position range of the return keyword in the code.
*
* @return CodePositionRange representing the start and end positions of the return keyword.
*/
public func getReturnKeyWordPos(): CodePositionRange {
let endPos = posInfos.returnKeyWordPos + SyntaxNodeKind.ReturnToken.size
return CodePositionRange(posInfos.returnKeyWordPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: ReturnExprPosInfos,
propInfos: ReturnExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with the returned value.
*/
public init(retVal: Option<Expr>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createReturnExprImpl(retVal, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<ReturnExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief The expression being returned, optional.
*/
public prop retVal: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.retValPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
}
class SpawnExprPosInfos {
let spawnKeyWordPos: CodePosition
let threadContextLParenPos: Option<CodePosition>
let threadContextRParenPos: Option<CodePosition>
init(spawnKeyWordPos: CodePosition, threadContextLParenPos: Option<CodePosition>,
threadContextRParenPos: Option<CodePosition>) {
this.spawnKeyWordPos = spawnKeyWordPos
this.threadContextLParenPos = threadContextLParenPos
this.threadContextRParenPos = threadContextRParenPos
}
}
class SpawnExprPropInfos {
let threadContextPropInfo: Option<PropInfo>
let trailingLambdaExprPropInfo: PropInfo
init(threadContextPropInfo: Option<PropInfo>, trailingLambdaExprPropInfo: PropInfo) {
this.threadContextPropInfo = threadContextPropInfo
this.trailingLambdaExprPropInfo = trailingLambdaExprPropInfo
}
}
/**
* @brief Represents a spawn expression for creating threads.
* It consists of a thread context and a lambda expression.
*/
public class SpawnExpr <: Expr {
private let startPos: CodePosition
private let posInfos: SpawnExprPosInfos
private let propInfos: SpawnExprPropInfos
/**
* @brief Get the position range of the 'spawn' keyword.
*/
public func getSpawnKeyWordPos(): CodePositionRange {
let endPos = posInfos.spawnKeyWordPos + SyntaxNodeKind.SpawnToken.size
CodePositionRange(posInfos.spawnKeyWordPos, endPos)
}
/**
* @brief Get the position range of the left parenthesis for thread context.
*/
public func getThreadContextLParenPos(): Option<CodePositionRange> {
if (let Some(v) <- posInfos.threadContextLParenPos) {
let endPos = v + SyntaxNodeKind.LParenToken.size
return CodePositionRange(v, endPos)
}
return None
}
/**
* @brief Get the position range of the right parenthesis for thread context.
*/
public func getThreadContextRParenPos(): Option<CodePositionRange> {
if (let Some(v) <- posInfos.threadContextRParenPos) {
let endPos = v + SyntaxNodeKind.RParenToken.size
return CodePositionRange(v, endPos)
}
return None
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: SpawnExprPosInfos,
propInfos: SpawnExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new SpawnExpr node.
*/
public init(threadContext: Option<Expr>, trailingLambdaExpr: Lambda, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createSpawnExprImpl(threadContext, trailingLambdaExpr, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<SpawnExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The optional thread context expression.
*/
public prop threadContext: Option<Expr> {
get() {
if (let Some(propInfo) <- propInfos.threadContextPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief The lambda expression representing the thread's code.
*/
public prop trailingLambdaExpr: Lambda {
get() {
return translateExprChild<Lambda>(nodeImpl, startPos, this, propInfos.trailingLambdaExprPropInfo)
}
}
}
class StrInterpolationContentPosInfos {
let dollarPos: CodePosition
init(dollarPos: CodePosition) {
this.dollarPos = dollarPos
}
}
class StrInterpolationContentPropInfos {
let interpolationBlockPropInfo: PropInfo
init(interpolationBlockPropInfo: PropInfo) {
this.interpolationBlockPropInfo = interpolationBlockPropInfo
}
}
/**
* @brief Represents the content of a string interpolation block.
*
* The StrInterpolationContent class is a subclass of SyntaxTreeNode and is
* used to model the content of a string interpolation block. It contains an
* interpolation block which is a piece of code executed within the string
* interpolation.
*/
public class StrInterpolationContent <: SyntaxTreeNode {
private let startPos: CodePosition
private let posInfos: StrInterpolationContentPosInfos
private let propInfos: StrInterpolationContentPropInfos
public func getDollarPos(): CodePositionRange {
let endPos = posInfos.dollarPos + SyntaxNodeKind.DollarToken.size
return CodePositionRange(posInfos.dollarPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
posInfos: StrInterpolationContentPosInfos, propInfos: StrInterpolationContentPropInfos,
commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with interpolation block.
*/
public init(interpolationBlock: Block, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createStrInterpolationContentImpl(interpolationBlock, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<StrInterpolationContent>(SyntaxNodeImplTranslator.translate(curNode, startPos, None))
.getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief Block of code within the string interpolation.
* This member variable stores the block of code that is executed as part of
* the string interpolation.
*/
public prop interpolationBlock: Block {
get() {
let propInfo = propInfos.interpolationBlockPropInfo
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + propInfo.offset, this)).getOrThrow()
}
}
}
class SubscriptExprPropInfos {
let basePropInfo: PropInfo
let indexsPropInfo: PropInfo
init(basePropInfo: PropInfo, indexsPropInfo: PropInfo) {
this.basePropInfo = basePropInfo
this.indexsPropInfo = indexsPropInfo
}
}
class SubscriptExprPosInfos {
let lSquarePos: CodePosition
let rSquarePos: CodePosition
let commasPos: Array<CodePosition>
init(lSquarePos: CodePosition, rSquarePos: CodePosition, commasPos: Array<CodePosition>) {
this.lSquarePos = lSquarePos
this.rSquarePos = rSquarePos
this.commasPos = commasPos
}
}
/**
* @brief Represents a subscript expression for accessing array elements.
* It consists of a base expression and index expressions.
*/
public class SubscriptExpr <: Expr {
private let startPos: CodePosition
private let posInfos: SubscriptExprPosInfos
private let propInfos: SubscriptExprPropInfos
/**
* @brief Gets the position range of the left square bracket in the SubacriptExpr.
*
* @return A CodePositionRange representing the position range of the left square bracket.
*/
public func getLSquarePos(): CodePositionRange {
return createExprTokenRange(posInfos.lSquarePos, SyntaxNodeKind.LSquareToken.size)
}
/**
* @brief Gets the position range of the right square bracket in the SubacriptExpr.
*
* @return A CodePositionRange representing the position range of the right square bracket.
*/
public func getRSquarePos(): CodePositionRange {
return createExprTokenRange(posInfos.rSquarePos, SyntaxNodeKind.RSquareToken.size)
}
/**
* @brief Gets the position ranges of the commas in the SubacriptExpr.
*
* @return An Array of PositionRange representing the position ranges of the commas.
*/
public func getCommasPos(): Array<CodePositionRange> {
return createExprTokenRanges(posInfos.commasPos, SyntaxNodeKind.CommaToken.size)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: SubscriptExprPosInfos,
propInfos: SubscriptExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new SubscriptExpr node.
*/
public init(base: Expr, indexs: Array<Expr>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createSubscriptExprImpl(base, indexs, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<SubscriptExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The base expression.
*/
public prop base: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.basePropInfo)
}
}
/**
* @brief The array of index expressions.
*/
public prop indexs: Array<Expr> {
get() {
let indexs = ArrayList<Expr>()
let lp = LocalParser((nodeImpl as NonTerminal).getOrThrow().children, propInfos.indexsPropInfo.offset,
index: propInfos.indexsPropInfo.index)
let predictExpr = {
kind: SyntaxNodeKind => kind.isExpr()
}
while (lp.look(predictExpr)) {
if (let Some(node) <- lp.consume()) {
indexs.add(
cast<Expr>(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this)).getOrThrow())
lp.moveOffset(node)
}
if (lp.look(SyntaxNodeKind.CommaToken)) {
lp.moveOffset(lp.consume())
}
}
indexs.toArray()
}
}
}
class SymbolRefPropInfos {
let typeArgumentsPropInfo: Option<PropInfo>
init(typeArgumentsPropInfo: Option<PropInfo>) {
this.typeArgumentsPropInfo = typeArgumentsPropInfo
}
}
class SymbolRefPosInfos {
let identifierPos: CodePosition
let lAnglePos: Option<CodePosition>
let rAnglePos: Option<CodePosition>
let commasPos: Array<CodePosition>
init(identifierPos: CodePosition, lAnglePos: Option<CodePosition>, rAnglePos: Option<CodePosition>,
commasPos: Array<CodePosition>) {
this.identifierPos = identifierPos
this.lAnglePos = lAnglePos
this.rAnglePos = rAnglePos
this.commasPos = commasPos
}
}
/**
* @brief Represents a reference to a symbol.
*
* The SymbolRef class is a subclass of Expr and is used to model references to
* symbols. It contains a name representing the symbol being referenced and an
* array of type annotations for the symbol reference.
*/
public class SymbolRef <: Expr {
private let name_: String
private let startPos: CodePosition
private let propInfos: SymbolRefPropInfos
private let posInfos: SymbolRefPosInfos
/**
* @brief Gets the position range of the identifier in the code.
*
* @return A CodePositionRange representing the position range of the identifier.
*/
public func getIdentifierPos(): CodePositionRange {
let endPos = posInfos.identifierPos + name.size
return CodePositionRange(posInfos.identifierPos, endPos)
}
/**
* @brief Gets the position range of the left angle bracket in the code.
*
* @return An Option of CodePositionRange representing the position range of the left angle bracket, if present.
*/
public func getLAnglePos(): Option<CodePositionRange> {
if (let Some(lAnglePos) <- posInfos.lAnglePos) {
let endPos = lAnglePos + SyntaxNodeKind.LtToken.size
return CodePositionRange(lAnglePos, endPos)
}
return None
}
/**
* @brief Gets the position range of the right angle bracket in the code.
*
* @return An Option of CodePositionRange representing the position range of the right angle bracket, if present.
*/
public func getRAnglePos(): Option<CodePositionRange> {
if (let Some(rAnglePos) <- posInfos.rAnglePos) {
let endPos = rAnglePos + SyntaxNodeKind.GtToken.size
return CodePositionRange(rAnglePos, endPos)
}
return None
}
/**
* @brief Gets the position ranges of the commas in the code.
*
* @return An Array of PositionRange representing the position ranges of the commas.
*/
public func getCommasPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.commasPos.size) {
let endPos = posInfos.commasPos[i] + SyntaxNodeKind.CommaToken.size
ret.add(CodePositionRange(posInfos.commasPos[i], endPos))
}
ret.toArray()
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, name_: String,
posInfos: SymbolRefPosInfos, propInfos: SymbolRefPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.name_ = name_
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new SymbolRef node.
*/
public init(name: String, typeArguments: Array<TypeAnnotation>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createSymbolRefImpl(name, typeArguments, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<SymbolRef>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.name_ = name
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief Name of the symbol being referenced.
*
* This member variable stores the name of the symbol that is being referenced.
*/
public prop name: String {
get() {
name_
}
}
/**
* @brief Type annotations for the SymbolRef reference.
*
* This member variable stores an array of TypeAnnotation objects that specify
* the types associated with the SymbolRef reference.
*/
public prop typeArguments: Array<TypeAnnotation> {
get() {
let typeArguments = ArrayList<TypeAnnotation>()
if (let Some(propInfo) <- propInfos.typeArgumentsPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
let lp = LocalParser((curNode as NonTerminal).getOrThrow().children, offset)
if (lp.look(SyntaxNodeKind.LtToken)) {
lp.offset.move(lp.consume()?.offset)
}
let predictType = {
kind: SyntaxNodeKind => kind.isTypeAnnotation()
}
while (lp.look(predictType)) {
var node = lp.consume().getOrThrow()
typeArguments.add(
cast<TypeAnnotation>(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this))
.getOrThrow())
lp.offset.move(node.offset)
if (lp.look(SyntaxNodeKind.CommaToken)) {
lp.offset.move(lp.consume()?.offset)
}
}
}
typeArguments.toArray()
}
}
}
class SynchronizedExprPosInfos {
let lParenPos: CodePosition
let rParenPos: CodePosition
let synchronizedKeyWordPos: CodePosition
init(lParenPos: CodePosition, rParenPos: CodePosition, synchronizedKeyWordPos: CodePosition) {
this.lParenPos = lParenPos
this.rParenPos = rParenPos
this.synchronizedKeyWordPos = synchronizedKeyWordPos
}
}
class SynchronizedExprPropInfos {
let blockPropInfo: PropInfo
let structuredMutexPropInfo: PropInfo
init(blockPropInfo: PropInfo, structuredMutexPropInfo: PropInfo) {
this.blockPropInfo = blockPropInfo
this.structuredMutexPropInfo = structuredMutexPropInfo
}
}
/**
* @brief Represents a synchronized expression for thread synchronization.
* It consists of a block of code and a mutex expression.
*/
public class SynchronizedExpr <: Expr {
private let startPos: CodePosition
private let propInfos: SynchronizedExprPropInfos
private let posInfos: SynchronizedExprPosInfos
/**
* @brief Get position range of 'synchronized' keyword.
* @return Range covering the 'synchronized' token.
*/
public func getSynchronizedKeyWordPos(): CodePositionRange {
let endPos = posInfos.synchronizedKeyWordPos + SyntaxNodeKind.SynchronizedToken.size
CodePositionRange(posInfos.synchronizedKeyWordPos, endPos)
}
/**
* @brief Get position range of left parenthesis.
* @return Range covering the left parenthesis token.
*/
public func getLParenPos(): CodePositionRange {
let endPos = posInfos.lParenPos + SyntaxNodeKind.LParenToken.size
CodePositionRange(posInfos.lParenPos, endPos)
}
/**
* @brief Get position range of right parenthesis.
* @return Range covering the right parenthesis token.
*/
public func getRParenPos(): CodePositionRange {
let endPos = posInfos.rParenPos + SyntaxNodeKind.RParenToken.size
CodePositionRange(posInfos.rParenPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
posInfos: SynchronizedExprPosInfos, propInfos: SynchronizedExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new SynchronizedExpr node.
*/
public init(block: Block, structuredMutex: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createSynchronizedExprImpl(block, structuredMutex, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<SynchronizedExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The block of code to be synchronized.
*/
public prop block: Block {
get() {
return translateExprChild<Block>(nodeImpl, startPos, this, propInfos.blockPropInfo)
}
}
/**
* @brief The expression representing the mutex.
*/
public prop structuredMutex: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.structuredMutexPropInfo.index]
let offset = propInfos.structuredMutexPropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class ThrowExprPropInfos {
let throwValPropInfo: PropInfo
init(throwValPropInfo: PropInfo) {
this.throwValPropInfo = throwValPropInfo
}
}
class ThrowExprPosInfos {
let throwKeyWordPos: CodePosition
init(throwKeyWordPos: CodePosition) {
this.throwKeyWordPos = throwKeyWordPos
}
}
/**
* @brief Represents a throw expression for throwing exceptions.
* It consists of a value to throw.
*/
public class ThrowExpr <: Expr {
private let startPos: CodePosition
private let propInfos: ThrowExprPropInfos
private let posInfos: ThrowExprPosInfos
/**
* @brief Gets the position range of the 'throw' keyword in the code.
*
* @return A PositionRange representing the position range of the 'throw' keyword.
*/
public func getThrowKeyWordPos(): CodePositionRange {
let endPos = posInfos.throwKeyWordPos + SyntaxNodeKind.ThrowToken.size
return CodePositionRange(posInfos.throwKeyWordPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: ThrowExprPosInfos,
propInfos: ThrowExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new ThrowExpr node.
*/
public init(throwVal: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createThrowExprImpl(throwVal, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<ThrowExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The expression representing the value to throw.
*/
public prop throwVal: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.throwValPropInfo.index]
let offset = propInfos.throwValPropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class TrailingClosureExprPosInfos {
let commasPos: Array<CodePosition>
let lParenPos: Option<CodePosition>
let rParenPos: Option<CodePosition>
init(commasPos: Array<CodePosition>, lParenPos: Option<CodePosition>, rParenPos: Option<CodePosition>) {
this.commasPos = commasPos
this.lParenPos = lParenPos
this.rParenPos = rParenPos
}
}
class TrailingClosureExprPropInfos {
let argumentsPropInfo: PropInfo
let calleePropInfo: PropInfo
let trailingLambdaExprPropInfo: PropInfo
init(argumentsPropInfo: PropInfo, calleePropInfo: PropInfo, trailingLambdaExprPropInfo: PropInfo) {
this.argumentsPropInfo = argumentsPropInfo
this.calleePropInfo = calleePropInfo
this.trailingLambdaExprPropInfo = trailingLambdaExprPropInfo
}
}
/**
* @brief Represents a trailing closure expression.
* It consists of a prefix expression which is MemberAccess or SymbolRef,
* arguments, and a trailing lambda expression.
*/
public class TrailingClosureExpr <: Expr {
private let startPos: CodePosition
private let propInfos: TrailingClosureExprPropInfos
private let posInfos: TrailingClosureExprPosInfos
/**
* @brief Gets the position ranges of the commas in the arguments in the code.
*
* @return An Array of CodePositionRange representing the position ranges of the commas in the arguments.
*/
public func getCommasPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.commasPos.size) {
let endPos = posInfos.commasPos[i] + SyntaxNodeKind.CommaToken.size
ret.add(CodePositionRange(posInfos.commasPos[i], endPos))
}
ret.toArray()
}
/**
* @brief Gets the position range of the left parenthesis in the code if present.
*
* @return Option<CodePositionRange> representing the position range of the left parenthesis.
*/
public func getLParenPos(): Option<CodePositionRange> {
if (let Some(lParenPos) <- posInfos.lParenPos) {
let endPos = lParenPos + SyntaxNodeKind.LParenToken.size
return CodePositionRange(lParenPos, endPos)
}
return None
}
/**
* @brief Gets the position range of the right parenthesis in the code if present.
*
* @return Option<CodePositionRange> representing the position range of the right parenthesis.
*/
public func getRParenPos(): Option<CodePositionRange> {
if (let Some(rParenPos) <- posInfos.rParenPos) {
let endPos = rParenPos + SyntaxNodeKind.RParenToken.size
return CodePositionRange(rParenPos, endPos)
}
return None
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode,
posInfos: TrailingClosureExprPosInfos, propInfos: TrailingClosureExprPropInfos,
commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with callee, arguments and trailing lambda expr.
*/
public init(callee: Expr, arguments: Array<Argument>, trailingLambdaExpr: Lambda, comments!: Array<Comment> = []) {
super(
SyntaxNodeImplCreator.createTrailingClosureExprImpl(callee, arguments, trailingLambdaExpr,
comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<TrailingClosureExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None))
.getOrThrow()
this.startPos = startPos
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
}
/**
* @brief The list of arguments passed to the expression.
*/
public prop arguments: Array<Argument> {
get() {
let args = ArrayList<Argument>()
let lp = LocalParser((nodeImpl as NonTerminal).getOrThrow().children, propInfos.argumentsPropInfo.offset,
index: propInfos.argumentsPropInfo.index)
while (lp.look(SyntaxNodeKind.Argument)) {
if (let Some(node) <- lp.consume()) {
args.add(
cast<Argument>(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this))
.getOrThrow())
lp.moveOffset(node)
}
if (lp.look(SyntaxNodeKind.CommaToken)) {
lp.moveOffset(lp.consume())
}
}
args.toArray()
}
}
/**
* @brief The callee that the trailing closure is associated with.
*/
public prop callee: Expr {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.calleePropInfo.index]
let offset = propInfos.calleePropInfo.offset
cast<Expr>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief The lambda expression that acts as the trailing closure.
*/
public prop trailingLambdaExpr: Lambda {
get() {
return translateExprChild<Lambda>(nodeImpl, startPos, this, propInfos.trailingLambdaExprPropInfo)
}
}
}
class TryExprPosInfos {
let tryKeyWordPos: CodePosition
let resourceSpecLParenPos: Option<CodePosition>
let resourceSpecCommasPos: Array<CodePosition>
let resourceSpecRParenPos: Option<CodePosition>
let catchKeyWordsPos: Array<CodePosition>
let catchLParensPos: Array<CodePosition>
let catchRParensPos: Array<CodePosition>
let finallyKeyWordPos: Option<CodePosition>
init(tryKeyWordPos: CodePosition, resourceSpecLParenPos: Option<CodePosition>,
resourceSpecCommasPos: Array<CodePosition>, resourceSpecRParenPos: Option<CodePosition>,
catchKeyWordsPos: Array<CodePosition>, catchLParensPos: Array<CodePosition>,
catchRParensPos: Array<CodePosition>, finallyKeyWordPos: Option<CodePosition>) {
this.tryKeyWordPos = tryKeyWordPos
this.resourceSpecLParenPos = resourceSpecLParenPos
this.resourceSpecCommasPos = resourceSpecCommasPos
this.resourceSpecRParenPos = resourceSpecRParenPos
this.catchKeyWordsPos = catchKeyWordsPos
this.catchLParensPos = catchLParensPos
this.catchRParensPos = catchRParensPos
this.finallyKeyWordPos = finallyKeyWordPos
}
}
class TryExprPropInfos {
let catchBlocksPropInfo: Array<PropInfo>
let catchPatternsPropInfo: Array<PropInfo>
let finallyBlockPropInfo: Option<PropInfo>
let resourceSpecPropInfo: Option<PropInfo>
let tryBlockPropInfo: PropInfo
init(catchBlocksPropInfo: Array<PropInfo>, catchPatternsPropInfo: Array<PropInfo>,
finallyBlockPropInfo: Option<PropInfo>, resourceSpecPropInfo: Option<PropInfo>, tryBlockPropInfo: PropInfo) {
this.catchBlocksPropInfo = catchBlocksPropInfo
this.catchPatternsPropInfo = catchPatternsPropInfo
this.finallyBlockPropInfo = finallyBlockPropInfo
this.resourceSpecPropInfo = resourceSpecPropInfo
this.tryBlockPropInfo = tryBlockPropInfo
}
}
/**
* @brief Represents a try-catch expression for exception handling.
* It consists of try, catch, and finally blocks.
*/
public class TryCatch <: Expr {
private let startPos: CodePosition
private let propInfos: TryExprPropInfos
private let posInfos: TryExprPosInfos
/**
* @brief Gets the position range of the 'try' keyword in the code.
*
* @return A CodePositionRange representing the position range of the 'try' keyword.
*/
public func getTryKeyWordPos(): CodePositionRange {
let endPos = posInfos.tryKeyWordPos + SyntaxNodeKind.TryToken.size
return CodePositionRange(posInfos.tryKeyWordPos, endPos)
}
/**
* @brief Gets the position range of the left parenthesis in the resource specification in the code.
*
* @return A CodePositionRange representing the position range of the left parenthesis in the resource specification.
*/
public func getResourceSpecLParenPos(): Option<CodePositionRange> {
if (let Some(lParenPos) <- posInfos.resourceSpecLParenPos) {
let endPos = lParenPos + SyntaxNodeKind.LParenToken.size
return CodePositionRange(lParenPos, endPos)
} else {
return None
}
}
/**
* @brief Gets the position ranges of the commas in the resource specification in the code.
*
* @return An Array of CodePositionRange representing the position ranges of the commas in the resource specification.
*/
public func getResourceSpecCommasPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.resourceSpecCommasPos.size) {
let endPos = posInfos.resourceSpecCommasPos[i] + SyntaxNodeKind.CommaToken.size
ret.add(CodePositionRange(posInfos.resourceSpecCommasPos[i], endPos))
}
ret.toArray()
}
/**
* @brief Gets the position range of the right parenthesis in the resource specification in the code.
*
* @return A CodePositionRange representing the position range of the right parenthesis in the resource specification.
*/
public func getResourceSpecRParenPos(): Option<CodePositionRange> {
if (let Some(rParenPos) <- posInfos.resourceSpecRParenPos) {
let endPos = rParenPos + SyntaxNodeKind.RParenToken.size
return CodePositionRange(rParenPos, endPos)
} else {
return None
}
}
/**
* @brief Gets the position ranges of the 'catch' keywords in the code.
*
* @return An Array of CodePositionRange representing the position ranges of the 'catch' keywords.
*/
public func getCatchKeyWordsPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.catchKeyWordsPos.size) {
let endPos = posInfos.catchKeyWordsPos[i] + SyntaxNodeKind.CatchToken.size
ret.add(CodePositionRange(posInfos.catchKeyWordsPos[i], endPos))
}
ret.toArray()
}
/**
* @brief Gets the position ranges of the left parentheses in the 'catch' blocks in the code.
*
* @return An Array of CodePositionRange representing the position ranges of the left parentheses in the 'catch' blocks.
*/
public func getCatchLParensPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.catchLParensPos.size) {
let endPos = posInfos.catchLParensPos[i] + SyntaxNodeKind.LParenToken.size
ret.add(CodePositionRange(posInfos.catchLParensPos[i], endPos))
}
ret.toArray()
}
/**
* @brief Gets the position ranges of the right parentheses in the 'catch' blocks in the code.
*
* @return An Array of CodePositionRange representing the position ranges of the right parentheses in the 'catch' blocks.
*/
public func getCatchRParensPos(): Array<CodePositionRange> {
let ret = ArrayList<CodePositionRange>()
for (i in 0..posInfos.catchRParensPos.size) {
let endPos = posInfos.catchRParensPos[i] + SyntaxNodeKind.RParenToken.size
ret.add(CodePositionRange(posInfos.catchRParensPos[i], endPos))
}
ret.toArray()
}
/**
* @brief Gets the position range of the 'finally' keyword in the code.
*
* @return An Option of CodePositionRange representing the position range of the 'finally' keyword, if present.
*/
public func getFinallyKeyWordPos(): Option<CodePositionRange> {
if (let Some(finallyKeyWordPos) <- posInfos.finallyKeyWordPos) {
let endPos = finallyKeyWordPos + SyntaxNodeKind.FinallyToken.size
return CodePositionRange(finallyKeyWordPos, endPos)
} else {
return None
}
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: TryExprPosInfos,
propInfos: TryExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new TryCatch node.
*/
public init(catchBlocks: Array<Block>, catchPatterns: Array<CatchPattern>, finallyBlock: Option<Block>,
resourceSpec: Array<VarDecl>, tryBlock: Block, comments!: Array<Comment> = []) {
super(
SyntaxNodeImplCreator.createTryCatchImpl(catchBlocks, catchPatterns, finallyBlock, resourceSpec, tryBlock,
comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<TryCatch>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The array of catch blocks.
*/
public prop catchBlocks: Array<Block> {
get() {
let catchBlocks = ArrayList<Block>()
for (propInfo in propInfos.catchBlocksPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
catchBlocks.add(
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow())
}
catchBlocks.toArray()
}
}
/**
* @brief The array of catch patterns.
*/
public prop catchPatterns: Array<CatchPattern> {
get() {
let catchPatterns = ArrayList<CatchPattern>()
for (propInfo in propInfos.catchPatternsPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
catchPatterns.add(
cast<CatchPattern>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this))
.getOrThrow())
}
catchPatterns.toArray()
}
}
/**
* @brief The optional finally block.
*/
public prop finallyBlock: Option<Block> {
get() {
if (let Some(propInfo) <- propInfos.finallyBlockPropInfo) {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
let offset = propInfo.offset
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
} else {
None
}
}
}
/**
* @brief The array of resource specifications.
*/
public prop resourceSpec: Array<VarDecl> {
get() {
let resourceSpec = ArrayList<VarDecl>()
if (let Some(propInfo) <- propInfos.resourceSpecPropInfo) {
let lp = LocalParser((nodeImpl as NonTerminal).getOrThrow().children, propInfo.offset,
index: propInfo.index)
while (lp.look(SyntaxNodeKind.VarDecl)) {
if (let Some(node) <- lp.consume()) {
resourceSpec.add(
cast<VarDecl>(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this))
.getOrThrow())
lp.moveOffset(node)
}
if (lp.look(SyntaxNodeKind.CommaToken)) {
lp.moveOffset(lp.consume())
}
}
}
resourceSpec.toArray()
}
}
/**
* @brief The try block.
*/
public prop tryBlock: Block {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.tryBlockPropInfo.index]
let offset = propInfos.tryBlockPropInfo.offset
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class TupleLiteralPosInfos {
let lParenPos: CodePosition
let rParenPos: CodePosition
let commasPos: Array<CodePosition>
init(lParenPos: CodePosition, rParenPos: CodePosition, commasPos: Array<CodePosition>) {
this.lParenPos = lParenPos
this.rParenPos = rParenPos
this.commasPos = commasPos
}
}
class TupleLiteralPropInfos {
let elementsPropInfo: PropInfo
init(elementsPropInfo: PropInfo) {
this.elementsPropInfo = elementsPropInfo
}
}
/**
* @brief Represents a tuple literal.
*
* The TupleLiteral class is a subclass of Expr and is used to model tuple
* literals. It contains an array of expressions that make up the tuple.
*/
public class TupleLiteral <: Expr {
private let startPos: CodePosition
private let posInfos: TupleLiteralPosInfos
private let propInfos: TupleLiteralPropInfos
/**
* @brief Gets the position range of the left bracket in the code.
*
* @return A CodePositionRange representing the position range of the left bracket.
*/
public func getLParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.lParenPos, SyntaxNodeKind.LParenToken.size)
}
/**
* @brief Gets the position range of the right bracket in the code.
*
* @return A CodePositionRange representing the position range of the right bracket.
*/
public func getRParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.rParenPos, SyntaxNodeKind.RParenToken.size)
}
/**
* @brief Gets the position ranges of the commas in the code.
*
* @return An ArrayList of CodePositionRange representing the position ranges of the commas.
*/
public func getCommasPos(): Array<CodePositionRange> {
return createExprTokenRanges(posInfos.commasPos, SyntaxNodeKind.CommaToken.size)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: TupleLiteralPosInfos,
propInfos: TupleLiteralPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new TupleLiteral node.
*/
public init(elements: Array<SyntaxTreeNode>, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createTupleLiteralImpl(elements, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<TupleLiteral>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief Array of expressions.
*
* This member variable stores an array of expressions of type Expr.
*/
public prop elements: Array<SyntaxTreeNode> {
get() {
let lp = LocalParser((nodeImpl as NonTerminal).getOrThrow().children, propInfos.elementsPropInfo.offset,
index: propInfos.elementsPropInfo.index)
let nodes = ArrayList<SyntaxTreeNode>()
let predictExpr = {
kind: SyntaxNodeKind => kind.isExpr()
}
while (lp.look(predictExpr) || lp.look(SyntaxNodeKind.WildcardPattern)) {
if (let Some(node) <- lp.consume()) {
nodes.add(SyntaxNodeImplTranslator.translate(node, startPos + lp.offset, this).getOrThrow())
lp.moveOffset(node)
}
lp.moveOffset(lp.lookAndConsume(SyntaxNodeKind.CommaToken))
}
nodes.toArray()
}
}
}
class TypeConvExprPropInfos {
let srcValPropInfo: PropInfo
let targetTypeAnnotationPropInfo: PropInfo
init(srcValPropInfo: PropInfo, targetTypeAnnotationPropInfo: PropInfo) {
this.srcValPropInfo = srcValPropInfo
this.targetTypeAnnotationPropInfo = targetTypeAnnotationPropInfo
}
}
class TypeConvExprPosInfos {
let lParenPos: CodePosition
let rParenPos: CodePosition
init(lParenPos: CodePosition, rParenPos: CodePosition) {
this.lParenPos = lParenPos
this.rParenPos = rParenPos
}
}
/**
* @brief Represents a type conversion expression.
*
* The TypeConvExpr class is a subclass of Expr and is used to model type
* conversion expressions. It contains a source value expression and a target
* type annotation specifying the type to which the source value should be
* converted.
*/
public class TypeConvExpr <: Expr {
private let startPos: CodePosition
private let propInfos: TypeConvExprPropInfos
private let posInfos: TypeConvExprPosInfos
/**
* @brief Retrieves the position range of the left parenthesis.
*
* @return The CodePositionRange representing the left parenthesis.
*/
public func getLParenPos(): CodePositionRange {
let endPos = posInfos.lParenPos + SyntaxNodeKind.LParenToken.size
return CodePositionRange(posInfos.lParenPos, endPos)
}
/**
* @brief Retrieves the position range of the right parenthesis.
*
* @return The CodePositionRange representing the right parenthesis.
*/
public func getRParenPos(): CodePositionRange {
let endPos = posInfos.rParenPos + SyntaxNodeKind.RParenToken.size
return CodePositionRange(posInfos.rParenPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfo: TypeConvExprPosInfos,
propInfo: TypeConvExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfo
this.propInfos = propInfo
}
/**
* @brief Initialize node with source value and target type.
*/
public init(srcVal: Expr, targetTypeAnnotation: AtomicType, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createTypeConvExprImpl(targetTypeAnnotation, srcVal, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<TypeConvExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief Expression representing the source value to be converted.
*
* This member variable stores the expression that represents the source value
* to be converted.
*/
public prop srcVal: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.srcValPropInfo)
}
}
/**
* @brief Target type for the conversion.
*
* This member variable stores the type annotation that specifies the target
* type for the conversion.
*/
public prop targetTypeAnnotation: AtomicType {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.targetTypeAnnotationPropInfo.index]
let offset = propInfos.targetTypeAnnotationPropInfo.offset
cast<AtomicType>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
/**
* @brief Enumeration for different kinds of unary operations.
*
* The UnaryOpKind enumeration defines various types of unary operations used
* in expressions. Each kind specifies a particular type of operation, such as
* subtraction or logical negation.
*/
public enum UnaryOpKind {
| Not
| Sub
| ...
}
class UnaryExprPropInfos {
let operandPropInfo: PropInfo
init(operandPropInfo: PropInfo) {
this.operandPropInfo = operandPropInfo
}
}
class UnaryExprPosInfos {
let opPos: CodePosition
init(opPos: CodePosition) {
this.opPos = opPos
}
}
/**
* @brief Represents a unary expression.
*
* The UnaryExpr class is a subclass of Expr and is used to model unary
* expressions. It contains an operator kind specifying the type of operation
* (e.g., subtraction or negation) and an operand expression on which the
* operation is applied.
*/
public class UnaryExpr <: Expr {
private let opKind_: UnaryOpKind
private let startPos: CodePosition
private let propInfos: UnaryExprPropInfos
private let posInfos: UnaryExprPosInfos
/**
* @brief Retrieves the position range of the operator in the code.
*
* @return CodePositionRange representing the start and end positions of the operator.
*/
public func getOperatorPos(): CodePositionRange {
let endPos = posInfos.opPos + SyntaxNodeKind.NotToken.size
return CodePositionRange(posInfos.opPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, opKind_: UnaryOpKind,
posInfos: UnaryExprPosInfos, propInfos: UnaryExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.opKind_ = opKind_
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with operand and op kind.
*/
public init(opKind: UnaryOpKind, operand: Expr, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createUnaryExprImpl(opKind, operand, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<UnaryExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
this.opKind_ = opKind
}
/**
* @brief Type of unary operation (e.g., subtraction or negation).
*
* This member variable stores the kind of unary operation specified by the
* UnaryOpKind enumeration.
*/
public prop opKind: UnaryOpKind {
get() {
opKind_
}
}
/**
* @brief Expression on which the unary operation is applied.
*
* This member variable stores the expression that is the operand of the unary
* operation.
*/
public prop operand: Expr {
get() {
return translateExprChild<Expr>(nodeImpl, startPos, this, propInfos.operandPropInfo)
}
}
}
class UnsafeExprPosInfos {
let unsafePos: CodePosition
init(unsafePos: CodePosition) {
this.unsafePos = unsafePos
}
}
class UnsafeExprPropInfos {
let blockPropInfo: PropInfo
init(blockPropInfo: PropInfo) {
this.blockPropInfo = blockPropInfo
}
}
/**
* @brief Represents a block of code that can execute unsafe operations.
*
* The UnsafeExpr class is a subclass of Expr and is used to encapsulate a block of code
* that may contain unsafe operations. It is designed to handle scenarios where direct
* manipulation of memory or other low-level operations are required, which are typically
* not allowed in safe code contexts.
*
* This class contains a single block of code which is executed in an environment where
* certain safety checks are relaxed. Care must be taken when using this class, as improper
* use can lead to memory leaks, undefined behavior, or security vulnerabilities.
*/
public class UnsafeExpr <: Expr {
private let startPos: CodePosition
private let propInfos: UnsafeExprPropInfos
private let posInfos: UnsafeExprPosInfos
public func getUnsafePos(): CodePositionRange {
let endPos = posInfos.unsafePos + SyntaxNodeKind.UnsafeToken.size
return CodePositionRange(posInfos.unsafePos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: UnsafeExprPosInfos,
propInfos: UnsafeExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new UnsafeExpr node.
*/
public init(block: Block, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createUnsafeExprImpl(block, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<UnsafeExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The block of code containing unsafe operations.
*
* This member variable stores the block of code that will be executed in an unsafe context.
* The block may contain operations such as raw pointer manipulation, direct memory access,
* or other low-level operations that bypass the language's usual safety mechanisms.
*/
public prop block: Block {
get() {
let propInfo = propInfos.blockPropInfo
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfo.index]
cast<Block>(SyntaxNodeImplTranslator.translate(curNode, startPos + propInfo.offset, this)).getOrThrow()
}
}
}
class VArrayExprPosInfos {
let lParenPos: CodePosition
let rParenPos: CodePosition
init(lParenPos: CodePosition, rParenPos: CodePosition) {
this.lParenPos = lParenPos
this.rParenPos = rParenPos
}
}
class VArrayExprPropInfos {
let argumentPropInfo: PropInfo
let vArrayTypePropInfo: PropInfo
init(argumentPropInfo: PropInfo, vArrayTypePropInfo: PropInfo) {
this.argumentPropInfo = argumentPropInfo
this.vArrayTypePropInfo = vArrayTypePropInfo
}
}
/**
* @brief VArray expression class, inheriting from Expr.
*/
public class VArrayExpr <: Expr {
private let startPos: CodePosition
private let propInfos: VArrayExprPropInfos
private let posInfos: VArrayExprPosInfos
/**
* @brief Gets the position range of the left parenthesis in the code.
*
* @return A CodePositionRange representing the position range of the left parenthesis.
*/
public func getLParenPos(): CodePositionRange {
let endPos = posInfos.lParenPos + SyntaxNodeKind.LParenToken.size
return CodePositionRange(posInfos.lParenPos, endPos)
}
/**
* @brief Gets the position range of the right parenthesis in the code.
*
* @return A CodePositionRange representing the position range of the right parenthesis.
*/
public func getRParenPos(): CodePositionRange {
let endPos = posInfos.rParenPos + SyntaxNodeKind.RParenToken.size
return CodePositionRange(posInfos.rParenPos, endPos)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: VArrayExprPosInfos,
propInfos: VArrayExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize node with augument and type of varray.
*/
public init(argument: Argument, vArrayType: VArrayType, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createVArrayExprImpl(argument, vArrayType, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<VArrayExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.posInfos = redNode.posInfos
this.propInfos = redNode.propInfos
this.startPos = startPos
}
/**
* @brief Array of arguments for the VArray expression.
*/
public prop argument: Argument {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.argumentPropInfo.index]
let offset = propInfos.argumentPropInfo.offset
cast<Argument>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
/**
* @brief Type of the VArray expression.
*/
public prop vArrayType: VArrayType {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.vArrayTypePropInfo.index]
let offset = propInfos.vArrayTypePropInfo.offset
cast<VArrayType>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this)).getOrThrow()
}
}
}
class WhileExprPosInfos {
let condLParenPos: CodePosition
let condRParenPos: CodePosition
let whileKeyWordPos: CodePosition
init(condLParenPos: CodePosition, condRParenPos: CodePosition, whileKeyWordPos: CodePosition) {
this.condLParenPos = condLParenPos
this.condRParenPos = condRParenPos
this.whileKeyWordPos = whileKeyWordPos
}
}
class WhileExprPropInfos {
let bodyPropInfo: PropInfo
let conditionPropInfo: PropInfo
init(bodyPropInfo: PropInfo, conditionPropInfo: PropInfo) {
this.bodyPropInfo = bodyPropInfo
this.conditionPropInfo = conditionPropInfo
}
}
/**
* @brief Represents a while loop expression.
* It consists of a loop body and a continuation condition.
*/
public class WhileExpr <: Expr {
private let startPos: CodePosition
private let propInfos: WhileExprPropInfos
private let posInfos: WhileExprPosInfos
/**
* @brief Get the position range of the 'while' keyword.
*/
public func getWhileKeyWordPos(): CodePositionRange {
return createExprTokenRange(posInfos.whileKeyWordPos, SyntaxNodeKind.WhileToken.size)
}
/**
* @brief Get the position range of the left parenthesis in the condition.
*/
public func getCondLParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.condLParenPos, SyntaxNodeKind.LParenToken.size)
}
/**
* @brief Get the position range of the right parenthesis in the condition.
*/
public func getCondRParenPos(): CodePositionRange {
return createExprTokenRange(posInfos.condRParenPos, SyntaxNodeKind.RParenToken.size)
}
init(nodeImpl: SyntaxNodeImpl, startPos: CodePosition, parentNode: ?SyntaxTreeNode, posInfos: WhileExprPosInfos,
propInfos: WhileExprPropInfos, commentsPropInfo: Array<PropInfo>) {
super(CodePositionRange(startPos, startPos + nodeImpl.offset), nodeImpl, parentNode, commentsPropInfo)
this.startPos = startPos
this.posInfos = posInfos
this.propInfos = propInfos
}
/**
* @brief Initialize a new WhileExpr node.
*/
public init(body: Block, condition: DisjunctionCondition, comments!: Array<Comment> = []) {
super(SyntaxNodeImplCreator.createWhileExprImpl(body, condition, comments: comments))
let startPos = DEFAULT_START_POS
let curNode = (this.nodeImpl as NonTerminal).getOrThrow()
let redNode = cast<WhileExpr>(SyntaxNodeImplTranslator.translate(curNode, startPos, None)).getOrThrow()
this.startPos = startPos
this.propInfos = redNode.propInfos
this.posInfos = redNode.posInfos
}
/**
* @brief The body of the loop as a block of code.
*/
public prop body: Block {
get() {
return translateExprChild<Block>(nodeImpl, startPos, this, propInfos.bodyPropInfo)
}
}
/**
* @brief The loop continuation condition.
*/
public prop condition: DisjunctionCondition {
get() {
let curNode = (nodeImpl as NonTerminal).getOrThrow().children[propInfos.conditionPropInfo.index]
let offset = propInfos.conditionPropInfo.offset
cast<DisjunctionCondition>(SyntaxNodeImplTranslator.translate(curNode, startPos + offset, this))
.getOrThrow()
}
}
}