/*
 * 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

public import std.ast.{Tokens, Token, TokenKind}
import std.ast.getTokenKind
import std.collection.{ArrayStack, ArrayList}

foreign func CJ_ParseFile(path: CString): CPointer<ParseRes>

foreign func CJ_ParseText(text: CString): CPointer<ParseRes>

foreign func CJ_ParseTokens(tokens: CPointer<UInt8>, tokenCounter: CPointer<Int64>, refreshPos: Bool): CPointer<ParseRes>

func findError(diags: Array<Diagnostic>): String {
    var res = ""
    for (diag in diags) {
        match (diag.diagInfo) {
            case Error(err, hint) => res += err + "\n" + hint
            case _ => ()
        }
    }
    return res
}

class ParserImpl {
    ParserImpl(private let filePath: String) {}

    func parseFile(): (?SyntaxNodeImpl, Array<Diagnostic>) {
        let (node, msg) = NodeLoader.load(filePath)
        // build impl tree by NodeFormat_Node
        let file: ?SyntaxNodeImpl = if (let Some(root) <- node) {
            FlatbufferNodeTranslator.translate(root)
        } else {
            None
        }
        (file, msg)
    }

    func getPreChildren(text: String): Array<SyntaxNodeImpl> {
        let builder = SyntaxNodeBuilder()
        let preChildren = ArrayList<SyntaxNodeImpl>()
        var cnt = 0
        // normalize NewLine to eliminate platform differences
        let tmpText = text.replace("\r\n", "\n")
        for (i in 0..tmpText.size) {
            let cur = tmpText[i..i + 1]
            // whitespace ended
            if (cur != "\n" && cur != " ") {
                break
            }
            // cnt increase
            if (cnt == 0 || tmpText[i - 1..i] == cur) {
                cnt += 1
            }
            // cnt downto 0, add current whitespace to array
            if (i < tmpText.size - 1 && tmpText[i + 1..i + 2] != cur) {
                if (cur == "\n") {
                    preChildren.add(builder.buildNewline(cnt))
                } else {
                    preChildren.add(builder.buildSpace(cnt))
                }
                cnt = 0
            }
        }
        return preChildren.toArray()
    }

    func parseText(text: String): (?SyntaxNodeImpl, Array<Diagnostic>) {
        let (node, msg) = NodeLoader.loadText(text)
        // build impl tree by NodeFormat_Node
        let res: ?SyntaxNodeImpl = if (let Some(root) <- node) {
            let errMsg = findError(msg)
            if (errMsg != "") {
                throw Exception("unsupported node type or parse error in parseText function:\n${errMsg}")
            }
            let preChildren = getPreChildren(text)
            FlatbufferNodeTranslator.translate(root, preChildren: preChildren.toArray())
        } else {
            None
        }
        (res, msg)
    }

    func parseTokens(tokens: Tokens, refreshPos: Bool): (?SyntaxNodeImpl, Array<Diagnostic>) {
        let (node, msg) = NodeLoader.loadTokens(tokens, refreshPos)
        // build impl tree by NodeFormat_Node
        let res: ?SyntaxNodeImpl = if (let Some(root) <- node) {
            FlatbufferNodeTranslator.translate(root)
        } else {
            None
        }
        (res, msg)
    }
}

// Extract all non-null elements from an Array<Option<T>>
private func getElements<T>(nodes: Array<Option<T>>): Array<T> {
    let elements = ArrayList<T>()
    for (node in nodes) {
        if (let Some(element) <- node) {
            elements.add(element)
        }
    }
    return elements.toArray()
}

private func transDiag(diag: NodeFormat_DiagInfo, fileInfo: FileInfos): Diagnostic {
    let msg = unsafe { String.fromUtf8Unchecked(diag.GetMsg()) }
    let hint = unsafe { String.fromUtf8Unchecked(diag.GetHint()) }
    let info = match (diag.GetSeverity()) {
        case 0 => DiagnosticInfo.Error(msg, hint)
        case 1 => DiagnosticInfo.Warning(msg, hint)
        case _ => throw Exception("unsupported severity kind (only support note or hint)")
    }
    var (begin, end) = (CodePosition(), CodePosition())
    if (let Some(range) <- diag.GetRange()) {
        begin = CodePosition(range.GetBegin().line, range.GetBegin().column, fileInfo)
        end = CodePosition(range.GetEnd().line, range.GetEnd().column, fileInfo)
    }
    return Diagnostic(CodePositionRange(begin, end), info)
}

private func transDiags(diags: NodeFormat_Diags, filePath: String): Array<Diagnostic> {
    let ret = ArrayList<Diagnostic>()
    let filePathArray = filePath.split(SEPARATOR)
    let fileName = if (filePathArray.size > 0) {
        filePathArray[filePathArray.size - 1]
    } else {
        ""
    }
    let fileInfo = FileInfos(fileName, filePath)
    for (diag in getElements<NodeFormat_DiagInfo>(diags.GetDiags())) {
        ret.add(transDiag(diag, fileInfo))
    }
    return ret.toArray()
}

private class NodeLoader {
    private let text: String
    private let tokens: Tokens
    // read 4 bytes for buffer size
    static const HEADER_SIZE: Int64 = 4
    private NodeLoader(private let filePath: String, private var diagInfo!: Array<Diagnostic> = []) {
        this.text = ""
        this.tokens = Tokens()
    }
    private init(text!: String) {
        this.text = text
        this.tokens = Tokens()
        this.filePath = ""
        this.diagInfo = []
    }

    private init(tokens!: Tokens) {
        this.text = ""
        this.tokens = tokens
        this.filePath = ""
        this.diagInfo = []
    }

    static func load(filePath: String): (?NodeFormat_Node, Array<Diagnostic>) {
        let loader = NodeLoader(filePath)
        (unsafe { loader.loadNodeFromFile() }, loader.diagInfo)
    }

    static func loadText(text: String): (?NodeFormat_Node, Array<Diagnostic>) {
        let loader = NodeLoader(text: text)
        (unsafe { loader.loadNodeFromText() }, loader.diagInfo)
    }

    static func loadTokens(tokens: Tokens, refreshPos: Bool): (?NodeFormat_Node, Array<Diagnostic>) {
        let loader = NodeLoader(tokens: tokens)
        (unsafe { loader.loadNodeFromTokens(refreshPos) }, loader.diagInfo)
    }

    private func getDiags(diagNode: CPointer<UInt8>) {
        let dataSize = Int64(getInt32(Array<UInt8>(HEADER_SIZE, {x: Int64 => unsafe { diagNode.read(x) }})))
        if (dataSize > 0) {
            let flatBuf = Array<UInt8>(dataSize, {x: Int64 => unsafe { diagNode.read(x) }})
            diagInfo = transDiags(NodeFormat_Diags(flatBuf[HEADER_SIZE..], 0), filePath)
        }
    }

    private func getNode(pnode: CPointer<UInt8>): ?NodeFormat_Node {
        let dataSize = Int64(getInt32(Array<UInt8>(HEADER_SIZE, {x: Int64 => unsafe { pnode.read(x) }})))
        if (dataSize <= 0) {
            return None
        }
        let flatBuf = Array<UInt8>(dataSize, {x: Int64 => unsafe { pnode.read(x) }})
        return NodeFormat_Node(flatBuf[HEADER_SIZE..], 0)
    }

    private unsafe func getParseResultPointers(resPtr: CPointer<ParseRes>): (CPointer<UInt8>, CPointer<UInt8>) {
        if (resPtr.isNull()) {
            throw Exception("the parsing result is empty.")
        }
        let res = resPtr.read()
        return (res.node, res.errMsg)
    }

    private unsafe func loadNodeFromFile(): ?NodeFormat_Node {
        var pathPtr: CString = CString(CPointer<UInt8>())
        var nodePtr = CPointer<UInt8>()
        var resPtr = CPointer<ParseRes>()
        var diagPtr = CPointer<UInt8>()
        try {
            pathPtr = LibC.mallocCString(filePath)
            if (pathPtr.isNull()) {
                throw Exception("mallocCString failed for file path.")
            }
            resPtr = CJ_ParseFile(pathPtr)
            (nodePtr, diagPtr) = getParseResultPointers(resPtr)
            if (nodePtr.isNull() && diagPtr.isNull()) {
                throw Exception("unsupported node type in parseFile function.")
            }
            if (!diagPtr.isNull()) {
                getDiags(diagPtr)
            }
            if (nodePtr.isNull()) {
                return None
            }
            return getNode(nodePtr)
        } finally {
            // free memory allocated in C.
            LibC.free(pathPtr)
            LibC.free(nodePtr)
            LibC.free(diagPtr)
            LibC.free(resPtr)
        }
    }

    private unsafe func loadNodeFromText(): ?NodeFormat_Node {
        var textPtr: CString = CString(CPointer<UInt8>())
        var nodePtr = CPointer<UInt8>()
        var resPtr = CPointer<ParseRes>()
        var diagPtr = CPointer<UInt8>()
        try {
            textPtr = LibC.mallocCString(text)
            if (textPtr.isNull()) {
                throw Exception("mallocCString failed for text.")
            }
            resPtr = CJ_ParseText(textPtr)
            (nodePtr, diagPtr) = getParseResultPointers(resPtr)
            if (nodePtr.isNull() && diagPtr.isNull()) {
                throw Exception("unsupported node type in parseText function.")
            }
            if (!diagPtr.isNull()) {
                getDiags(diagPtr)
            }
            if (nodePtr.isNull()) {
                return None
            }
            return getNode(nodePtr)
        } finally {
            // free memory allocated in C.
            LibC.free(textPtr)
            LibC.free(nodePtr)
            LibC.free(diagPtr)
            LibC.free(resPtr)
        }
    }

    private unsafe func loadNodeFromTokens(refreshPos: Bool): ?NodeFormat_Node {
        var tokensPtr = CPointer<UInt8>()
        var nodePtr = CPointer<UInt8>()
        var resPtr = CPointer<ParseRes>()
        var diagPtr = CPointer<UInt8>()
        let sizeOfInt64 = 8
        var tokensCounterPtr: CPointer<Int64> = LibC.malloc<Int64>(count: sizeOfInt64)
        try {
            tokensPtr = unsafePointerCastFromUint8Array(tokens.toBytes())
            if (tokensPtr.isNull()) {
                throw Exception("the input tokens is empty.")
            }
            resPtr = CJ_ParseTokens(tokensPtr, tokensCounterPtr, refreshPos)
            if (resPtr.isNull()) {
                throw Exception("the parsing result is empty.")
                return None
            }
            let res = resPtr.read()
            if (!res.errMsg.isNull()) {
                let diagNode = res.errMsg
                diagPtr = diagNode // backup for free
                getDiags(diagNode)
            }
            if (res.node.isNull()) {
                if (res.errMsg.isNull()) {
                    throw Exception("unsupported node type in parseTokens function.")
                }
                return None
            }
            let errMsg = findError(diagInfo)
            if (errMsg != "") {
                nodePtr = res.node
                throw Exception("unsupported node type or parse error in parseTokens function:\n${errMsg}")
            }
            let tokenCnt: Int64 = tokensCounterPtr.read()
            if (tokenCnt == 1) {
                nodePtr = res.node
                throw Exception("parseTokens function not support parse more than one node.")
            }
            let pnode = res.node
            nodePtr = pnode // backup for free
            return getNode(pnode)
        } finally {
            // free memory allocated in C.
            LibC.free(tokensPtr)
            LibC.free(nodePtr)
            LibC.free(diagPtr)
            LibC.free(resPtr)
            LibC.free(tokensCounterPtr)
        }
    }
}

private class FlatbufferNodeTranslator {
    private let builder = SyntaxNodeBuilder()
    private var cursorLine: Int32 = 1 // default (line: 1, column: 1)
    private var cursorColumn: Int32 = 1
    private var curChildren = ArrayList<SyntaxNodeImpl>() // record current context node
    private var innerComments = Array<Option<NodeFormat_CommentGroup>>()
    private var leadCommentNodes = ArrayList<SyntaxNodeImpl>()
    private var trailComments = Array<Option<NodeFormat_CommentGroup>>()

    static func translate(root: NodeFormat_Node, preChildren!: Array<SyntaxNodeImpl> = []): ?SyntaxNodeImpl {
        FlatbufferNodeTranslator().transRoot(root, preChildren)
    }

    private func transRoot(root: NodeFormat_Node, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let table = root.table
        let o: UInt16 = table.offset(root.ROOT)
        let off: UInt32 = UInt32(o) + table.pos
        match (root.GetRootType()) {
            case AnyNode_FILE => transFile(NodeFormat_File(table.bytes, off))
            case AnyNode_DECL => transDecl(NodeFormat_Decl(table.bytes, off), preChildren)
            case AnyNode_EXPR => transExpr(NodeFormat_Expr(table.bytes, off), preChildren)
            case AnyNode_IMPORT_SPEC => transImportList(NodeFormat_ImportSpec(table.bytes, off))
            case AnyNode_FEATURES_DIRECTIVE => transFeaturesDirective(NodeFormat_FeaturesDirective(table.bytes, off))
            case _ => throw Exception("ParseException: The current version does not support this node.")
        }
    }

    /* util funcs*/
    // add a child into parent
    private func addChild(children: ArrayList<SyntaxNodeImpl>, node: ?SyntaxNodeImpl) {
        if (let Some(child) <- node) {
            children.add(child)
        }
    }

    private func isBetweenCursorAndDest(cursorLine: Int32, cursorColumn: Int32, desLine: Int32, desColumn: Int32,
        commentLine: Int32, commentColumn: Int32): Bool {
        // check if the comments locate between the Cursor and the Destination position
        let afterCursor: Bool = cursorLine < commentLine || (cursorLine == commentLine && cursorColumn <= commentColumn)
        let beforeDest: Bool = commentLine < desLine || (commentLine == desLine && commentColumn < desColumn)
        if (afterCursor && beforeDest) {
            return true
        }
        return false
    }

    private func addInnerComments(line: Int32, column: Int32, needNewLine!: Bool = true): Unit {
        for (commentGroup in innerComments) {
            let tmpGroupList = [commentGroup]
            if (let Some(cmtStartPos) <- getCommentGroupListBeginPos(tmpGroupList) && isBetweenCursorAndDest(cursorLine,
                cursorColumn, line, column, cmtStartPos.line, cmtStartPos.column)) {
                /*
                if comments exist, and the comments locate between the Cursor and the Destination position,
                addWhitespace before the comment, then addComments, addWhitespace before the Destination position at last
                 */
                addWhitespaceWithoutComment(cmtStartPos.line, cmtStartPos.column, needNewLine: needNewLine)
                moveCursorColumn(cmtStartPos, 0)

                let tmpChildren = curChildren
                addChild(curChildren, transCommentGroupList(tmpGroupList))
                curChildren = tmpChildren
            }
        }
    }

    // add whitespace into curNode by [(cursorLine, cursorColumn) -- (line, column)]
    // needNewLine == false indicates that no newline is added.
    private func addWhitespace(line: Int32, column: Int32, needNewLine!: Bool = true): Unit {
        if (innerComments.size > 0) {
            addInnerComments(line, column, needNewLine: needNewLine)
        }
        addWhitespaceWithoutComment(line, column, needNewLine: needNewLine)
    }

    private func addWhitespaceWithoutComment(line: Int32, column: Int32, needNewLine!: Bool = true): Unit {
        var scol = column // default no spaces needed
        if (cursorLine == line) {
            scol = cursorColumn // the same line
        } else if (cursorLine < line) {
            scol = 1 // add current column - 1 spaces
            if (needNewLine) {
                addChild(curChildren, builder.buildNewline(Int64(line - cursorLine)))
            }
        }
        if (column - scol > 0) {
            addChild(curChildren, builder.buildSpace(Int64(column - scol)))
        }
        if (cursorLine < line || (cursorLine == line && cursorColumn <= column)) {
            (cursorLine, cursorColumn) = (line, column)
        }
    }

    private func addWhitespace(curPos: NodeFormat_Position, needNewLine!: Bool = true) {
        addWhitespace(curPos.line, curPos.column, needNewLine: needNewLine)
    }

    private func moveCursorColumn(pos: NodeFormat_Position, offset: Int64) {
        (cursorLine, cursorColumn) = (pos.line, pos.column + Int32(offset))
    }

    private func moveCursorColumn(col!: Int32 = 1) {
        cursorColumn += col
    }

    private func moveCursorLine(line!: Int32 = 1) {
        cursorColumn = 1
        cursorLine += 1
    }

    private func moveCursorToBegin(base: ?NodeFormat_NodeBase) {
        if (let Some(node) <- base) {
            let begin = node.GetBegin()
            // move cursor
            (cursorLine, cursorColumn) = (begin.line, begin.column)
        }
    }

    private func addWhitespaceAndMoveCursorToBegin(base: ?NodeFormat_NodeBase) {
        if (let Some(node) <- base) {
            let begin = getNodeCommentBeginPos(node)
            addWhitespaceAndMoveCursor(begin)
        }
    }

    private func getNodeCommentBeginPos(base: NodeFormat_NodeBase) {
        var begin = base.GetBegin()
        if (let Some(comments) <- base.GetComments()) {
            let leadComments = comments.GetLeadingComments()
            if (let Some(startPos) <- getCommentGroupListBeginPos(leadComments)) {
                begin = startPos
            }
        }
        begin
    }

    private func moveCursorToEnd(base: ?NodeFormat_NodeBase) {
        if (let Some(node) <- base) {
            let end = node.GetEnd()
            // Prevent position rollback
            if (cursorLine < end.line || (cursorLine == end.line && cursorColumn < end.column)) {
                (cursorLine, cursorColumn) = (end.line, end.column)
            }
        }
    }

    private func addWhitespaceAndMoveCursorToEnd(base: ?NodeFormat_NodeBase) {
        if (let Some(node) <- base) {
            let end = node.GetEnd()
            addWhitespace(end.line, end.column - 1)
            // move cursor
            (cursorLine, cursorColumn) = (end.line, end.column)
        }
    }

    private func addWhitespaceAndMoveCursor(curPos: NodeFormat_Position, needNewLine!: Bool = true) {
        addWhitespace(curPos, needNewLine: needNewLine)
        if (cursorLine < curPos.line || (cursorLine == curPos.line && cursorColumn <= curPos.column)) {
            (cursorLine, cursorColumn) = (curPos.line, curPos.column)
        }
    }

    private func moveCursorString(pos: NodeFormat_Position, str: String) {
        var strSplit = str.replace("\r\n", "\n").split("\n")
        if (strSplit.size > 1) {
            // The string contains newline characters; first, move the cursor line,
            // and the column position is determined by the last line of the string.
            cursorLine = pos.line + Int32(strSplit.size) - 1
            cursorColumn = Int32(strSplit[strSplit.size - 1].size + 1)
        } else {
            // The string is single line, simply move the column.
            (cursorLine, cursorColumn) = (pos.line, pos.column + Int32(str.size))
        }
    }

    private func resetGlobalVariables(ret: ArrayList<SyntaxNodeImpl>, innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        curChildren = ret
        innerComments = innerCmts
    }

    private func getSyntaxImplKind(num: UInt16): SyntaxNodeKind {
        match (num) {
            case 8 /*EXP*/ => SyntaxNodeKind.ExpToken
            case 9 /*MUL*/ => SyntaxNodeKind.MulToken
            case 10 /*MOD*/ => SyntaxNodeKind.ModToken
            case 11 /*DIV*/ => SyntaxNodeKind.DivToken
            case 12 /*ADD*/ => SyntaxNodeKind.AddToken
            case 13 /*SUB*/ => SyntaxNodeKind.SubToken
            case 14 /*INCR*/ => SyntaxNodeKind.IncrToken
            case 15 /*DECR*/ => SyntaxNodeKind.DecrToken
            case 16 /*AND*/ => SyntaxNodeKind.AndToken
            case 17 /*OR*/ => SyntaxNodeKind.OrToken
            case 18 /*COALESCING  */ => SyntaxNodeKind.CoalescingToken
            case 19 /*PIPELINE*/ => SyntaxNodeKind.PipelineToken
            case 20 /*COMPOSITION */ => SyntaxNodeKind.CompositionToken
            case 21 /*NOT*/ => SyntaxNodeKind.NotToken
            case 22 /*BITAND*/ => SyntaxNodeKind.BitAndToken
            case 23 /*BITOR */ => SyntaxNodeKind.BitOrToken
            case 24 /*BITXOR*/ => SyntaxNodeKind.BitXorToken
            case 25 /*BITNOT*/ => SyntaxNodeKind.BitNotToken
            case 26 /*LSHIFT*/ => SyntaxNodeKind.LShiftToken
            case 27 /*RSHIFT*/ => SyntaxNodeKind.RShiftToken
            case 30 /*ASSIGN*/ => SyntaxNodeKind.AssignToken
            case 31 /*ADDASSIGN*/ => SyntaxNodeKind.AddAssignToken
            case 32 /*SUBASSIGN*/ => SyntaxNodeKind.SubAssignToken
            case 34 /*EXPASSIGN*/ => SyntaxNodeKind.ExpAssignToken
            case 33 /*MULASSIGN*/ => SyntaxNodeKind.MulAssignToken
            case 35 /*DIVASSIGN*/ => SyntaxNodeKind.DivAssignToken
            case 36 /*MODASSIGN*/ => SyntaxNodeKind.ModAssignToken
            case 37 /*ANDASSIGN*/ => SyntaxNodeKind.AndAssignToken
            case 38 /*ORASSIGN*/ => SyntaxNodeKind.OrAssignToken
            case 39 /*BITANDASSIGN*/ => SyntaxNodeKind.BitAndAssignToken
            case 40 /*BITORASSIGN*/ => SyntaxNodeKind.BitOrAssignToken
            case 41 /*BITXORASSIGN*/ => SyntaxNodeKind.BitXorAssignToken
            case 42 /*LSHIFTASSIGN*/ => SyntaxNodeKind.LShiftAssignToken
            case 43 /*RSHIFTASSIGN*/ => SyntaxNodeKind.RShiftAssignToken
            case 53 /*LT*/ => SyntaxNodeKind.LtToken
            case 54 /*GT*/ => SyntaxNodeKind.GtToken
            case 55 /*LE*/ => SyntaxNodeKind.LeToken
            case 56 /*GE*/ => SyntaxNodeKind.GeToken
            case 59 /*NOTEQ*/ => SyntaxNodeKind.NotEqToken
            case 60 /*EQUAL*/ => SyntaxNodeKind.EqualToken
            case 93 /*CONST*/ => SyntaxNodeKind.ConstToken
            case 118 /*STATIC*/ => SyntaxNodeKind.StaticToken
            case 119 /*PUBLIC*/ => SyntaxNodeKind.PublicToken
            case 120 /*PRIVATE*/ => SyntaxNodeKind.PrivateToken
            case 121 /*INTERNAL*/ => SyntaxNodeKind.InternalToken
            case 122 /*PROTECTED*/ => SyntaxNodeKind.ProtectedToken
            case 123 /*OVERRIDE*/ => SyntaxNodeKind.OverrideToken
            case 124 /*REDEF*/ => SyntaxNodeKind.RedefToken
            case 125 /*ABSTRACT*/ => SyntaxNodeKind.AbstractToken
            case 126 /*SEALED*/ => SyntaxNodeKind.SealedToken
            case 127 /*OPEN*/ => SyntaxNodeKind.OpenToken
            case 128 /*FOREIGN*/ => SyntaxNodeKind.ForeignToken
            case 129 /*INOUT*/ => SyntaxNodeKind.InoutToken
            case 130 /*MUT*/ => SyntaxNodeKind.MutToken
            case 131 /*UNSAFE*/ => SyntaxNodeKind.UnsafeToken
            case 132 /*OPERATOR*/ => SyntaxNodeKind.OperatorToken
            case _ => SyntaxNodeKind.Invalid
        }
    }

    private func isValidPosition(pos: NodeFormat_Position): Bool {
        if (pos.line == 0 && pos.column == 0) {
            return false
        }
        return true
    }

    private func isSamePosition(pos1: NodeFormat_Position, pos2: NodeFormat_Position) {
        return pos1.fileId == pos2.fileId && pos1.line == pos2.line && pos1.column == pos2.column
    }

    // add expr to curNode
    private func transNoTerminalExpr(expr: NodeFormat_Expr, isInterpol!: Bool = false) {
        addWhitespaceAndMoveCursorToBegin(expr.GetBase())
        addChild(curChildren, transExpr(expr, [], isInterpol: isInterpol))
        moveCursorToEnd(expr.GetBase())
    }

    // add type to curNode,  startFromBegin = false indicates translate from the TypePos of the type.
    private func transType(ty: NodeFormat_Type, startFromBegin!: Bool = true) {
        if (let Some(tyBase) <- ty.GetBase()) {
            if (!startFromBegin) {
                let beginPos = tyBase.GetTypePos()
                addWhitespaceAndMoveCursor(beginPos)
            } else {
                addWhitespaceAndMoveCursorToBegin(tyBase.GetBase())
            }
            addChild(curChildren, transTypeAnnotation(ty))
            moveCursorToEnd(tyBase.GetBase())
        }
    }

    // add basic terminal to curNode
    private func transBasicTerminal(begin: NodeFormat_Position, kind: SyntaxNodeKind) {
        if (isValidPosition(begin)) {
            // add prefix whitespace
            addWhitespace(begin)
            // add basic terminal
            addChild(curChildren, builder.buildBasicTerminal(kind))
            // move cursor
            moveCursorColumn(begin, kind.toString().size)
        }
    }

    private func transTokenTerminal(begin: NodeFormat_Position, kind: TokenKind, value: String,
        needNewLine!: Bool = true, delimiterNum!: UInt32 = 0, isSingleQuote!: Bool = false, hasEscape!: Bool = false) {
        if (!isValidPosition(begin)) {
            return
        }
        // add prefix whitespace
        addWhitespace(begin, needNewLine: needNewLine)
        var quoteToken = builder.buildQuote(isSingleQuote)
        let tokenValue = builder.buildTokenTerminal(kind, value, hasEscape: hasEscape)
        let valueEscaped = tokenValue.toString()
        var moveStr = valueEscaped
        // add Token terminal, handle strings and character types separately.
        if (kind == TokenKind.MULTILINE_RAW_STRING) {
            let hashToken = builder.buildHash(Int64(delimiterNum))
            curChildren.add(all: [hashToken, quoteToken, tokenValue, quoteToken, hashToken])
            moveStr = '#' * Int64(delimiterNum) + '"' + valueEscaped + '"' + '#' * Int64(delimiterNum)
        } else if (kind == TokenKind.MULTILINE_STRING) {
            quoteToken = builder.buildTripleQuote(isSingleQuote)
            curChildren.add(all: [quoteToken, builder.buildNewline(1), tokenValue, quoteToken])
            moveStr = "'''\n" + valueEscaped + "'''"
        } else if (kind == TokenKind.STRING_LITERAL || kind == TokenKind.SINGLE_QUOTED_STRING_LITERAL) {
            curChildren.add(all: [quoteToken, tokenValue, quoteToken])
            moveStr = "'" + valueEscaped + "'"
        } else if (kind == RUNE_LITERAL) {
            let prefix = builder.buildBasicTerminal(SyntaxNodeKind.RunePrefixToken)
            curChildren.add(all: [prefix, quoteToken, tokenValue, quoteToken])
            moveStr = "r'" + valueEscaped + "'"
        } else {
            curChildren.add(tokenValue)
        }

        // move cursor
        moveCursorString(begin, moveStr)
    }

    // add identifier to curNode
    private func transIdentifier(idPos: NodeFormat_Position, id: String) {
        if (isValidPosition(idPos)) {
            addWhitespace(idPos)
            addChild(curChildren, builder.buildValuedTerminal(SyntaxNodeKind.IdentToken, id))
            moveCursorColumn(idPos, id.size)
        }
    }

    private func transImportContent(content: NodeFormat_ImportContent): ?SyntaxNodeImpl {
        let (kind, nodeKind) = match (content.GetKind()) {
            case ImportKind_IMPORT_SINGLE => (ImportKind.Single, SyntaxNodeKind.ImportSingle)
            case ImportKind_IMPORT_ALIAS => (ImportKind.Alias, SyntaxNodeKind.ImportAlias)
            case ImportKind_IMPORT_ALL => (ImportKind.All, SyntaxNodeKind.ImportAll)
            case ImportKind_IMPORT_MULTI => (ImportKind.Multi, SyntaxNodeKind.ImportMulti)
        }
        addWhitespaceAndMoveCursorToBegin(content.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = content.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)

        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let prefixPaths = content.GetPrefixPaths()
        let prefixPoses = content.GetPrefixPoses()
        let prefixDotPoses = content.GetPrefixDotPoses()
        for (i in 0..prefixPaths.size) {
            if (let Some(path) <- prefixPaths[i]) {
                transIdentifier(prefixPoses[i], path)
            }
            transBasicTerminal(prefixDotPoses[i], SyntaxNodeKind.DotToken)
        }
        let identPos = content.GetIdentifierPos()
        if (let ImportKind.All <- kind) {
            transBasicTerminal(identPos, SyntaxNodeKind.MulToken)
        } else if (let ImportKind.Multi <- kind) {
            transBasicTerminal(content.GetLeftCurlPos(), SyntaxNodeKind.LCurlToken)

            let vItems = content.GetItems()
            let commaPoses = content.GetCommaPoses()
            for (i in 0..vItems.size) {
                if (let Some(content) <- vItems[i]) {
                    addChild(ret, transImportContent(content))
                    resetGlobalVariables(ret, innerCmts)
                }
                if (i < commaPoses.size) {
                    transBasicTerminal(commaPoses[i], SyntaxNodeKind.CommaToken)
                }
            }
            transBasicTerminal(content.GetRightCurlPos(), SyntaxNodeKind.RCurlToken)
        } else {
            transIdentifier(identPos, content.GetIdentifier())
            if (let ImportKind.Alias <- kind) {
                transBasicTerminal(content.GetAsPos(), SyntaxNodeKind.AsToken)
                transIdentifier(content.GetAsIdentifierPos(), content.GetAsIdentifier())
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(nodeKind, ret.toArray())
    }

    private func transImportList(imports: NodeFormat_ImportSpec): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(imports.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = imports.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let kind = match (imports.GetReExport()) {
            case ReExportKind_REEXPORT_PUBLIC => SyntaxNodeKind.PublicToken
            case ReExportKind_REEXPORT_PROTECTED => SyntaxNodeKind.ProtectedToken
            case ReExportKind_REEXPORT_INTERNAL => SyntaxNodeKind.InternalToken
            case _ => SyntaxNodeKind.PrivateToken
        }
        if (let Some(base) <- imports.GetBase()) {
            if (!isSamePosition(imports.GetImportPos(), base.GetBegin())) {
                addChild(ret, transModifier(base.GetBegin(), kind))
                resetGlobalVariables(ret, innerCmts)
            }
        }
        transBasicTerminal(imports.GetImportPos(), SyntaxNodeKind.ImportToken)
        if (let Some(v) <- imports.GetContent()) {
            addChild(ret, transImportContent(v))
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ImportSpec, ret.toArray())
    }

    private func getPrimitiveTypeKind(num: UInt16): SyntaxNodeKind {
        match (num) {
            case 1 /*UNIT*/ => SyntaxNodeKind.UnitToken
            case 2 /*INT8*/ => SyntaxNodeKind.Int8Token
            case 3 /*INT16*/ => SyntaxNodeKind.Int16Token
            case 4 /*INT32*/ => SyntaxNodeKind.Int32Token
            case 5 /*INT64*/ => SyntaxNodeKind.Int64Token
            case 6 /*INTNATIVE*/ => SyntaxNodeKind.IntNativeToken
            case 8 /*UINT8*/ => SyntaxNodeKind.UInt8Token
            case 9 /*UINT16*/ => SyntaxNodeKind.UInt16Token
            case 10 /*UINT32*/ => SyntaxNodeKind.UInt32Token
            case 11 /*UINT64*/ => SyntaxNodeKind.UInt64Token
            case 12 /*UINTNATIVE*/ => SyntaxNodeKind.UIntNativeToken
            case 13 /*FLOAT16*/ => SyntaxNodeKind.Float16Token
            case 14 /*FLOAT32*/ => SyntaxNodeKind.Float32Token
            case 15 /*FLOAT64*/ => SyntaxNodeKind.Float64Token
            case 17 /*RUNE*/ => SyntaxNodeKind.RuneToken
            case 18 /*NOTHING*/ => SyntaxNodeKind.NothingToken
            case 19 /*BOOLEAN*/ => SyntaxNodeKind.BooleanToken
            case _ => return SyntaxNodeKind.Invalid
        }
    }

    private func transPrimitiveTypeExpr(primitiveType: NodeFormat_PrimitiveTypeExpr): ?SyntaxNodeImpl {
        return transPrimitiveTypeNode(primitiveType.GetBase(), primitiveType.GetKind(), false)
    }

    private func transPrimitiveType(primitiveType: NodeFormat_PrimitiveType): ?SyntaxNodeImpl {
        return transPrimitiveTypeNode(primitiveType.GetBase().getOrThrow().GetBase(), primitiveType.GetKind(), true)
    }

    private func transPrimitiveTypeNode(nodeBase: ?NodeFormat_NodeBase, primitiveKind: UInt16,
        addPendingTrailComments: Bool): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let ty = getPrimitiveTypeKind(primitiveKind)
        addChild(ret, builder.buildBasicTerminal(ty))
        moveCursorColumn(col: Int32(ty.size))
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        if (addPendingTrailComments) {
            addTrailCommentNodesToRet(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.PrimitiveType, ret.toArray())
    }

    private func transRefType(ty: NodeFormat_RefType): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = ty.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(ref) <- ty.GetRef()) {
            transIdentifier(ref.GetIdentifierPos(), ref.GetIdentifier())
        }
        let typeArguments = ty.GetTypeArguments()
        if (typeArguments.size != 0) {
            addChild(ret, transTypeArguments(typeArguments, ty.GetLeftAnglePos(), ty.GetRightAnglePos()))
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.RefType, ret.toArray())
    }

    private func transTypeElementWithOptionalLabel(type_: NodeFormat_Type, ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        if (let Some(db) <- type_.GetBase()) {
            var startFromBegin = true
            if (isValidPosition(db.GetColonPos()) && let Some(base) <- db.GetBase()) {
                transIdentifier(base.GetBegin(), db.GetTypeParameterName())
                transBasicTerminal(db.GetColonPos(), SyntaxNodeKind.ColonToken)
                startFromBegin = false
            }
            transType(type_, startFromBegin: startFromBegin)
            resetGlobalVariables(ret, innerCmts)
            transBasicTerminal(db.GetCommaPos(), SyntaxNodeKind.CommaToken)
        }
    }

    private func transFuncType(ty: NodeFormat_FuncType): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = ty.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(ty.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        let types = ty.GetParamTypes()
        for (t in types) {
            if (let Some(type_) <- t) {
                transTypeElementWithOptionalLabel(type_, ret, innerCmts)
            }
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(ty.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        transBasicTerminal(ty.GetArrowPos(), SyntaxNodeKind.ArrowToken)
        if (let Some(t) <- ty.GetRetType()) {
            transType(t)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.FuncType, ret.toArray())
    }

    private func transThisType(ty: NodeFormat_ThisType): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = ty.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        addChild(ret, builder.buildBasicTerminal(SyntaxNodeKind.ThisTypeToken))
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.PrimitiveType, ret.toArray())
    }

    private func transTupleType(ty: NodeFormat_TupleType): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = ty.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(ty.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        let types = ty.GetFieldTypes()
        for (t in 0..types.size) {
            if (let Some(type_) <- types[t]) {
                transTypeElementWithOptionalLabel(type_, ret, innerCmts)
            }
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(ty.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TupleType, ret.toArray())
    }

    private func transInnerOptionType(questVec: Array<NodeFormat_Position>, i: Int64, ty: NodeFormat_Type): ?SyntaxNodeImpl {
        if (questVec.size == i) {
            if (let Some(tyBase) <- ty.GetBase()) {
                addWhitespaceAndMoveCursorToBegin(tyBase.GetBase())
                let ret = transTypeAnnotation(ty)
                return ret
            }
            return None
        } else {
            addWhitespace(questVec[i])
            let ret = ArrayList<SyntaxNodeImpl>()
            addLeadCommentNodesToRet(ret)
            curChildren = ret

            let nodeBase = ty.GetBase().getOrThrow().GetBase()
            let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
            addLeadingComments(nodeBase, ret, leadCmts)
            innerComments = innerCmts

            ret.add(builder.buildBasicTerminal(SyntaxNodeKind.QuestToken))
            moveCursorColumn(questVec[i], 1)
            addChild(ret, transInnerOptionType(questVec, i + 1, ty))
            if (trailCmts.size > 0) {
                addChild(ret, transCommentGroupList(trailCmts))
                curChildren = ret
            }
            addTrailCommentNodesToRet(ret, innerCmts)
            return builder.buildNonTerminal(SyntaxNodeKind.OptionType, ret.toArray())
        }
    }

    private func transOptionType(ty: NodeFormat_OptionType): ?SyntaxNodeImpl {
        let questVec = ty.GetQuestVector()
        let questNum = questVec.size
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        addWhitespace(questVec[0])
        curChildren = ret

        let nodeBase = ty.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        ret.add(builder.buildBasicTerminal(SyntaxNodeKind.QuestToken))
        moveCursorColumn(questVec[0], 1)
        if (let Some(t) <- ty.GetComponentType()) {
            if (let Some(tyBase) <- t.GetBase()) {
                addChild(ret, transInnerOptionType(questVec, 1, t))
                moveCursorToEnd(tyBase.GetBase())
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        return builder.buildNonTerminal(SyntaxNodeKind.OptionType, ret.toArray())
    }

    private func transParenType(parenType: NodeFormat_ParenType): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = parenType.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(parenType.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        if (let Some(ty) <- parenType.GetType()) {
            transType(ty)
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(parenType.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ParenType, ret.toArray())
    }

    private func transBaseIdentTokens(ty: NodeFormat_Type): Unit {
        let table = ty.table
        let o: UInt16 = table.offset(ty.TYPE)
        let off: UInt32 = UInt32(o) + table.pos
        let ret = curChildren
        match (ty.GetTypeType()) {
            case AnyType_REF_TYPE =>
                if (let Some(ref) <- NodeFormat_RefType(table.bytes, off).GetRef()) {
                    transIdentifier(ref.GetIdentifierPos(), ref.GetIdentifier())
                }
            case AnyType_QUALIFIED_TYPE =>
                let qualifiedType = NodeFormat_QualifiedType(table.bytes, off)
                if (let Some(baseTy) <- qualifiedType.GetBaseType()) {
                    transBaseIdentTokens(baseTy)
                    curChildren = ret
                }
                transBasicTerminal(qualifiedType.GetDotPos(), SyntaxNodeKind.DotToken)
                transIdentifier(qualifiedType.GetFieldPos(), qualifiedType.GetField())
            case _ => throw Exception("ParseException: error trans base identToken")
        }
    }

    private func transQualifiedType(qualifiedType: NodeFormat_QualifiedType): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = qualifiedType.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(baseTy) <- qualifiedType.GetBaseType()) {
            transBaseIdentTokens(baseTy)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(qualifiedType.GetDotPos(), SyntaxNodeKind.DotToken)
        transIdentifier(qualifiedType.GetFieldPos(), qualifiedType.GetField())
        let typeArguments = qualifiedType.GetTypeArguments()
        if (typeArguments.size != 0) {
            addChild(ret,
                transTypeArguments(typeArguments, qualifiedType.GetLeftAnglePos(), qualifiedType.GetRightAnglePos()))
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.QualifiedType, ret.toArray())
    }

    // only use in transVArrayType
    private func transConstantType(constantTy: NodeFormat_ConstantType): ?SyntaxNodeImpl {
        transBasicTerminal(constantTy.GetDollarPos(), SyntaxNodeKind.DollarToken)
        if (let Some(constantExpr) <- constantTy.GetConstantExpr()) {
            transNoTerminalExpr(constantExpr)
        }
        None
    }

    private func transVArrayType(vArrayType: NodeFormat_VArrayType): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = vArrayType.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(vArrayType.GetVarrayPos(), SyntaxNodeKind.VArrayToken)
        transBasicTerminal(vArrayType.GetLeftAnglePos(), SyntaxNodeKind.LtToken)
        if (let Some(ty) <- vArrayType.GetTypeArgument()) {
            transType(ty)
            resetGlobalVariables(ret, innerCmts)
            if (let Some(tb) <- ty.GetBase()) {
                transBasicTerminal(tb.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
        }
        if (let Some(constantTy) <- vArrayType.GetConstantType()) {
            transTypeAnnotation(constantTy)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(vArrayType.GetRightAnglePos(), SyntaxNodeKind.GtToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        addTrailCommentNodesToRet(ret, innerCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.VArrayType, ret.toArray())
    }

    private func transTypeAnnotation(ty: NodeFormat_Type): ?SyntaxNodeImpl {
        let table = ty.table
        let o: UInt16 = table.offset(ty.TYPE)
        let off: UInt32 = UInt32(o) + table.pos
        match (ty.GetTypeType()) {
            case AnyType_PRIMITIVE_TYPE => transPrimitiveType(NodeFormat_PrimitiveType(table.bytes, off))
            case AnyType_REF_TYPE => transRefType(NodeFormat_RefType(table.bytes, off))
            case AnyType_FUNC_TYPE => transFuncType(NodeFormat_FuncType(table.bytes, off))
            case AnyType_THIS_TYPE => transThisType(NodeFormat_ThisType(table.bytes, off))
            case AnyType_PAREN_TYPE => transParenType(NodeFormat_ParenType(table.bytes, off))
            case AnyType_QUALIFIED_TYPE => transQualifiedType(NodeFormat_QualifiedType(table.bytes, off))
            case AnyType_OPTION_TYPE => transOptionType(NodeFormat_OptionType(table.bytes, off))
            case AnyType_TUPLE_TYPE => transTupleType(NodeFormat_TupleType(table.bytes, off))
            case AnyType_CONSTANT_TYPE => transConstantType(NodeFormat_ConstantType(table.bytes, off))
            case AnyType_VARRAY_TYPE => transVArrayType(NodeFormat_VArrayType(table.bytes, off))
            case _ => throw Exception("ParseException: The current version does not support this node.")
        }
    }

    /* translate funcs*/
    private func transFile(file: NodeFormat_File): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = file.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(featuresNode) <- file.GetFeature()) {
            addChild(ret, transFeaturesDirective(featuresNode))
            resetGlobalVariables(ret, innerCmts)
        }

        if (let Some(packageNode) <- file.GetPackage()) {
            addChild(ret, transPackageSpec(packageNode))
            resetGlobalVariables(ret, innerCmts)
        }
        let imports = file.GetImports()
        for (imp in imports) {
            if (let Some(import1) <- imp) {
                addChild(ret, transImportList(import1))
                resetGlobalVariables(ret, innerCmts)
            }
        }

        let decls: Array<Option<NodeFormat_Decl>> = file.GetDecls()
        for (node in decls) {
            resetGlobalVariables(ret, innerCmts) // set context node
            if (let Some(decl) <- node) {
                addChild(ret, transDecl(decl))
            }
        }
        resetGlobalVariables(ret, innerCmts)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.File, ret.toArray())
    }

    private func transFeatureId(ftr: NodeFormat_FeatureId): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(ftr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let idents = ftr.GetIdentifiers()
        let identPoses = ftr.GetIdentPoses()
        let dotPoses = ftr.GetDotPoses()
        for (i in 0..idents.size) {
            if (let Some(item) <- idents[i]) {
                transIdentifier(identPoses[i], item)
            }
            if (i < dotPoses.size) {
                transBasicTerminal(dotPoses[i], SyntaxNodeKind.DotToken)
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.FeatureId, ret.toArray())
    }

    private func transFeaturesSet(ftrSet: NodeFormat_FeaturesSet): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(ftrSet.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let lCurlPos = ftrSet.GetLCurlPos()
        let rCurlPos = ftrSet.GetRCurlPos()
        let content = ftrSet.GetContent()
        let commaPoses = ftrSet.GetCommaPoses()
        transBasicTerminal(lCurlPos, SyntaxNodeKind.LCurlToken)
        for (i in 0..content.size) {
            if (let Some(item) <- content[i]) {
                addChild(ret, transFeatureId(item))
                curChildren = ret
            }
            if (i < commaPoses.size) {
                transBasicTerminal(commaPoses[i], SyntaxNodeKind.CommaToken)
            }
        }
        transBasicTerminal(rCurlPos, SyntaxNodeKind.RCurlToken)
        builder.buildNonTerminal(SyntaxNodeKind.FeaturesSet, ret.toArray())
    }
    
    private func transFeaturesDirective(ftr: NodeFormat_FeaturesDirective): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(ftr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        curChildren = ret

        let annos = ftr.GetAnnotations()
        if (annos.size != 0) {
            addChild(ret, transAnnotations(annos))
        } else {
            addWhitespaceAndMoveCursorToBegin(ftr.GetBase())
        }
        transBasicTerminal(ftr.GetFeaturesPos(), SyntaxNodeKind.FeaturesToken)
        if (let Some(ftrSet) <- ftr.GetFeaturesSet()) {
            addChild(ret, transFeaturesSet(ftrSet))
        }
        builder.buildNonTerminal(SyntaxNodeKind.FeaturesDirective, ret.toArray())
    }

    private func getPackageIndentKind(s: String): SyntaxNodeKind {
        let isPkgIdent = s.contains(".") || s.contains("-") || s.contains(" ")
        if (isPkgIdent) {
            return SyntaxNodeKind.PackageIdentifierToken
        } else {
            return SyntaxNodeKind.IdentToken
        }
    }

    private func transPackagePrefixes(prefixPaths: Array<Option<String>>, prefixPoses: Array<NodeFormat_Position>,
        prefixDotPoses: Array<NodeFormat_Position>): ?SyntaxNodeImpl {
        if (prefixPaths.size != prefixPoses.size || prefixPaths.size != prefixDotPoses.size) {
            return None
        }
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        for (i in 0..prefixPaths.size) {
            addWhitespace(prefixPoses[i])
            curChildren = ret
            if (let Some(prefixPath) <- prefixPaths[i]) {
                ret.add(builder.buildValuedTerminal(getPackageIndentKind(prefixPath), prefixPath))
                moveCursorColumn(prefixPoses[i], prefixPath.size)
            }
            transBasicTerminal(prefixDotPoses[i], SyntaxNodeKind.DotToken)
        }
        builder.buildNonTerminal(SyntaxNodeKind.PackagePrefixes, ret.toArray())
    }

    private func transPackageSpec(pkg: NodeFormat_PackageSpec): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(pkg.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = pkg.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(nodeBase) <- pkg.GetBase()) {
            let beginPos = nodeBase.GetBegin()
            if (!isSamePosition(pkg.GetMacroPos(), beginPos) && !isSamePosition(pkg.GetPackagePos(), beginPos)) {
                let kind = match (pkg.GetAccessible()) {
                    case NodeFormat_AccessibleKind.AccessibleKind_ACCESSIBLE_PUBLIC => SyntaxNodeKind.PublicToken
                    case NodeFormat_AccessibleKind.AccessibleKind_ACCESSIBLE_PROTECTED => SyntaxNodeKind.ProtectedToken
                    case _ => SyntaxNodeKind.InternalToken
                }
                addChild(ret, transModifier(beginPos, kind))
                resetGlobalVariables(ret, innerCmts)
            }
        }
        transBasicTerminal(pkg.GetMacroPos(), SyntaxNodeKind.MacroToken)
        transBasicTerminal(pkg.GetPackagePos(), SyntaxNodeKind.PackageToken)
        let prefixPaths = pkg.GetPrefixPaths()
        if (prefixPaths.size != 0) {
            addChild(ret, transPackagePrefixes(prefixPaths, pkg.GetPrefixPoses(), pkg.GetPrefixDotPoses()))
        }
        resetGlobalVariables(ret, innerCmts)
        addWhitespace(pkg.GetPackageNamePos())
        let packageName = pkg.GetPackageName()
        ret.add(builder.buildValuedTerminal(getPackageIndentKind(packageName), packageName))
        moveCursorColumn(pkg.GetPackageNamePos(), packageName.size)

        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.PackageSpec, ret.toArray())
    }

    // Decls: 
    private func transDecl(decl: NodeFormat_Decl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let table = decl.table
        let o: UInt16 = table.offset(decl.DECL)
        let off: UInt32 = UInt32(o) + table.pos
        match (decl.GetDeclType()) {
            case AnyDecl_VAR_DECL => transVarDecl(NodeFormat_VarDecl(table.bytes, off), preChildren)
            case AnyDecl_MAIN_DECL => transMainDecl(NodeFormat_MainDecl(table.bytes, off), preChildren)
            case AnyDecl_FUNC_DECL => transFuncDecl(NodeFormat_FuncDecl(table.bytes, off), preChildren)
            case AnyDecl_TYPE_ALIAS_DECL => transTypeAlias(NodeFormat_TypeAliasDecl(table.bytes, off), preChildren)
            case AnyDecl_CLASS_DECL => transClassDecl(NodeFormat_ClassDecl(table.bytes, off), preChildren)
            case AnyDecl_STRUCT_DECL => transStructDecl(NodeFormat_StructDecl(table.bytes, off), preChildren)
            case AnyDecl_ENUM_DECL => transEnumDecl(NodeFormat_EnumDecl(table.bytes, off), preChildren)
            case AnyDecl_EXTEND_DECL => transExtendDecl(NodeFormat_ExtendDecl(table.bytes, off), preChildren)
            case AnyDecl_INTERFACE_DECL => transInterfaceDecl(NodeFormat_InterfaceDecl(table.bytes, off), preChildren)
            case AnyDecl_PROP_DECL => transPropDecl(NodeFormat_PropDecl(table.bytes, off), preChildren)
            case AnyDecl_PRIMARY_CTOR_DECL => transPrimaryCtorDecl(NodeFormat_PrimaryCtorDecl(table.bytes, off),
                preChildren)
            case AnyDecl_MACRO_DECL => transMacroDecl(NodeFormat_MacroDecl(table.bytes, off), preChildren)
            case AnyDecl_VAR_WITH_PATTERN_DECL => transVarWithPatternDecl(
                NodeFormat_VarWithPatternDecl(table.bytes, off), preChildren)
            case AnyDecl_FUNC_PARAM => transFuncParam(NodeFormat_FuncParam(table.bytes, off), preChildren)
            case AnyDecl_MACRO_EXPAND_DECL => transMacroExpandDecl(NodeFormat_MacroExpandDecl(table.bytes, off),
                preChildren)
            case _ => throw Exception("ParseException: The current version does not support this node.")
        }
    }

    private func transAnnotation(annotation: NodeFormat_Annotation): ?SyntaxNodeImpl {
        /* frist node add space to parentNode,*/
        addWhitespaceAndMoveCursorToBegin(annotation.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = annotation.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(nb) <- annotation.GetBase()) {
            let atKind = if (annotation.GetIsCompileTimeVisible()) {
                transBasicTerminal(nb.GetBegin(), SyntaxNodeKind.AtExclToken)
            } else {
                transBasicTerminal(nb.GetBegin(), SyntaxNodeKind.AtToken)
            }
        }
        transIdentifier(annotation.GetIdentPos(), annotation.GetIdentifier())
        transBasicTerminal(annotation.GetLeftSquarePos(), SyntaxNodeKind.LSquareToken)
        for (p in annotation.GetArgs()) {
            if (let Some(arg) <- p) {
                addWhitespaceAndMoveCursorToBegin(arg.GetBase())
                addChild(ret, transFuncArg(arg))
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(arg.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
        }
        if (let Some(cond) <- annotation.GetCondExpr()) {
            addWhitespaceAndMoveCursorToBegin(cond.GetBase())
            let argRet = ArrayList<SyntaxNodeImpl>()
            curChildren = argRet
            transNoTerminalExpr(cond)
            resetGlobalVariables(ret, innerCmts)
            addChild(ret, builder.buildNonTerminal(SyntaxNodeKind.Argument, argRet.toArray()))
        }
        let attrs = annotation.GetAttrs()
        let attrCommasPos = annotation.GetAttrCommasPos()
        for (i in 0..attrs.size) {
            if (let Some(v) <- attrs[i]) {
                let curPos = v.GetPos()
                addWhitespaceAndMoveCursor(curPos)
                let cur = match (getTokenKind(v.GetKind())) {
                    case TokenKind.IDENTIFIER =>
                        moveCursorString(curPos, v.GetValue())
                        builder.buildNonTerminal(SyntaxNodeKind.RefExpr,
                            [builder.buildValuedTerminal(SyntaxNodeKind.IdentToken, v.GetValue())])
                    case TokenKind.STRING_LITERAL => buildLineStringLiteral(nodeBase,
                        builder.buildValuedTerminal(SyntaxNodeKind.StringLiteralToken, v.GetValue()),
                        v.GetIsSingleQuote(), [])
                    case _ => builder.buildInvalidTerminal()
                }
                addChild(ret, builder.buildNonTerminal(SyntaxNodeKind.Argument, [cur]))
                if (i < attrCommasPos.size) {
                    transBasicTerminal(attrCommasPos[i], SyntaxNodeKind.CommaToken)
                }
            }
        }
        transBasicTerminal(annotation.GetRightSquarePos(), SyntaxNodeKind.RSquareToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.Annotation, ret.toArray())
    }

    private func transAnnotations(annotations: Array<Option<NodeFormat_Annotation>>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        for (annotation in annotations) {
            if (let Some(anno) <- annotation) {
                addChild(ret, transAnnotation(anno))
                curChildren = ret
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.AnnotationList, ret.toArray())
    }

    private func transModifier(begin: NodeFormat_Position, kind: SyntaxNodeKind): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        transBasicTerminal(begin, kind)

        builder.buildNonTerminal(SyntaxNodeKind.Modifier, ret.toArray())
    }

    private func transModifier(modifier: NodeFormat_Modifier): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(modifier.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = modifier.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let kind = getSyntaxImplKind(modifier.GetKind())
        addChild(ret, builder.buildBasicTerminal(kind))
        moveCursorToEnd(modifier.GetBase())
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.Modifier, ret.toArray())
    }

    private func transModifiers(modifiers: Array<Option<NodeFormat_Modifier>>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        for (modifier in modifiers) {
            if (let Some(mod) <- modifier) {
                // first node add space to parentNode
                addChild(ret, transModifier(mod))
                curChildren = ret
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.ModifierList, ret.toArray())
    }

    private func transVarDeclModifiers(modifiers: Array<Option<NodeFormat_Modifier>>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        for (modifier in modifiers) {
            if (let Some(mod) <- modifier && getSyntaxImplKind(mod.GetKind()) != SyntaxNodeKind.ConstToken) {
                // first node add space to parentNode())
                addChild(ret, transModifier(mod))
                curChildren = ret
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.ModifierList, ret.toArray())
    }

    private func transVarPattern4VarDecl(varDecl: NodeFormat_VarDecl): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()
        if (let Some(db) <- varDecl.GetBase()) {
            addWhitespaceAndMoveCursor(db.GetIdentifierPos())
            curChildren = ret
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
        }
        builder.buildNonTerminal(SyntaxNodeKind.VarBindingPattern, ret.toArray())
    }

    private func prepareVarDeclPrefix(base: Option<NodeFormat_DeclBase>) {
        let ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = base.getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- base) {
            // annotation
            let annos = db.GetAnnotations()
            if (annos.size != 0) {
                addChild(ret, transAnnotations(db.GetAnnotations()))
            } else {
                // The begin of variable declaration is not begin of annotations.
                addWhitespaceAndMoveCursorToBegin(db.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)

            // modifier
            let modifiers = db.GetModifiers()
            if (modifiers.size != 0) {
                addChild(ret, transVarDeclModifiers(modifiers))
                resetGlobalVariables(ret, innerCmts)
            }
        }

        return (ret, innerCmts, trailCmts)
    }

    private func appendVarDeclInitializer(initializer: Option<NodeFormat_Expr>, assignPos: NodeFormat_Position) {
        if (let Some(initializerExpr) <- initializer) {
            transBasicTerminal(assignPos, SyntaxNodeKind.AssignToken)
            transNoTerminalExpr(initializerExpr)
        }
    }

    private func appendTrailingComments(ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>, trailCmts: Array<Option<NodeFormat_CommentGroup>>) {
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
    }

    private func transDeclIdentifierAndTypeParams(db: NodeFormat_DeclBase, ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())

        if (let Some(generic) <- db.GetGeneric()) {
            let typeParameters = generic.GetTypeParameters()
            if (typeParameters.size != 0) {
                addChild(ret, transTypeArguments(typeParameters, generic.GetLeftAnglePos(), generic.GetRightAnglePos()))
            }
        }
        resetGlobalVariables(ret, innerCmts)
    }

    private func transDeclAnnotationsAndModifiers(db: NodeFormat_DeclBase, ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        let annos = db.GetAnnotations()
        if (annos.size != 0) {
            addChild(ret, transAnnotations(annos))
        } else {
            addWhitespaceAndMoveCursorToBegin(db.GetBase())
        }
        resetGlobalVariables(ret, innerCmts)

        let modifiers = db.GetModifiers()
        if (modifiers.size != 0) {
            addChild(ret, transModifiers(modifiers))
            resetGlobalVariables(ret, innerCmts)
        }
    }

    private func finishFuncBodyBlockAndComments(body: Option<NodeFormat_FuncBody>, ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>, trailCmts: Array<Option<NodeFormat_CommentGroup>>) {
        if (let Some(funcBody) <- body) {
            resetGlobalVariables(ret, innerCmts)
            if (let Some(block) <- funcBody.GetBody()) {
                addChild(ret, transBlock(block))
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
    }

    private func transBitAndSeparatedTypes(types: Array<Option<NodeFormat_Type>>, ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        for (i in 0..types.size) {
            if (let Some(ty) <- types[i]) {
                transType(ty)
                resetGlobalVariables(ret, innerCmts)
                if (i < types.size - 1 && let Some(base) <- ty.GetBase()) {
                    transBasicTerminal(base.GetBitAndPos(), SyntaxNodeKind.BitAndToken)
                }
            }
        }
        resetGlobalVariables(ret, innerCmts)
    }

    private func transVarDecl(varDecl: NodeFormat_VarDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let (ret, innerCmts, trailCmts) = prepareVarDeclPrefix(varDecl.GetBase())

        if (let Some(db) <- varDecl.GetBase()) {
            if (!varDecl.GetEmptyKeyword()) {
                if (varDecl.GetIsVar()) {
                    transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.VarToken)
                } else if (db.GetIsConst()) {
                    transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.ConstToken)
                } else {
                    transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.LetToken)
                }
            }
            addChild(ret, transVarPattern4VarDecl(varDecl))
            resetGlobalVariables(ret, innerCmts)
            if (let Some(ty) <- varDecl.GetType()) {
                transBasicTerminal(varDecl.GetColonPos(), SyntaxNodeKind.ColonToken)
                transType(ty)
                curChildren = ret
            }
        }
        resetGlobalVariables(ret, innerCmts)
        appendVarDeclInitializer(varDecl.GetInitializer(), varDecl.GetAssignPos())
        appendTrailingComments(ret, innerCmts, trailCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.VarDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transVarWithPatternDecl(varDecl: NodeFormat_VarWithPatternDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let (ret, innerCmts, trailCmts) = prepareVarDeclPrefix(varDecl.GetBase())

        if (let Some(db) <- varDecl.GetBase()) {
            if (varDecl.GetIsVar()) {
                transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.VarToken)
            } else if (db.GetIsConst()) {
                transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.ConstToken)
            } else {
                transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.LetToken)
            }
            if (let Some(pattern) <- varDecl.GetPattern()) {
                addChild(ret, transPattern(pattern))
            }
            resetGlobalVariables(ret, innerCmts)
            if (let Some(ty) <- varDecl.GetType()) {
                transBasicTerminal(varDecl.GetColonPos(), SyntaxNodeKind.ColonToken)
                transType(ty)
                resetGlobalVariables(ret, innerCmts)
            }
        }
        resetGlobalVariables(ret, innerCmts)
        appendVarDeclInitializer(varDecl.GetInitializer(), varDecl.GetAssignPos())
        appendTrailingComments(ret, innerCmts, trailCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.VarDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transMainDecl(mainDecl: NodeFormat_MainDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = mainDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- mainDecl.GetBase()) {
            addWhitespaceAndMoveCursorToBegin(db.GetBase())
            resetGlobalVariables(ret, innerCmts)
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.MainToken)
        }
        if (let Some(body) <- mainDecl.GetFuncBody()) {
            // functionParameters
            if (let Some(paramList) <- body.GetParamList()) {
                addChild(ret, transParamList(paramList))
                moveCursorToEnd(paramList.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)
            if (let Some(ty) <- body.GetRetType()) {
                transBasicTerminal(body.GetColonPos(), SyntaxNodeKind.ColonToken)
                transType(ty)
                resetGlobalVariables(ret, innerCmts)
            }
            // block
            if (let Some(block) <- body.GetBody()) {
                addChild(ret, transBlock(block))
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MainDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transTypeAlias(typeAlias: NodeFormat_TypeAliasDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = typeAlias.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- typeAlias.GetBase()) {
            // annotation
            let annos = db.GetAnnotations()
            if (annos.size != 0) {
                addChild(ret, transAnnotations(db.GetAnnotations()))
            } else {
                // The begin of TypeAlias is not begin of annotations
                addWhitespaceAndMoveCursorToBegin(db.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)
            // modifier
            let modifiers = db.GetModifiers()
            if (modifiers.size != 0) {
                if (!db.GetIsConst() || modifiers.size > 1) {
                    addChild(ret, transModifiers(modifiers))
                    resetGlobalVariables(ret, innerCmts)
                }
            }

            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.TypeToken)
            transDeclIdentifierAndTypeParams(db, ret, innerCmts)
        }

        transBasicTerminal(typeAlias.GetAssignPos(), SyntaxNodeKind.AssignToken)
        if (let Some(ty) <- typeAlias.GetType()) {
            transType(ty)
        }
        resetGlobalVariables(ret, innerCmts)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TypeAlias, ret.toArray(), preChildren: preChildren)
    }

    private func transClassBody(nodeBase: ?NodeFormat_NodeBase, decls: Array<Option<NodeFormat_Decl>>,
        lcurlPos: NodeFormat_Position, rcurlPos: NodeFormat_Position): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        addWhitespaceAndMoveCursor(lcurlPos)
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(lcurlPos, SyntaxNodeKind.LCurlToken)

        for (decl in decls) {
            if (let Some(dl) <- decl) {
                addChild(ret, transDecl(dl))
                resetGlobalVariables(ret, innerCmts)
            }
        }
        innerComments = innerCmts
        transBasicTerminal(rcurlPos, SyntaxNodeKind.RCurlToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.Body, ret.toArray())
    }

    private func transClassBody(decls: Array<Option<NodeFormat_Decl>>, lcurlPos: NodeFormat_Position,
        rcurlPos: NodeFormat_Position): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        // add prefix whitespace and move cursor
        addWhitespaceAndMoveCursor(lcurlPos)
        curChildren = ret
        transBasicTerminal(lcurlPos, SyntaxNodeKind.LCurlToken)

        for (decl in decls) {
            if (let Some(dl) <- decl) {
                addChild(ret, transDecl(dl))
                curChildren = ret
            }
        }
        transBasicTerminal(rcurlPos, SyntaxNodeKind.RCurlToken)
        builder.buildNonTerminal(SyntaxNodeKind.Body, ret.toArray())
    }

    private func transPrimaryCtorDecl(primaryCtorDecl: NodeFormat_PrimaryCtorDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = primaryCtorDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- primaryCtorDecl.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)

            // identifier
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
        }

        if (let Some(body) <- primaryCtorDecl.GetFuncBody()) {
            if (let Some(paramList) <- body.GetParamList()) {
                addChild(ret, transParamList(paramList))
                moveCursorToEnd(paramList.GetBase())
            }
        }
        finishFuncBodyBlockAndComments(primaryCtorDecl.GetFuncBody(), ret, innerCmts, trailCmts)
        builder.buildNonTerminal(SyntaxNodeKind.FuncDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transClassDecl(classDecl: NodeFormat_ClassDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = classDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- classDecl.GetBase()) {
            // annotation
            if (db.GetAnnotations().size != 0) {
                addChild(ret, transAnnotations(db.GetAnnotations()))
            } else {
                addWhitespaceAndMoveCursorToBegin(db.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)
            // modifier
            if (db.GetModifiers().size != 0) {
                addChild(ret, transModifiers(db.GetModifiers()))
                resetGlobalVariables(ret, innerCmts)
            }
            // ClassToken
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.ClassToken)

            // identifier
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())

            if (let Some(generic) <- db.GetGeneric() && generic.GetTypeParameters().size != 0) {
                addChild(ret,
                    transTypeArguments(generic.GetTypeParameters(), generic.GetLeftAnglePos(),
                        generic.GetRightAnglePos()))
            }
            resetGlobalVariables(ret, innerCmts)
        }

        transBasicTerminal(classDecl.GetUpperBoundPos(), SyntaxNodeKind.UpperBoundToken)

        let superTypes = classDecl.GetSuperTypes()
        transBitAndSeparatedTypes(superTypes, ret, innerCmts)

        if (let Some(db) <- classDecl.GetBase() && let Some(generic) <- db.GetGeneric() &&
            generic.GetGenericConstraints().size != 0) {
            addChild(ret, transGenericConstraints(generic.GetGenericConstraints()))
            resetGlobalVariables(ret, innerCmts)
        }

        if (let Some(body) <- classDecl.GetBody()) {
            addChild(ret, transClassBody(body.GetBase(), body.GetDecls(), body.GetLeftCurlPos(), body.GetRightCurlPos()))
            resetGlobalVariables(ret, innerCmts)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ClassDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transStructDecl(structDecl: NodeFormat_StructDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = structDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- structDecl.GetBase()) {
            // annotation
            let annos = db.GetAnnotations()
            if (annos.size != 0) {
                addChild(ret, transAnnotations(db.GetAnnotations()))
            } else {
                addWhitespaceAndMoveCursorToBegin(db.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)
            // modifier
            if (db.GetModifiers().size != 0) {
                addChild(ret, transModifiers(db.GetModifiers()))
                resetGlobalVariables(ret, innerCmts)
            }
            // func
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.StructToken)

            // identifier
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())

            if (let Some(generic) <- db.GetGeneric() && generic.GetTypeParameters().size != 0) {
                addChild(ret,
                    transTypeArguments(generic.GetTypeParameters(), generic.GetLeftAnglePos(),
                        generic.GetRightAnglePos()))
            }
            resetGlobalVariables(ret, innerCmts)
        }

        transBasicTerminal(structDecl.GetUpperBoundPos(), SyntaxNodeKind.UpperBoundToken)

        let superTypes = structDecl.GetSuperTypes()
        transBitAndSeparatedTypes(superTypes, ret, innerCmts)

        if (let Some(db) <- structDecl.GetBase() && let Some(generic) <- db.GetGeneric() &&
            generic.GetGenericConstraints().size > 0) {
            addChild(ret, transGenericConstraints(generic.GetGenericConstraints()))
            resetGlobalVariables(ret, innerCmts)
        }

        if (let Some(body) <- structDecl.GetBody()) {
            addChild(ret, transClassBody(body.GetBase(), body.GetDecls(), body.GetLeftCurlPos(), body.GetRightCurlPos()))
            resetGlobalVariables(ret, innerCmts)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.StructDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transInterfaceDecl(interfaceDecl: NodeFormat_InterfaceDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = interfaceDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- interfaceDecl.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)
            // func
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.InterfaceToken)
            transDeclIdentifierAndTypeParams(db, ret, innerCmts)
        }

        transBasicTerminal(interfaceDecl.GetUpperBoundPos(), SyntaxNodeKind.UpperBoundToken)

        let superTypes = interfaceDecl.GetSuperTypes()
        for (i in 0..superTypes.size) {
            if (let Some(anno) <- superTypes[i]) {
                transType(anno)
                resetGlobalVariables(ret, innerCmts)
                if (let Some(base) <- anno.GetBase()) {
                    transBasicTerminal(base.GetBitAndPos(), SyntaxNodeKind.BitAndToken)
                }
            }
        }

        if (let Some(db) <- interfaceDecl.GetBase()) {
            if (let Some(generic) <- db.GetGeneric()) {
                let genericConstraints = generic.GetGenericConstraints();
                if (genericConstraints.size != 0) {
                    addChild(ret, transGenericConstraints(genericConstraints))
                }
                resetGlobalVariables(ret, innerCmts)
            }
        }

        if (let Some(body) <- interfaceDecl.GetBody()) {
            let declList = body.GetDecls()
            addChild(ret, transClassBody(body.GetBase(), declList, body.GetLeftCurlPos(), body.GetRightCurlPos()))
            resetGlobalVariables(ret, innerCmts)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.InterfaceDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transExtendDecl(extendDecl: NodeFormat_ExtendDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = extendDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- extendDecl.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)
            // extend
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.ExtendToken)

            if (let Some(generic) <- db.GetGeneric()) {
                let typeParameters = generic.GetTypeParameters()
                if (typeParameters.size != 0) {
                    addChild(ret,
                        transTypeArguments(typeParameters, generic.GetLeftAnglePos(), generic.GetRightAnglePos()))
                }
            }
            resetGlobalVariables(ret, innerCmts)
        }

        if (let Some(extendType) <- extendDecl.GetExtendedType()) {
            transType(extendType)
            resetGlobalVariables(ret, innerCmts)
        }

        transBasicTerminal(extendDecl.GetUpperBoundPos(), SyntaxNodeKind.UpperBoundToken)

        let superTypes = extendDecl.GetInterfaces()
        for (i in 0..superTypes.size) {
            if (let Some(anno) <- superTypes[i]) {
                transType(anno)
                resetGlobalVariables(ret, innerCmts)
                if (let Some(base) <- anno.GetBase()) {
                    transBasicTerminal(base.GetBitAndPos(), SyntaxNodeKind.BitAndToken)
                }
            }
        }

        if (let Some(db) <- extendDecl.GetBase()) {
            if (let Some(generic) <- db.GetGeneric()) {
                let genericConstraints = generic.GetGenericConstraints();
                if (genericConstraints.size != 0) {
                    addChild(ret, transGenericConstraints(genericConstraints))
                }
                resetGlobalVariables(ret, innerCmts)
            }
        }

        let memberDecls = extendDecl.GetMembers()
        addChild(ret, transClassBody(memberDecls, extendDecl.GetLeftCurlPos(), extendDecl.GetRightCurlPos()))
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ExtendDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transEnumBody(enumDecl: NodeFormat_EnumDecl, decls: Array<Option<NodeFormat_Decl>>,
        constructors: Array<Option<NodeFormat_Decl>>, lcurlPos: NodeFormat_Position, rcurlPos: NodeFormat_Position): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        let innerCmts = innerComments
        // add prefix whitespace and move cursor
        addWhitespaceAndMoveCursor(lcurlPos)
        curChildren = ret
        transBasicTerminal(lcurlPos, SyntaxNodeKind.LCurlToken)

        let constructorSize = constructors.size
        let bitOrTokenSize = enumDecl.GetBitOrPosVec().size
        var bitFirstFlag = false
        if (bitOrTokenSize > constructorSize || (bitOrTokenSize == constructorSize && !enumDecl.GetHasEllipsis())) {
            bitFirstFlag = true
        }

        let cons = getElements<NodeFormat_Decl>(constructors)
        for (i in 0..cons.size) {
            // | Enum | Enum2 | ...
            if (bitFirstFlag) {
                if (i < enumDecl.GetBitOrPosVec().size) {
                    transBasicTerminal(enumDecl.GetBitOrPosVec()[i], SyntaxNodeKind.BitOrToken)
                }
                addChild(ret, transEnumConstructor(cons[i]))
                innerComments = innerCmts
                curChildren = ret
            } else {
                // Enum | Enum2 | Enum3 | ...
                addChild(ret, transEnumConstructor(cons[i]))
                innerComments = innerCmts
                curChildren = ret
                if (i < enumDecl.GetBitOrPosVec().size) {
                    transBasicTerminal(enumDecl.GetBitOrPosVec()[i], SyntaxNodeKind.BitOrToken)
                }
            }
        }

        if (enumDecl.GetHasEllipsis()) {
            if (bitFirstFlag) {
                transBasicTerminal(enumDecl.GetBitOrPosVec()[bitOrTokenSize - 1], SyntaxNodeKind.BitOrToken)
            }
            transBasicTerminal(enumDecl.GetEllipsisPos(), SyntaxNodeKind.EllipsisToken)
        }

        for (decl in decls) {
            if (let Some(dl) <- decl) {
                addChild(ret, transDecl(dl))
                innerComments = innerCmts
                curChildren = ret
            }
        }

        transBasicTerminal(rcurlPos, SyntaxNodeKind.RCurlToken)
        builder.buildNonTerminal(SyntaxNodeKind.Body, ret.toArray())
    }

    private func transEnumDecl(enumDecl: NodeFormat_EnumDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = enumDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- enumDecl.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)
            // func
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.EnumToken)
            transDeclIdentifierAndTypeParams(db, ret, innerCmts)
        }

        transBasicTerminal(enumDecl.GetUpperBoundPos(), SyntaxNodeKind.UpperBoundToken)

        let superTypes = enumDecl.GetSuperInterfaceTypes()
        for (i in 0..superTypes.size) {
            if (let Some(anno) <- superTypes[i]) {
                transType(anno)
                resetGlobalVariables(ret, innerCmts)
                if (let Some(base) <- anno.GetBase()) {
                    transBasicTerminal(base.GetBitAndPos(), SyntaxNodeKind.BitAndToken)
                }
            }
        }

        if (let Some(db) <- enumDecl.GetBase()) {
            if (let Some(generic) <- db.GetGeneric()) {
                let genericConstraints = generic.GetGenericConstraints();
                if (genericConstraints.size != 0) {
                    addChild(ret, transGenericConstraints(genericConstraints))
                }
                resetGlobalVariables(ret, innerCmts)
            }
        }

        var memberDecls = enumDecl.GetMembers()
        var constructors = enumDecl.GetConstructors()
        addChild(ret,
            transEnumBody(enumDecl, memberDecls, constructors, enumDecl.GetLeftCurlPos(), enumDecl.GetRightCurlPos()))
        resetGlobalVariables(ret, innerCmts)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.EnumDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transEnumConstructor(enumConstructor: NodeFormat_Decl): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = enumConstructor.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts
        let astKind: String = nodeBase.getOrThrow().GetAstKind()
        if (astKind == "macro_expand_decl") {
            let table = enumConstructor.table
            let off: UInt32 = UInt32(table.offset(enumConstructor.DECL)) + table.pos
            return transMacroExpandDecl(NodeFormat_MacroExpandDecl(table.bytes, off), Array<SyntaxNodeImpl>(),
                isEnumConstructor: true)
        }
        if (let Some(db) <- enumConstructor.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)

            // identifier
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
        }

        if (let Some(funcDecl) <- enumConstructor.GetDeclAsFuncDecl() && let Some(body) <- funcDecl.GetFuncBody() && let Some(paramList) <- body
            .GetParamList()) {
            let bodyBase = body.GetBase()
            // EnumConstructor body has no innerComments
            let (leadBodyCmts, _, trailBodyCmts) = getCommentGroups(bodyBase)
            addLeadingComments(bodyBase, ret, leadBodyCmts)

            let paramBase = paramList.GetBase()
            // EnumConstructor paramList has no innerComments
            let (leadParamListCmts, _, trailParamListCmts) = getCommentGroups(paramBase)
            addLeadingComments(paramBase, ret, leadParamListCmts)
            transBasicTerminal(paramList.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

            let params = paramList.GetParams()
            for (param in getElements<NodeFormat_FuncParam>(params)) {
                let paramNodeBase = param.GetNodeBase()
                let (leadParamCmts, _, trailParamCmts) = getCommentGroups(paramNodeBase)
                trailComments = trailParamCmts
                // save leadingComments to temp ret, add to typeAnnotation node later
                addLeadingComments(paramNodeBase, leadCommentNodes, leadParamCmts)
                resetGlobalVariables(ret, innerCmts)
                // type
                if (let Some(vb) <- param.GetBase() && let Some(ty) <- vb.GetType()) {
                    transType(ty)
                    resetGlobalVariables(ret, innerCmts)
                }
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(param.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
            transBasicTerminal(paramList.GetRightParenPos(), SyntaxNodeKind.RParenToken)
            if (trailParamListCmts.size > 0) {
                addChild(ret, transCommentGroupList(trailParamListCmts))
                resetGlobalVariables(ret, innerCmts)
            }
            if (trailBodyCmts.size > 0) {
                addChild(ret, transCommentGroupList(trailBodyCmts))
                resetGlobalVariables(ret, innerCmts)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.EnumConstructor, ret.toArray())
    }

    private func transPropDecl(propDecl: NodeFormat_PropDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = propDecl.GetBase().getOrThrow().GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(varDecl) <- propDecl.GetBase() && let Some(db) <- varDecl.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)
            // prop
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.PropToken)
            // identifier
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
            transBasicTerminal(propDecl.GetColonPos(), SyntaxNodeKind.ColonToken)

            if (let Some(ty) <- varDecl.GetType()) {
                transType(ty)
                resetGlobalVariables(ret, innerCmts)
            }
            transBasicTerminal(propDecl.GetLeftCurlPos(), SyntaxNodeKind.LCurlToken)

            var getters = propDecl.GetGetters()
            if (getters.size != 0) {
                if (let Some(getter) <- getters[0]) {
                    addChild(ret, transFuncDecl(getter))
                    resetGlobalVariables(ret, innerCmts)
                }
            }
            var setters = propDecl.GetSetters()
            if (setters.size != 0) {
                if (let Some(setter) <- setters[0]) {
                    addChild(ret, transFuncDecl(setter))
                    resetGlobalVariables(ret, innerCmts)
                }
            }
            transBasicTerminal(propDecl.GetRightCurlPos(), SyntaxNodeKind.RCurlToken)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.PropDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transMacroDecl(macroDecl: NodeFormat_MacroDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()

        let nodeBase = macroDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- macroDecl.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)
            transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.MacroToken)
            // identifier
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
        }

        if (let Some(body) <- macroDecl.GetFuncBody()) {
            if (let Some(paramList) <- body.GetParamList()) {
                addChild(ret, transParamList(paramList))
                moveCursorToEnd(paramList.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)

            if (let Some(ty) <- body.GetRetType() && isValidPosition(body.GetColonPos())) {
                // :
                transBasicTerminal(body.GetColonPos(), SyntaxNodeKind.ColonToken)
                // type
                transType(ty)
            }
        }
        finishFuncBodyBlockAndComments(macroDecl.GetFuncBody(), ret, innerCmts, trailCmts)
        builder.buildNonTerminal(SyntaxNodeKind.MacroDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transTokenList(tokenArray: Array<Option<NodeFormat_Token>>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret
        for (tk in tokenArray) {
            if (let Some(v) <- tk) {
                transTokenTerminal(v.GetPos(), getTokenKind(v.GetKind()), v.GetValue(), needNewLine: true,
                    delimiterNum: v.GetDelimiterNum(), isSingleQuote: v.GetIsSingleQuote(), hasEscape: v.GetHasEscape())
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.TokenList, ret.toArray())
    }

    private func transSymbolRef4Invocation(invocation: NodeFormat_MacroInvocation): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret
        transIdentifier(invocation.GetIdentifierPos(), invocation.GetFullName())

        builder.buildNonTerminal(SyntaxNodeKind.RefExpr, ret.toArray())
    }

    private func transMacroInvocationCalleeAttrsAndParenArgs(invocation: NodeFormat_MacroInvocation,
        ret: ArrayList<SyntaxNodeImpl>, innerCmts: Array<Option<NodeFormat_CommentGroup>>): Bool {
        addChild(ret, transSymbolRef4Invocation(invocation))
        resetGlobalVariables(ret, innerCmts)

        transBasicTerminal(invocation.GetLeftSquarePos(), SyntaxNodeKind.LSquareToken)

        addChild(ret, transTokenList(invocation.GetAttrs()))
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(invocation.GetRightSquarePos(), SyntaxNodeKind.RSquareToken)

        if (invocation.GetHasParenthesis()) {
            transBasicTerminal(invocation.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

            addChild(ret, transTokenList(invocation.GetArgs()))
            resetGlobalVariables(ret, innerCmts)

            transBasicTerminal(invocation.GetRightParenPos(), SyntaxNodeKind.RParenToken)
            return true
        }
        return false
    }

    private func createArgumentTokens(invocation: NodeFormat_MacroInvocation) {
        var argTokens = Tokens()
        var position = invocation.GetAtPos()
        let atExcl = Token(TokenKind.AT_EXCL).addPosition(position.fileId, position.line, position.column)
        argTokens.append(atExcl)

        position = invocation.GetIdentifierPos()
        let identifier = Token(TokenKind.IDENTIFIER, invocation.GetIdentifier()).addPosition(position.fileId,
            position.line, position.column)
        argTokens.append(identifier)

        position = invocation.GetLeftSquarePos()
        let lSquare = Token(TokenKind.LSQUARE).addPosition(position.fileId, position.line, position.column)
        argTokens.append(lSquare)

        for (tk in invocation.GetAttrs()) {
            if (let Some(v) <- tk) {
                position = v.GetPos()
                argTokens.append(
                    Token(getTokenKind(v.GetKind()), v.GetValue()).addPosition(position.fileId, position.line,
                        position.column))
            }
        }

        position = invocation.GetRightSquarePos()
        let rSquare = Token(TokenKind.RSQUARE).addPosition(position.fileId, position.line, position.column)
        argTokens.append(rSquare)
        return argTokens
    }

    func createCustomAnnotation(invocation: NodeFormat_MacroInvocation): ?NodeFormat_Annotation {
        let argTokens = createArgumentTokens(invocation)
        let node = unsafe {
            try {
                parse(argTokens, {p: CPointer<UInt8> => return CJ_ParseAnnotationArguments(p)})
            } catch (e: Exception) {
                throw Exception("\n" + e.message + "parsing custom annotation error.")
            }
        }
        return node.GetRootAsAnnotation()
    }

    private func transDeclWithAtExclAnnotation(annos: Array<Option<NodeFormat_Annotation>>,
        invocation: NodeFormat_MacroInvocation, leadCmts: Array<Option<NodeFormat_CommentGroup>>,
        trailCmts: Array<Option<NodeFormat_CommentGroup>>, isEnumConstructor!: Bool = false): ?SyntaxNodeImpl {
        // BNF: (former annos)? atExcel decl
        let tmpInnerComments = innerComments
        // transAnnotationList
        var formerAnnos = transAnnotations(annos)
        innerComments = tmpInnerComments
        if (let Some(former) <- formerAnnos && let Some(formerAnno) <- (former as NonTerminal) && let Some(v) <- createCustomAnnotation(
            invocation)) {
            // transAtExcl and add to AnnotationList
            let ret = ArrayList<SyntaxNodeImpl>(formerAnno.children)
            if (ret.size > 0) {
                curChildren = ret
            }
            addChild(ret, transAnnotation(v))
            innerComments = tmpInnerComments
            formerAnnos = builder.buildNonTerminal(SyntaxNodeKind.AnnotationList, ret.toArray())
        }

        // store space and newLine before decl
        var retBefore = ArrayList<SyntaxNodeImpl>()
        curChildren = retBefore
        // transDecl
        // merge formerAnnos and atExcel and into decl
        let declNodeImpl: ?SyntaxNodeImpl = if (let Some(dl) <- invocation.GetDecl()) {
            if (isEnumConstructor) {
                transEnumConstructor(dl)
            } else {
                transDecl(dl)
            }
        } else {
            None
        }
        if (let Some(dl) <- declNodeImpl && let Some(nt) <- (dl as NonTerminal) && nt.children.size != 0) {
            var ret = ArrayList<SyntaxNodeImpl>(nt.children)
            if (let Some(annos) <- formerAnnos && let Some(formers) <- (annos as NonTerminal)) {
                if (ret[0].kind == SyntaxNodeKind.AnnotationList && let Some(annoList) <- (ret[0] as NonTerminal)) {
                    let firstChildRet = ArrayList<SyntaxNodeImpl>(annoList.children)
                    // already have a annoList, merge formerAnnotations init annoList
                    // add space and newLine first           
                    firstChildRet.add(all: retBefore, at: 0)
                    // add new annoList
                    firstChildRet.add(all: formers.children, at: 0)
                    ret[0] = builder.buildNonTerminal(SyntaxNodeKind.AnnotationList, firstChildRet.toArray())
                } else {
                    // not have a annoList, add formerAnnos to decl
                    // add space and newLine first
                    ret.add(all: retBefore, at: 0)
                    // add new annoList
                    ret.add(annos, at: 0)
                }
            }
            if (leadCmts.size > 0) {
                // add space and newLine first           
                ret.add(all: retBefore, at: 0)
                // add new annoList
                ret.add(transCommentGroupList(leadCmts).getOrThrow(), at: 0)
            }
            moveCursorToEnd(invocation.GetDecl().getOrThrow().GetBase().getOrThrow().GetBase())
            if (trailCmts.size > 0) {
                addChild(ret, transCommentGroupList(trailCmts))
            }
            return builder.buildNonTerminal(nt.kind, ret.toArray())
        }
        return None
    }

    private func transMacroExpandDecl(macroExpandDecl: NodeFormat_MacroExpandDecl, preChildren: Array<SyntaxNodeImpl>,
        isEnumConstructor!: Bool = false): ?SyntaxNodeImpl {
        let nodeBase = macroExpandDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        innerComments = innerCmts

        // if AtExcl, trans macro  to annotation
        if (let Some(db) <- macroExpandDecl.GetBase() && let Some(invocation) <- macroExpandDecl.GetInvocation() &&
            invocation.GetIsCompileTimeVisible()) {
            return transDeclWithAtExclAnnotation(db.GetAnnotations(), invocation, leadCmts, trailCmts,
                isEnumConstructor: isEnumConstructor)
        }

        var ret = ArrayList<SyntaxNodeImpl>()

        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(db) <- macroExpandDecl.GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)
        }

        if (let Some(invocation) <- macroExpandDecl.GetInvocation()) {
            transBasicTerminal(invocation.GetAtPos(), SyntaxNodeKind.AtToken)

            let hasParenthesizedArgs = transMacroInvocationCalleeAttrsAndParenArgs(invocation, ret, innerCmts)
            if (!hasParenthesizedArgs) {
                if (let Some(dl) <- invocation.GetDecl()) {
                    if (isEnumConstructor) {
                        addChild(ret, transEnumConstructor(dl))
                    } else {
                        addChild(ret, transDecl(dl))
                    }
                    resetGlobalVariables(ret, innerCmts)
                }
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MacroExpandDecl, ret.toArray(), preChildren: preChildren)
    }

    private func transMacroExpandParam(macroExpandParam: NodeFormat_MacroExpandParam): ?SyntaxNodeImpl {
        let nodeBase = macroExpandParam.GetBase().getOrThrow().GetNodeBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        innerComments = innerCmts

        // if AtExcl, trans macro  to annotation
        if (let Some(funcParam) <- macroExpandParam.GetBase() && let Some(varDecl) <- funcParam.GetBase() && let Some(db) <- varDecl
            .GetBase() && let Some(invocation) <- macroExpandParam.GetInvocation() &&
            invocation.GetIsCompileTimeVisible()) {
            return transDeclWithAtExclAnnotation(db.GetAnnotations(), invocation, leadCmts, trailCmts)
        }

        var ret = ArrayList<SyntaxNodeImpl>()

        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(funcParam) <- macroExpandParam.GetBase() && let Some(varDecl) <- funcParam.GetBase() && let Some(db) <- varDecl
            .GetBase()) {
            transDeclAnnotationsAndModifiers(db, ret, innerCmts)
        }

        if (let Some(invocation) <- macroExpandParam.GetInvocation()) {
            transBasicTerminal(invocation.GetAtPos(), SyntaxNodeKind.AtToken)
            resetGlobalVariables(ret, innerCmts)

            let hasParenthesizedArgs = transMacroInvocationCalleeAttrsAndParenArgs(invocation, ret, innerCmts)
            if (!hasParenthesizedArgs) {
                if (let Some(decl) <- invocation.GetDecl() && let Some(param) <- decl.GetDeclAsFuncParam()) {
                    addChild(ret, transFuncParam(param))
                    resetGlobalVariables(ret, innerCmts)
                }
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MacroExpandParam, ret.toArray())
    }

    private func transMacroExpandExpr(macroExpandExpr: NodeFormat_MacroExpandExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(macroExpandExpr.GetBase())
        var ret = ArrayList<SyntaxNodeImpl>()
        curChildren = ret

        let nodeBase = macroExpandExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(invocation) <- macroExpandExpr.GetInvocation()) {
            transBasicTerminal(invocation.GetAtPos(), SyntaxNodeKind.AtToken)
            resetGlobalVariables(ret, innerCmts)

            let hasParenthesizedArgs = transMacroInvocationCalleeAttrsAndParenArgs(invocation, ret, innerCmts)
            if (!hasParenthesizedArgs) {
                if (let Some(dl) <- invocation.GetDecl()) {
                    addChild(ret, transDecl(dl))
                    resetGlobalVariables(ret, innerCmts)
                }
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MacroExpandExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transGenericConstraint(constraint: NodeFormat_GenericConstraint): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = constraint.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(ty) <- constraint.GetType()) {
            if (let Some(tyBase) <- ty.GetBase()) {
                addWhitespaceAndMoveCursorToBegin(tyBase.GetBase())
                resetGlobalVariables(ret, innerCmts)
                addChild(ret, transRefType(ty))
                moveCursorToEnd(tyBase.GetBase())
            }
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(constraint.GetOperatorPos(), SyntaxNodeKind.UpperBoundToken)
        let upperBounds = constraint.GetUpperBound()
        let bitAndPos = constraint.GetBitAndPosVec()
        if (upperBounds.size != bitAndPos.size + 1) {
            return None
        }
        for (i in 0..upperBounds.size) {
            if (let Some(upperBound) <- upperBounds[i]) {
                transType(upperBound)
                resetGlobalVariables(ret, innerCmts)
                if (i < bitAndPos.size) {
                    transBasicTerminal(bitAndPos[i], SyntaxNodeKind.BitAndToken)
                }
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.GenericConstraint, ret.toArray())
    }

    private func transGenericConstraints(genericConstraints: Array<Option<NodeFormat_GenericConstraint>>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        var whereFlag = true
        for (genericConstraint in genericConstraints) {
            if (let Some(constraint) <- genericConstraint) {
                addWhitespaceAndMoveCursorToBegin(constraint.GetBase())
                if (whereFlag) {
                    curChildren = ret
                    ret.add(builder.buildBasicTerminal(SyntaxNodeKind.WhereToken))
                    moveCursorColumn(constraint.GetWherePos(), SyntaxNodeKind.WhereToken.toString().size)
                    whereFlag = false
                }
                addChild(ret, transGenericConstraint(constraint))
                curChildren = ret
                transBasicTerminal(constraint.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.GenericConstraints, ret.toArray())
    }

    private func transGenericParam(param: NodeFormat_GenericParamDecl): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(param.GetBase().getOrThrow().GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = param.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- param.GetBase()) {
            transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
        }
        resetGlobalVariables(ret, innerCmts)

        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.GenericParam, ret.toArray())
    }

    private func transTypeArguments(typeParameters: Array<Option<NodeFormat_GenericParamDecl>>,
        ltPos: NodeFormat_Position, gtPos: NodeFormat_Position): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        addWhitespace(ltPos)
        curChildren = ret

        transBasicTerminal(ltPos, SyntaxNodeKind.LtToken)
        for (typeParameter in typeParameters) {
            if (let Some(genericTy) <- typeParameter) {
                addChild(ret, transGenericParam(genericTy))
                curChildren = ret

                transBasicTerminal(genericTy.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
        }
        transBasicTerminal(gtPos, SyntaxNodeKind.GtToken)
        builder.buildNonTerminal(SyntaxNodeKind.TypeArguments, ret.toArray())
    }

    private func transTypeArguments(typeParameters: Array<Option<NodeFormat_Type>>, ltPos: NodeFormat_Position,
        gtPos: NodeFormat_Position): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        addWhitespace(ltPos)
        curChildren = ret
        transBasicTerminal(ltPos, SyntaxNodeKind.LtToken)
        for (typeParameter in typeParameters) {
            if (let Some(ty) <- typeParameter) {
                transType(ty)
                curChildren = ret
                if (let Some(tb) <- ty.GetBase()) {
                    transBasicTerminal(tb.GetCommaPos(), SyntaxNodeKind.CommaToken)
                }
            }
        }
        transBasicTerminal(gtPos, SyntaxNodeKind.GtToken)
        builder.buildNonTerminal(SyntaxNodeKind.TypeArguments, ret.toArray())
    }

    private func findStatic(modifiers: Array<Option<NodeFormat_Modifier>>): Bool {
        for (modifier in modifiers) {
            if (let Some(mod) <- modifier) {
                if (mod.GetKind() == 118) { //find static
                    return true
                }
            }
        }
        return false
    }

    func transFuncHeader(funcDecl: NodeFormat_FuncDecl, ret: ArrayList<SyntaxNodeImpl>, nodeKind: SyntaxNodeKind,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        var identifier = ""
        var modifiers = Array<Option<NodeFormat_Modifier>>()
        var kind = nodeKind

        if (let Some(db) <- funcDecl.GetBase()) {
            modifiers = db.GetModifiers()
            identifier = db.GetIdentifier()
            if (funcDecl.GetIsGetter() || funcDecl.GetIsSetter()) {
                kind = SyntaxNodeKind.PropGetterOrSetter
            } else if (identifier == "init" && findStatic(modifiers)) {
                kind = SyntaxNodeKind.StaticInit
            }
            // annotation
            if (db.GetAnnotations().size != 0) {
                addChild(ret, transAnnotations(db.GetAnnotations()))
            } else {
                // The begin of FuncDecl is not begin of annotations
                addWhitespaceAndMoveCursorToBegin(db.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)
            // modifier
            if (modifiers.size != 0) {
                addChild(ret, transModifiers(modifiers))
                resetGlobalVariables(ret, innerCmts)
            }
            if (funcDecl.GetIsGetter()) {
                transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.GetToken)
            } else if (funcDecl.GetIsSetter()) {
                transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.SetToken)
            } else {
                if (identifier == "init") {
                    transBasicTerminal(db.GetIdentifierPos(), SyntaxNodeKind.InitToken)
                } else if (identifier == "~init") {
                    // IdentifierPos ---- ~,  KeywordPos ---- init
                    transBasicTerminal(db.GetIdentifierPos(), SyntaxNodeKind.BitNotToken)
                    transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.InitToken)
                } else {
                    // func
                    transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.FuncToken)
                    // identifier
                    transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
                }
            }
        }
        return (ret, kind, identifier, modifiers)
    }

    func transFuncBody(funcDecl: NodeFormat_FuncDecl, nodes: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>, identifier: String,
        modifiers: Array<Option<NodeFormat_Modifier>>) {
        var ret: ArrayList<SyntaxNodeImpl> = nodes
        if (let Some(body) <- funcDecl.GetFuncBody()) {
            if (let Some(generic) <- body.GetGeneric()) {
                let typeParameters = generic.GetTypeParameters()
                if (typeParameters.size != 0) {
                    addChild(ret,
                        transTypeArguments(typeParameters, generic.GetLeftAnglePos(), generic.GetRightAnglePos()))
                }
            }
            resetGlobalVariables(ret, innerCmts)

            if (funcDecl.GetIsSetter() && let Some(paramList) <- body.GetParamList()) {
                transBasicTerminal(paramList.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
                let params = paramList.GetParams()
                if (params.size > 0 && let Some(param) <- params[0] && let Some(vb) <- param.GetBase() && let Some(db) <- vb
                    .GetBase()) {
                    let paramNodeBase = param.GetNodeBase()
                    // Setter has no innerComments
                    let (leadParamListCmts, _, trailParamListCmts) = getCommentGroups(paramNodeBase)
                    addLeadingComments(paramNodeBase, ret, leadParamListCmts)
                    transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())

                    addChild(ret, transCommentGroupList(trailParamListCmts))
                    resetGlobalVariables(ret, innerCmts)
                }
                transBasicTerminal(paramList.GetRightParenPos(), SyntaxNodeKind.RParenToken)
            } else if (funcDecl.GetIsGetter() || (identifier == "init" && findStatic(modifiers))) {
                if (let Some(paramList) <- body.GetParamList()) {
                    let paramListBase = paramList.GetBase()
                    // Getter or Init has no leadingComments and trailingComments
                    let (_, innerParamListCmts, _) = getCommentGroups(paramListBase)
                    innerComments = innerParamListCmts
                    transBasicTerminal(paramList.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
                    transBasicTerminal(paramList.GetRightParenPos(), SyntaxNodeKind.RParenToken)
                    innerComments = innerCmts
                }
            } else if (let Some(paramList) <- body.GetParamList()) {
                addChild(ret, transParamList(paramList))
                moveCursorToEnd(paramList.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)
            if (let Some(ty) <- body.GetRetType()) {
                // :
                transBasicTerminal(body.GetColonPos(), SyntaxNodeKind.ColonToken)
                // type
                transType(ty)
                resetGlobalVariables(ret, innerCmts)
            }
            if (let Some(generic) <- body.GetGeneric()) {
                let genericConstraints = generic.GetGenericConstraints();
                if (genericConstraints.size != 0) {
                    addChild(ret, transGenericConstraints(genericConstraints))
                }
                resetGlobalVariables(ret, innerCmts)
            }
            // block
            if (let Some(block) <- body.GetBody()) {
                addChild(ret, transBlock(block))
            }
        }
        return ret
    }

    private func transFuncDecl(funcDecl: NodeFormat_FuncDecl, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var ret = ArrayList<SyntaxNodeImpl>()
        var kind = SyntaxNodeKind.FuncDecl
        var identifier = ""
        var modifiers = Array<Option<NodeFormat_Modifier>>()

        let nodeBase = funcDecl.GetBase().getOrThrow().GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        (ret, kind, identifier, modifiers) = transFuncHeader(funcDecl, ret, kind, innerCmts)

        ret = transFuncBody(funcDecl, ret, innerCmts, identifier, modifiers)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(kind, ret.toArray(), preChildren: preChildren)
    }

    // functionParameters
    // MacroExpandParam CommaToken manually added
    private func transParamList(paramList: NodeFormat_FuncParamList, isLambda!: Bool = false): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(paramList.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = paramList.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(paramList.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        let params = getElements<NodeFormat_FuncParam>(paramList.GetParams())
        for (i in 0..params.size) {
            let param = params[i]
            addWhitespaceAndMoveCursorToBegin(param.GetNodeBase())
            if (let Some(macroExpandParam) <- param.GetMacroParamAsMacroExpandParam()) {
                addChild(ret, transMacroExpandParam(macroExpandParam))
                resetGlobalVariables(ret, innerCmts)
                if (i < params.size - 1) {
                    addChild(ret, builder.buildBasicTerminal(SyntaxNodeKind.CommaToken))
                }
                moveCursorColumn(col: Int32(SyntaxNodeKind.CommaToken.toString().size))
            } else if (isLambda) {
                addChild(ret, transLambdaParam(param))
                resetGlobalVariables(ret, innerCmts)
                if (isValidPosition(param.GetCommaPos())) {
                    transBasicTerminal(param.GetCommaPos(), SyntaxNodeKind.CommaToken)
                }
            } else {
                addChild(ret, transFuncParam(param))
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(param.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
        }
        transBasicTerminal(paramList.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ParameterList, ret.toArray())
    }

    private func transLambdaParam(param: NodeFormat_FuncParam): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = param.GetNodeBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(vb) <- param.GetBase()) {
            resetGlobalVariables(ret, innerCmts)
            if (let Some(db) <- vb.GetBase()) {
                // The begin of FuncDecl is not begin of annotations
                addWhitespaceAndMoveCursorToBegin(db.GetBase())
                resetGlobalVariables(ret, innerCmts)
                transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
            }
            if (isValidPosition(param.GetColonPos())) {
                transBasicTerminal(param.GetColonPos(), SyntaxNodeKind.ColonToken)
            }
            if (let Some(ty) <- vb.GetType()) {
                transType(ty)
                resetGlobalVariables(ret, innerCmts)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.LambdaParam, ret.toArray())
    }

    private func transFuncParam(param: NodeFormat_FuncParam, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = param.GetNodeBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts, isDecl: true)
        innerComments = innerCmts

        if (let Some(vb) <- param.GetBase()) {
            if (let Some(db) <- vb.GetBase()) {
                transDeclAnnotationsAndModifiers(db, ret, innerCmts)
                if (param.GetHasLetOrVar() && vb.GetIsVar()) {
                    transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.VarToken)
                } else if (param.GetHasLetOrVar()) {
                    transBasicTerminal(db.GetKeywordPos(), SyntaxNodeKind.LetToken)
                }
                transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
            }
            transBasicTerminal(param.GetNotMarkPos(), SyntaxNodeKind.NotToken)

            transBasicTerminal(param.GetColonPos(), SyntaxNodeKind.ColonToken)

            // type
            if (let Some(ty) <- vb.GetType()) {
                transType(ty)
                resetGlobalVariables(ret, innerCmts)
            }
            resetGlobalVariables(ret, innerCmts)

            if (let Some(expr) <- param.GetAssignment()) {
                transBasicTerminal(vb.GetAssignPos(), SyntaxNodeKind.AssignToken)
                transNoTerminalExpr(expr)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.FuncParam, ret.toArray(), preChildren: preChildren)
    }

    private func transBlock(block: NodeFormat_Block, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(block.GetBase())
        if (block.GetIsUnsafe() && isValidPosition(block.GetUnsafePos())) {
            transUnsafeExpr(block, preChildren)
        } else {
            transSafeBlock(block, preChildren)
        }
    }

    private func transSafeBlock(block: NodeFormat_Block, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = block.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        addWhitespaceAndMoveCursor(block.GetLeftCurlPos())
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(block.GetLeftCurlPos(), SyntaxNodeKind.LCurlToken)
        for (e in block.GetBody()) {
            if (let Some(expr) <- e) {
                resetGlobalVariables(ret, innerCmts)
                addChild(ret, transRoot(expr))
            }
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(block.GetRightCurlPos(), SyntaxNodeKind.RCurlToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.Block, ret.toArray(), preChildren: preChildren)
    }

    private func transUnsafeExpr(block: NodeFormat_Block, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = block.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(block.GetUnsafePos(), SyntaxNodeKind.UnsafeToken)

        addChild(ret, transSafeBlock(block))
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.UnsafeExpr, ret.toArray(), preChildren: preChildren)
    }

    // Expr
    private func transExpr(expr: NodeFormat_Expr, preChildren: Array<SyntaxNodeImpl>, isInterpol!: Bool = false): ?SyntaxNodeImpl {
        let table = expr.table
        let o: UInt16 = table.offset(expr.EXPR)
        let off: UInt32 = UInt32(o) + table.pos
        match (expr.GetExprType()) {
            case NodeFormat_AnyExpr.AnyExpr_CALL_EXPR => transCallExpr(NodeFormat_CallExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_UNARY_EXPR => transUnaryExpr(NodeFormat_UnaryExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_BINARY_EXPR => transBinaryExpr(NodeFormat_BinaryExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_LIT_CONST_EXPR => transLitConst(NodeFormat_LitConstExpr(table.bytes, off),
                preChildren, isInterpol: isInterpol)
            case NodeFormat_AnyExpr.AnyExpr_REF_EXPR => transRefExpr(NodeFormat_RefExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_ARRAY_LIT => transArrayLit(NodeFormat_ArrayLit(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_TUPLE_LIT => transTupleLit(NodeFormat_TupleLit(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_ARRAY_EXPR => transArrayExpr(NodeFormat_ArrayExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_RANGE_EXPR => transRangeExpr(NodeFormat_RangeExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_INC_OR_DEC_EXPR => transIncOrDecExpr(
                NodeFormat_IncOrDecExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_PAREN_EXPR => transParenExpr(NodeFormat_ParenExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_IS_EXPR => transIsExpr(NodeFormat_IsExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_AS_EXPR => transAsExpr(NodeFormat_AsExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_TYPE_CONV_EXPR => transTypeConvExpr(
                NodeFormat_TypeConvExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_OPTIONAL_EXPR => transOptionalExpr(NodeFormat_OptionalExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_OPTIONAL_CHAIN_EXPR => transOptionalChainExpr(
                NodeFormat_OptionalChainExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_ASSIGN_EXPR => transAssignExpr(NodeFormat_AssignExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_RETURN_EXPR => transReturnExpr(NodeFormat_ReturnExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_JUMP_EXPR => transJumpExpr(NodeFormat_JumpExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_MEMBER_ACCESS => transMemberAccess(NodeFormat_MemberAccess(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_SUBSCRIPT_EXPR => transSubscriptExpr(
                NodeFormat_SubscriptExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_LAMBDA_EXPR => transLambda(NodeFormat_LambdaExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_SYNCHRONIZED_EXPR => transSynchronizedExpr(
                NodeFormat_SynchronizedExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_SPAWN_EXPR => transSpawnExpr(NodeFormat_SpawnExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_IF_EXPR => transIfExpr(NodeFormat_IfExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_BLOCK => transBlock(NodeFormat_Block(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_WHILE_EXPR => transWhileExpr(NodeFormat_WhileExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_DO_WHILE_EXPR => transDoWhileExpr(NodeFormat_DoWhileExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_FOR_IN_EXPR => transForInExpr(NodeFormat_ForInExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_WILDCARD_EXPR => transWildcardExpr(NodeFormat_WildcardExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_MATCH_EXPR => transMatchExpr(NodeFormat_MatchExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_TRY_EXPR => transTryExpr(NodeFormat_TryExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_THROW_EXPR => transThrowExpr(NodeFormat_ThrowExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_INTERPOLATION_EXPR => transInterpolationExpr(
                NodeFormat_InterpolationExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_QUOTE_EXPR => transQuoteExpr(NodeFormat_QuoteExpr(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_TOKEN_PART => transQuoteTokenExpr(NodeFormat_TokenPart(table.bytes, off),
                preChildren)
            case NodeFormat_AnyExpr.AnyExpr_LET_PATTERN_DESTRUCTOR => transLetPattern(
                NodeFormat_LetPatternDestructor(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_TRAILING_CLOSURE_EXPR => transTrailingClosureExpr(
                NodeFormat_TrailingClosureExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_MACRO_EXPAND_EXPR => transMacroExpandExpr(
                NodeFormat_MacroExpandExpr(table.bytes, off), preChildren)
            case NodeFormat_AnyExpr.AnyExpr_PRIMITIVE_TYPE_EXPR => transPrimitiveTypeExpr(
                NodeFormat_PrimitiveTypeExpr(table.bytes, off))
            case _ => throw Exception("ParseException: The current version does not support this node.")
        }
    }

    private func transWildcardExpr(matchExpr: NodeFormat_WildcardExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        // justify: WildcardExpr -> WildcardPattern
        addWhitespaceAndMoveCursorToBegin(matchExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = matchExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- matchExpr.GetBase()) {
            resetGlobalVariables(ret, innerCmts)
            transBasicTerminal(db.GetBegin(), SyntaxNodeKind.WildcardToken)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.WildcardPattern, ret.toArray(), preChildren: preChildren)
    }

    private func transMatchExpr(matchExpr: NodeFormat_MatchExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(matchExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = matchExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- matchExpr.GetBase()) {
            resetGlobalVariables(ret, innerCmts)
            // match
            transBasicTerminal(db.GetBegin(), SyntaxNodeKind.MatchToken)

            // expr
            if (let Some(selector) <- matchExpr.GetSelector()) {
                // case 1: match (expr) { patterns }
                transBasicTerminal(matchExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
                addChild(ret, transExpr(selector))
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(matchExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
                transBasicTerminal(matchExpr.GetLeftCurlPos(), SyntaxNodeKind.LCurlToken)
                // match cases
                for (normalCase in getElements<NodeFormat_MatchCase>(matchExpr.GetMatchCases())) {
                    addChild(ret, transMatchCase(normalCase))
                    resetGlobalVariables(ret, innerCmts)
                }
                transBasicTerminal(matchExpr.GetRightCurlPos(), SyntaxNodeKind.RCurlToken)
            } else {
                // case 2: match { patterns }
                transBasicTerminal(matchExpr.GetLeftCurlPos(), SyntaxNodeKind.LCurlToken)
                // match cases
                for (otherCase in getElements<NodeFormat_MatchCaseOther>(matchExpr.GetMatchCaseOthers())) {
                    addChild(ret, transMatchCaseOther(otherCase))
                    resetGlobalVariables(ret, innerCmts)
                }
                transBasicTerminal(matchExpr.GetRightCurlPos(), SyntaxNodeKind.RCurlToken)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MatchExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transTryExpr(tryExpr: NodeFormat_TryExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(tryExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)

        let nodeBase = tryExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- tryExpr.GetBase()) {
            resetGlobalVariables(ret, innerCmts)
            // try
            transBasicTerminal(db.GetBegin(), SyntaxNodeKind.TryToken)
            // resourceSpec
            let (children, commaPos) = (tryExpr.GetResourceSpec(), tryExpr.GetResourceSpecCommaPosVec())

            transBasicTerminal(tryExpr.GetResourceSpecLparenPos(), SyntaxNodeKind.LParenToken)
            for (i in 0..children.size) {
                if (let Some(varDecl) <- children[i]) {
                    addChild(ret, transVarDecl(varDecl))
                    resetGlobalVariables(ret, innerCmts)
                }
                if (i < commaPos.size) {
                    transBasicTerminal(commaPos[i], SyntaxNodeKind.CommaToken)
                }
            }
            transBasicTerminal(tryExpr.GetResourceSpecRparenPos(), SyntaxNodeKind.RParenToken)

            // tryBlock
            if (let Some(block) <- tryExpr.GetTryBlock()) {
                addChild(ret, transBlock(block))
                resetGlobalVariables(ret, innerCmts)
            }

            // catch
            let (catchPos, lParenPos, rParenPos) = (tryExpr.GetCatchPosVec(), tryExpr.GetCatchLeftParenPosVec(),
                tryExpr.GetCatchRightParenPosVec())
            let (catchPatterns, catchBlocks) = (tryExpr.GetCatchPatterns(), tryExpr.GetCatchBlocks())
            for (i in 0..catchPos.size) {
                transBasicTerminal(catchPos[i], SyntaxNodeKind.CatchToken)
                transBasicTerminal(lParenPos[i], SyntaxNodeKind.LParenToken)
                if (let Some(pattern) <- catchPatterns[i]) {
                    addChild(ret, transCatchPattern(pattern))
                    resetGlobalVariables(ret, innerCmts)
                }
                transBasicTerminal(rParenPos[i], SyntaxNodeKind.RParenToken)
                if (let Some(block) <- catchBlocks[i]) {
                    addChild(ret, transBlock(block))
                    resetGlobalVariables(ret, innerCmts)
                }
            }
            // finally
            transBasicTerminal(tryExpr.GetFinallyPos(), SyntaxNodeKind.FinallyToken)
            if (let Some(block) <- tryExpr.GetFinallyBlock()) {
                addChild(ret, transBlock(block))
                resetGlobalVariables(ret, innerCmts)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TryExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transPattern(pattern: NodeFormat_Pattern): ?SyntaxNodeImpl {
        let table = pattern.table
        let o: UInt16 = table.offset(pattern.PATTERN)
        let off: UInt32 = UInt32(o) + table.pos
        match (pattern.GetPatternType()) {
            case AnyPattern_CONST_PATTERN => transConstPattern(NodeFormat_ConstPattern(table.bytes, off))
            case AnyPattern_WILDCARD_PATTERN => transWildcardPattern(NodeFormat_WildcardPattern(table.bytes, off))
            case AnyPattern_VAR_PATTERN => transVarBindingPattern(NodeFormat_VarPattern(table.bytes, off))
            case AnyPattern_TYPE_PATTERN => transTypePattern(NodeFormat_TypePattern(table.bytes, off))
            case AnyPattern_ENUM_PATTERN => transEnumPattern(NodeFormat_EnumPattern(table.bytes, off))
            case AnyPattern_VAR_OR_ENUM_PATTERN => transVarOrEnumPattern(NodeFormat_VarOrEnumPattern(table.bytes, off))
            case AnyPattern_TUPLE_PATTERN => transTuplePattern(NodeFormat_TuplePattern(table.bytes, off))
            case AnyPattern_EXCEPT_TYPE_PATTERN => transExceptTypePattern(NodeFormat_ExceptTypePattern(table.bytes, off))
            case _ => None
        }
    }

    private func transConstPattern(constPattern: NodeFormat_ConstPattern): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(constPattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = constPattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        // literal
        if (let Some(literal) <- constPattern.GetLiteral()) {
            addChild(ret, transExpr(literal))
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ConstPattern, ret.toArray())
    }

    private func transWildcardPattern(wildcard: NodeFormat_WildcardPattern): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(wildcard.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = wildcard.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- wildcard.GetBase()) {
            transBasicTerminal(db.GetBegin(), SyntaxNodeKind.WildcardToken)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.WildcardPattern, ret.toArray())
    }

    private func transVarBindingPattern(varPattern: NodeFormat_VarPattern): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(varPattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = varPattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(varDecl) <- varPattern.GetVarDecl()) {
            if (let Some(db) <- varDecl.GetBase()) {
                transIdentifier(db.GetIdentifierPos(), db.GetIdentifier())
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.VarBindingPattern, ret.toArray())
    }

    private func transVarOrEnumPattern(varOrEnumPattern: NodeFormat_VarOrEnumPattern): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(varOrEnumPattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = varOrEnumPattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- varOrEnumPattern.GetBase()) {
            transIdentifier(db.GetBegin(), varOrEnumPattern.GetIdentifier())
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.VarOrEnumPattern, ret.toArray())
    }

    private func transTypePattern(typePattern: NodeFormat_TypePattern): ?SyntaxNodeImpl {
        // (wildcardPattern | varBindingPattern) NL* COLON NL* type
        addWhitespaceAndMoveCursorToBegin(typePattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = typePattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        // (wildcardPattern | varBindingPattern)
        if (let Some(pat) <- typePattern.GetPattern()) {
            addChild(ret, transPattern(pat))
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(typePattern.GetColonPos(), SyntaxNodeKind.ColonToken)
        // type
        if (let Some(ty) <- typePattern.GetType()) {
            resetGlobalVariables(ret, innerCmts)
            transType(ty)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TypePattern, ret.toArray())
    }

    private func transCompositeType(mem: NodeFormat_MemberAccess): ?SyntaxNodeImpl {
        // (identifier NL* DOT NL*)* identifier ( NL* typeArguments)?
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = mem.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        // work stack
        let stack = ArrayStack<NodeFormat_MemberAccess>()
        stack.add(mem)
        var tmpMem = mem
        while (let Some(base) <- tmpMem.GetBaseExpr() && let Some(baseMem) <- base.GetExprAsMemberAccess()) {
            stack.add(baseMem)
            tmpMem = baseMem
        }
        // work stack is top: [A.B, B.C, C.D<Int64>] bottom
        while (let Some(curMem) <- stack.remove()) {
            // A<Int64>.B
            if (let Some(base) <- curMem.GetBaseExpr()) {
                if (let Some(baseRef) <- base.GetExprAsRefExpr()) {
                    if (let Some(ref) <- baseRef.GetRef()) {
                        transIdentifier(ref.GetIdentifierPos(), ref.GetIdentifier())
                    }
                    let typeArguments = baseRef.GetTypeArguments()
                    if (typeArguments.size > 0) {
                        addChild(ret,
                            transTypeArguments(typeArguments, baseRef.GetLeftAnglePos(), baseRef.GetRightAnglePos()))
                    }
                } else if (let Some(baseMem) <- base.GetExprAsMemberAccess()) {
                    transIdentifier(baseMem.GetFieldPos(), baseMem.GetField())
                    // P.A<Int64>.B
                    let typeArguments = baseMem.GetTypeArguments()
                    if (typeArguments.size > 0) {
                        addChild(ret,
                            transTypeArguments(typeArguments, baseMem.GetLeftAnglePos(), baseMem.GetRightAnglePos()))
                    }
                }
            }
            resetGlobalVariables(ret, innerCmts)
            if (!stack.isEmpty()) {
                transBasicTerminal(curMem.GetDotPos(), SyntaxNodeKind.DotToken)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.CompositeType, ret.toArray())
    }

    private func transEnumPattern(enumPattern: NodeFormat_EnumPattern): ?SyntaxNodeImpl {
        // (compositeType NL* DOT NL*)? identifier NL* enumPatternParameters?
        // enumPatternParameters : LPAREN NL* pattern (NL* COMMA NL* pattern)* NL* RPAREN
        addWhitespaceAndMoveCursorToBegin(enumPattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = enumPattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        // For example: pkg1.subpkg0.E<Int64>.C0
        // compositeType pkg1.subpkg0.E<Int64>
        // SymbolRef C0
        if (let Some(expr) <- enumPattern.GetRef()) {
            if (let Some(memAccess) <- expr.GetExprAsMemberAccess()) {
                addChild(ret, transCompositeType(memAccess))
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(memAccess.GetDotPos(), SyntaxNodeKind.DotToken)
                addChild(ret, transSymbolRef4MemberAccess(memAccess))
                resetGlobalVariables(ret, innerCmts)
            } else if (let Some(refExpr) <- expr.GetExprAsRefExpr()) {
                addChild(ret, transRefExpr(refExpr))
                resetGlobalVariables(ret, innerCmts)
            }
        }
        // patterns
        let patterns = enumPattern.GetPatterns()
        if (patterns.size > 0) {
            let commaPos = enumPattern.GetCommaPosVec()
            // RPAREN
            transBasicTerminal(enumPattern.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
            for (i in 0..patterns.size) {
                if (i > 0) {
                    transBasicTerminal(commaPos[i - 1], SyntaxNodeKind.CommaToken)
                }
                if (let Some(pat) <- patterns[i]) {
                    addChild(ret, transPattern(pat))
                }
                resetGlobalVariables(ret, innerCmts)
            }
            // RPAREN
            transBasicTerminal(enumPattern.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.EnumPattern, ret.toArray())
    }

    private func transTuplePattern(tuplePattern: NodeFormat_TuplePattern): ?SyntaxNodeImpl {
        // LPAREN NL* pattern (NL* COMMA NL* pattern)+ NL* RPAREN
        addWhitespaceAndMoveCursorToBegin(tuplePattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = tuplePattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(tuplePattern.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        // patterns
        let commaPos = tuplePattern.GetCommaPosVec()
        let patterns = tuplePattern.GetPatterns()
        for (i in 0..patterns.size) {
            if (i > 0) {
                transBasicTerminal(commaPos[i - 1], SyntaxNodeKind.CommaToken)
            }
            if (let Some(pat) <- patterns[i]) {
                addChild(ret, transPattern(pat))
            }
            resetGlobalVariables(ret, innerCmts)
        }
        // RPAREN
        transBasicTerminal(tuplePattern.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TuplePattern, ret.toArray())
    }

    private func transExceptTypePattern(exceptTypePattern: NodeFormat_ExceptTypePattern): ?SyntaxNodeImpl {
        let tmpChildren = curChildren
        if (let Some(pattern) <- exceptTypePattern.GetPattern()) {
            addChild(tmpChildren, transPattern(pattern))
            curChildren = tmpChildren
        }
        transBasicTerminal(exceptTypePattern.GetColonPos(), SyntaxNodeKind.ColonToken)

        let types = exceptTypePattern.GetTypes()
        let bitOrPoses = exceptTypePattern.GetBitOrPosVec()
        let types_ = getElements<NodeFormat_Type>(types)
        for (i in 0..types_.size) {
            transType(types_[i])
            curChildren = tmpChildren
            if (i < bitOrPoses.size) {
                transBasicTerminal(bitOrPoses[i], SyntaxNodeKind.BitOrToken)
            }
        }
        curChildren = tmpChildren
        return None
    }

    private func transCatchPattern(pattern: NodeFormat_Pattern): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(pattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = pattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        match (pattern.GetPatternType()) {
            case AnyPattern_WILDCARD_PATTERN => addChild(ret, transPattern(pattern))
            case AnyPattern_EXCEPT_TYPE_PATTERN => transPattern(pattern)
            case _ => return None
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.CatchPattern, ret.toArray())
    }

    private func transMatchCaseBody(body: NodeFormat_Block): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = body.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, leadCommentNodes, leadCmts)
        curChildren = ret
        innerComments = innerCmts

        for (exprOrDecl in body.GetBody()) {
            if (let Some(node) <- exprOrDecl) {
                addChild(ret, transRoot(node))
            }
            resetGlobalVariables(ret, innerCmts)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MatchCaseBody, ret.toArray())
    }

    private func prepareMatchCasePrefix(base: Option<NodeFormat_NodeBase>) {
        addWhitespaceAndMoveCursorToBegin(base)
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = base
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- base) {
            transBasicTerminal(db.GetBegin(), SyntaxNodeKind.CaseToken)
        }
        return (ret, innerCmts, trailCmts)
    }

    private func appendMatchCaseArrowAndBody(base: Option<NodeFormat_NodeBase>, arrowPos: NodeFormat_Position,
        body: Option<NodeFormat_Block>, ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        if (let Some(_) <- base) {
            resetGlobalVariables(ret, innerCmts)
            transBasicTerminal(arrowPos, SyntaxNodeKind.DoubleArrowToken)
            if (let Some(block) <- body) {
                addChild(ret, transMatchCaseBody(block))
            }
        }
    }

    private func transMatchCase(matchCase: NodeFormat_MatchCase): ?SyntaxNodeImpl {
        // CASE NL* pattern (NL* BITOR NL* pattern)* NL* (WHERE NL* expression)? NL* DOUBLE_ARROW NL* expressionOrDeclaration (end+ expressionOrDeclaration?)*
        let (ret, innerCmts, trailCmts) = prepareMatchCasePrefix(matchCase.GetBase())

        if (let Some(db) <- matchCase.GetBase()) {
            let bitOrPos = matchCase.GetBitOrPosVec()
            let patterns = matchCase.GetPatterns()
            for (i in 0..patterns.size) {
                if (i > 0) {
                    transBasicTerminal(bitOrPos[i - 1], SyntaxNodeKind.BitOrToken)
                }
                if (let Some(pattern) <- patterns[i]) {
                    addChild(ret, transPattern(pattern))
                }
                resetGlobalVariables(ret, innerCmts)
            }
            // patternGuard
            if (let Some(patGuard) <- matchCase.GetPatternguard()) {
                transBasicTerminal(matchCase.GetIfPos(), SyntaxNodeKind.WhereToken)
                addChild(ret, transExpr(patGuard))
            }
        }
        appendMatchCaseArrowAndBody(matchCase.GetBase(), matchCase.GetArrowPos(), matchCase.GetExprOrDecls(), ret, innerCmts)
        appendTrailingComments(ret, innerCmts, trailCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MatchCase, ret.toArray())
    }

    private func transMatchCaseOther(matchCase: NodeFormat_MatchCaseOther): ?SyntaxNodeImpl {
        // CASE NL* expression NL* DOUBLE_ARROW NL* expressionOrDeclaration (end+ expressionOrDeclaration?)*
        let (ret, innerCmts, trailCmts) = prepareMatchCasePrefix(matchCase.GetBase())

        if (let Some(db) <- matchCase.GetBase()) {
            if (let Some(caseExpr) <- matchCase.GetMatchExpr()) {
                addChild(ret, transExpr(caseExpr))
            }
        }
        appendMatchCaseArrowAndBody(matchCase.GetBase(), matchCase.GetArrowPos(), matchCase.GetExprOrDecls(), ret, innerCmts)
        appendTrailingComments(ret, innerCmts, trailCmts)
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MatchCase, ret.toArray())
    }

    private func transRefExpr(refExpr: NodeFormat_RefExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        if (refExpr.GetIsQuoteDollar()) {
            moveCursorColumn()
        } else {
            addWhitespaceAndMoveCursorToBegin(refExpr.GetBase())
        }
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = refExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(ref) <- refExpr.GetRef()) {
            match (ref.GetIdentifier()) {
                case "this" => ret.add(builder.buildBasicTerminal(SyntaxNodeKind.ThisToken))
                case "super" => ret.add(builder.buildBasicTerminal(SyntaxNodeKind.SuperToken))
                case _ => ret.add(builder.buildValuedTerminal(SyntaxNodeKind.IdentToken, ref.GetIdentifier()))
            }
            moveCursorColumn(ref.GetIdentifierPos(), ref.GetIdentifier().size)
        }
        let typeArguments = refExpr.GetTypeArguments()
        if (typeArguments.size != 0) {
            addChild(ret,
                transTypeArguments(typeArguments, refExpr.GetLeftAnglePos(), refExpr.GetRightAnglePos()).getOrThrow())
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.RefExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transArrayLit(arrayLit: NodeFormat_ArrayLit, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(arrayLit.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = arrayLit.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(arrayLit.GetLeftCurlPos(), SyntaxNodeKind.LSquareToken)

        let children = arrayLit.GetChildren()
        let commaPos = arrayLit.GetCommaPosVec()
        for (i in 0..children.size) {
            if (let Some(expr) <- children[i]) {
                transNoTerminalExpr(expr)
                resetGlobalVariables(ret, innerCmts)
            }
            if (i < commaPos.size) {
                transBasicTerminal(commaPos[i], SyntaxNodeKind.CommaToken)
            }
        }
        transBasicTerminal(arrayLit.GetRightCurlPos(), SyntaxNodeKind.RSquareToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ArrayLiteral, ret.toArray(), preChildren: preChildren)
    }

    private func transTupleLit(tupleLit: NodeFormat_TupleLit, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(tupleLit.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = tupleLit.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(tupleLit.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

        let children = tupleLit.GetChildren()
        let commaPos = tupleLit.GetCommaPosVec()
        for (i in 0..commaPos.size) {
            if (let Some(expr) <- children[i]) {
                transNoTerminalExpr(expr)
                resetGlobalVariables(ret, innerCmts)
            }
            transBasicTerminal(commaPos[i], SyntaxNodeKind.CommaToken)
        }
        if (let Some(expr) <- children[commaPos.size]) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }

        transBasicTerminal(tupleLit.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TupleLiteral, ret.toArray(), preChildren: preChildren)
    }

    private func transArrayExpr(arrayExpr: NodeFormat_ArrayExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(arrayExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = arrayExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(tp) <- arrayExpr.GetType()) {
            transType(tp)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(arrayExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

        for (p in arrayExpr.GetArgs()) {
            if (let Some(arg) <- p) {
                addWhitespaceAndMoveCursorToBegin(arg.GetBase())
                addChild(ret, transFuncArg(arg))
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(arg.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
        }

        transBasicTerminal(arrayExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.VArrayExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transRangeExpr(rangeExpr: NodeFormat_RangeExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(rangeExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = rangeExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(start) <- rangeExpr.GetStartExpr()) {
            transNoTerminalExpr(start)
        }
        resetGlobalVariables(ret, innerCmts)

        var kind = SyntaxNodeKind.RangeOpToken
        if (rangeExpr.GetIsClosed()) {
            kind = SyntaxNodeKind.ClosedRangeOpToken
        }
        transBasicTerminal(rangeExpr.GetRangePos(), kind)

        if (let Some(stop) <- rangeExpr.GetStopExpr()) {
            transNoTerminalExpr(stop)
        }
        resetGlobalVariables(ret, innerCmts)

        if (let Some(step) <- rangeExpr.GetStepExpr()) {
            transBasicTerminal(rangeExpr.GetColonPos(), SyntaxNodeKind.ColonToken)
            transNoTerminalExpr(step)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.RangeExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transIncOrDecExpr(incOrDecExpr: NodeFormat_IncOrDecExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(incOrDecExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = incOrDecExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(expr) <- incOrDecExpr.GetExpr()) {
            transNoTerminalExpr(expr)
        }
        resetGlobalVariables(ret, innerCmts)

        let opKind = getSyntaxImplKind(incOrDecExpr.GetOperatorKind())
        transBasicTerminal(incOrDecExpr.GetOperatorPos(), opKind)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.IncOrDecExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transParenExpr(parenExpr: NodeFormat_ParenExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(parenExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = parenExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(parenExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

        if (let Some(expr) <- parenExpr.GetExpr()) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(parenExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ParenExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transIsExpr(isExpr: NodeFormat_IsExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(isExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = isExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(expr) <- isExpr.GetExpr()) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }

        transBasicTerminal(isExpr.GetIsPos(), SyntaxNodeKind.IsToken)
        if (let Some(tp) <- isExpr.GetIsType()) {
            transType(tp)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.IsExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transAsExpr(asExpr: NodeFormat_AsExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(asExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = asExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(expr) <- asExpr.GetExpr()) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }

        transBasicTerminal(asExpr.GetAsPos(), SyntaxNodeKind.AsToken)
        if (let Some(tp) <- asExpr.GetAsType()) {
            transType(tp)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.AsExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transTypeConvExpr(typeConvExpr: NodeFormat_TypeConvExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(typeConvExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = typeConvExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(tp) <- typeConvExpr.GetType()) {
            transType(tp)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(typeConvExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

        if (let Some(expr) <- typeConvExpr.GetExpr()) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(typeConvExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TypeConvExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transOptionalExpr(optionalExpr: NodeFormat_OptionalExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(optionalExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = optionalExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(baseExpr) <- optionalExpr.GetBaseExpr()) {
            transNoTerminalExpr(baseExpr)
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(optionalExpr.GetQuestPos(), SyntaxNodeKind.QuestToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.OptionalExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transOptionalChainExpr(optionalChainExpr: NodeFormat_OptionalChainExpr,
        preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        if (let Some(expr) <- optionalChainExpr.GetExpr()) {
            return transExpr(expr)
        }
        None
    }

    private func transAssignExpr(assignExpr: NodeFormat_AssignExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(assignExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = assignExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(lhs) <- assignExpr.GetLeftValue()) {
            transNoTerminalExpr(lhs)
        }
        resetGlobalVariables(ret, innerCmts)

        let assignOpKind = getSyntaxImplKind(assignExpr.GetAssignOp())
        transBasicTerminal(assignExpr.GetAssignPos(), assignOpKind)

        if (let Some(rhs) <- assignExpr.GetRightExpr()) {
            transNoTerminalExpr(rhs)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.AssignExpr, ret.toArray(), preChildren: preChildren)
    }

    private func isCompilerAddUnitLiteral(expr: NodeFormat_Expr): Bool {
        if (let Some(lit) <- expr.GetExprAsLitConstExpr() && lit.GetLiteralConstKind() == 7 /*UNIT*/ ) {
            if (let Some(db) <- lit.GetBase()) {
                let beg = db.GetBegin()
                let end = db.GetEnd()
                if (beg.line == end.line && beg.column == end.column) {
                    return true
                }
            }
        }
        return false
    }

    private func transReturnExpr(returnExpr: NodeFormat_ReturnExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(returnExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = returnExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(returnExpr.GetReturnPos(), SyntaxNodeKind.ReturnToken)
        if (let Some(expr) <- returnExpr.GetExpr()) {
            // special case: return (), () is compiler add node
            if (!isCompilerAddUnitLiteral(expr)) {
                transNoTerminalExpr(expr)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ReturnExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transJumpExpr(jumpExpr: NodeFormat_JumpExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        var kind = SyntaxNodeKind.BreakToken
        var jumpKind = SyntaxNodeKind.BreakExpr
        if (!jumpExpr.GetIsBreak()) {
            kind = SyntaxNodeKind.ContinueToken
            jumpKind = SyntaxNodeKind.ContinueExpr
        }
        addWhitespaceAndMoveCursorToBegin(jumpExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = jumpExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- jumpExpr.GetBase()) {
            transBasicTerminal(db.GetBegin(), kind)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(jumpKind, ret.toArray(), preChildren: preChildren)
    }

    private func transSymbolRef4MemberAccess(memberAccess: NodeFormat_MemberAccess): ?SyntaxNodeImpl {
        let beginPos = memberAccess.GetFieldPos()
        addWhitespaceAndMoveCursor(beginPos)
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        transIdentifier(memberAccess.GetFieldPos(), memberAccess.GetField())

        var typeArguments = memberAccess.GetTypeArguments()
        if (typeArguments.size != 0) {
            addChild(ret,
                transTypeArguments(typeArguments, memberAccess.GetLeftAnglePos(), memberAccess.GetRightAnglePos()))
        }
        builder.buildNonTerminal(SyntaxNodeKind.RefExpr, ret.toArray())
    }

    private func transMemberAccess(memberAccess: NodeFormat_MemberAccess, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(memberAccess.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = memberAccess.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(baseExpr) <- memberAccess.GetBaseExpr()) {
            transNoTerminalExpr(baseExpr)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(memberAccess.GetDotPos(), SyntaxNodeKind.DotToken)
        addChild(ret, transSymbolRef4MemberAccess(memberAccess))
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.MemberAccess, ret.toArray(), preChildren: preChildren)
    }

    private func transSubscriptExpr(subscriptExpr: NodeFormat_SubscriptExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(subscriptExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = subscriptExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(baseExpr) <- subscriptExpr.GetBaseExpr()) {
            transNoTerminalExpr(baseExpr)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(subscriptExpr.GetLeftSquarePos(), SyntaxNodeKind.LSquareToken)

        let children = subscriptExpr.GetIndexExprs()
        let commasPos = subscriptExpr.GetCommaPosVec()
        for (i in 0..children.size) {
            if (let Some(expr) <- children[i]) {
                transNoTerminalExpr(expr)
                curChildren = ret
                if (i < commasPos.size) {
                    transBasicTerminal(commasPos[i], SyntaxNodeKind.CommaToken)
                }
            }
        }

        transBasicTerminal(subscriptExpr.GetRightSquarePos(), SyntaxNodeKind.RSquareToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.SubscriptExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transLambda(lambdaExpr: NodeFormat_LambdaExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(lambdaExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = lambdaExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(base) <- lambdaExpr.GetBase()) {
            transBasicTerminal(base.GetBegin(), SyntaxNodeKind.LCurlToken)
        }

        if (let Some(funcBody) <- lambdaExpr.GetBody()) {
            if (let Some(paramList) <- funcBody.GetParamList()) {
                addChild(ret, transParamList(paramList, isLambda: true))
                moveCursorToEnd(paramList.GetBase())
            }
            resetGlobalVariables(ret, innerCmts)
            transBasicTerminal(funcBody.GetArrowPos(), SyntaxNodeKind.DoubleArrowToken)

            if (let Some(blockNode) <- funcBody.GetBody()) {
                var body = blockNode.GetBody()
                for (node in getElements<NodeFormat_Node>(body)) {
                    addChild(ret, transRoot(node))
                    resetGlobalVariables(ret, innerCmts)
                }
                transBasicTerminal(blockNode.GetRightCurlPos(), SyntaxNodeKind.RCurlToken)
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.Lambda, ret.toArray(), preChildren: preChildren)
    }

    private func transThrowExpr(throwExpr: NodeFormat_ThrowExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(throwExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = throwExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(base) <- throwExpr.GetBase()) {
            transBasicTerminal(base.GetBegin(), SyntaxNodeKind.ThrowToken)
        }
        if (let Some(expr) <- throwExpr.GetExpr()) {
            transNoTerminalExpr(expr)
        }
        resetGlobalVariables(ret, innerCmts)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ThrowExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transSynchronizedExpr(synchronizedExpr: NodeFormat_SynchronizedExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(synchronizedExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = synchronizedExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(synchronizedExpr.GetSyncPos(), SyntaxNodeKind.SynchronizedToken)

        transBasicTerminal(synchronizedExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

        if (let Some(expr) <- synchronizedExpr.GetMutexExpr()) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }

        transBasicTerminal(synchronizedExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)

        if (let Some(block) <- synchronizedExpr.GetBody()) {
            addChild(ret, transBlock(block))
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.SynchronizedExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transSpawnExpr(spawnExpr: NodeFormat_SpawnExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(spawnExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = spawnExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(spawnExpr.GetSpawnPos(), SyntaxNodeKind.SpawnToken)

        if (spawnExpr.GetHasArg()) {
            transBasicTerminal(spawnExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
            if (let Some(expr) <- spawnExpr.GetSpawnArgExpr()) {
                transNoTerminalExpr(expr)
                resetGlobalVariables(ret, innerCmts)
            }
            transBasicTerminal(spawnExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        }

        if (let Some(expr) <- spawnExpr.GetTaskExpr()) {
            transNoTerminalExpr(expr)
        }
        resetGlobalVariables(ret, innerCmts)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.SpawnExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transIfExpr(ifExpr: NodeFormat_IfExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        // IF NL* LPAREN NL* condition NL* RPAREN NL* block (NL* ELSE (NL* ifExpression | NL* block))?
        addWhitespaceAndMoveCursorToBegin(ifExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = ifExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(ifExpr.GetIfPos(), SyntaxNodeKind.IfToken)
        transBasicTerminal(ifExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        if (let Some(expr) <- ifExpr.GetCondExpr()) {
            addChild(ret, transDisjunctionCondition(expr))
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(ifExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)

        if (let Some(block) <- ifExpr.GetBody()) {
            addChild(ret, transBlock(block))
        }

        if (ifExpr.GetHasElse()) {
            resetGlobalVariables(ret, innerCmts)
            transBasicTerminal(ifExpr.GetElsePos(), SyntaxNodeKind.ElseToken)
            if (let Some(elseBody) <- ifExpr.GetElseBody()) {
                // BlockExpr or IfExpr
                addChild(ret, transExpr(elseBody))
            }
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.IfExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transWhileExpr(whileExpr: NodeFormat_WhileExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(whileExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = whileExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(whileExpr.GetWhilePos(), SyntaxNodeKind.WhileToken)
        transBasicTerminal(whileExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        if (let Some(expr) <- whileExpr.GetCondExpr()) {
            addChild(ret, transDisjunctionCondition(expr))
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(whileExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (let Some(block) <- whileExpr.GetBody()) {
            addChild(ret, transBlock(block))
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.WhileExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transDoWhileExpr(doWhileExpr: NodeFormat_DoWhileExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(doWhileExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = doWhileExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(doWhileExpr.GetDoPos(), SyntaxNodeKind.DoToken)
        if (let Some(block) <- doWhileExpr.GetBody()) {
            addChild(ret, transBlock(block))
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(doWhileExpr.GetWhilePos(), SyntaxNodeKind.WhileToken)
        transBasicTerminal(doWhileExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        if (let Some(expr) <- doWhileExpr.GetCondExpr()) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(doWhileExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.DoWhileExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transForInExpr(forInExpr: NodeFormat_ForInExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(forInExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = forInExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(base) <- forInExpr.GetBase()) {
            transBasicTerminal(base.GetBegin(), SyntaxNodeKind.ForToken)
        }
        transBasicTerminal(forInExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        if (let Some(pattern) <- forInExpr.GetPattern()) {
            addChild(ret, transPattern(pattern))
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(forInExpr.GetInPos(), SyntaxNodeKind.InToken)
        if (let Some(inExpr) <- forInExpr.GetInExpr()) {
            addChild(ret, transExpr(inExpr))
            resetGlobalVariables(ret, innerCmts)
        }
        if (let Some(patternGuard) <- forInExpr.GetPatternGuard()) {
            transBasicTerminal(forInExpr.GetIfPos(), SyntaxNodeKind.WhereToken)
            addChild(ret, transExpr(patternGuard))
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(forInExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (let Some(block) <- forInExpr.GetBody()) {
            addChild(ret, transBlock(block))
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ForInExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transFuncArg(argument: NodeFormat_FuncArg): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = argument.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transIdentifier(argument.GetNamePos(), argument.GetName())
        transBasicTerminal(argument.GetColonPos(), SyntaxNodeKind.ColonToken)
        if (argument.GetWithInout()) {
            transBasicTerminal(argument.GetInoutPos(), SyntaxNodeKind.InoutToken)
        }
        if (let Some(expr) <- argument.GetExpr()) {
            transNoTerminalExpr(expr)
            resetGlobalVariables(ret, innerCmts)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.Argument, ret.toArray())
    }

    private func transCallExpr(callExpr: NodeFormat_CallExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(callExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = callExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        // baseFunc
        if (let Some(baseFunc) <- callExpr.GetBaseFunc()) {
            transNoTerminalExpr(baseFunc)
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(callExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
        // funcArgs
        let args = callExpr.GetArgs()
        for (p in args) {
            if (let Some(arg) <- p) {
                addWhitespaceAndMoveCursorToBegin(arg.GetBase())
                addChild(ret, transFuncArg(arg))
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(arg.GetCommaPos(), SyntaxNodeKind.CommaToken)
            }
        }
        resetGlobalVariables(ret, innerCmts)
        transBasicTerminal(callExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.CallExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transUnaryExpr(unExpr: NodeFormat_UnaryExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(unExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = unExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let opKind = getSyntaxImplKind(unExpr.GetOperatorKind())
        transBasicTerminal(unExpr.GetOperatorPos(), opKind)
        if (let Some(expr) <- unExpr.GetExpr()) {
            transNoTerminalExpr(expr)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.UnaryExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transBinaryExpr(biExpr: NodeFormat_BinaryExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(biExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = biExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(lhs) <- biExpr.GetLeftExpr()) {
            transNoTerminalExpr(lhs)
            resetGlobalVariables(ret, innerCmts)
        }
        resetGlobalVariables(ret, innerCmts)

        let opKind = getSyntaxImplKind(biExpr.GetOperatorKind())
        transBasicTerminal(biExpr.GetOperatorPos(), opKind)
        if (let Some(rhs) <- biExpr.GetRightExpr()) {
            transNoTerminalExpr(rhs)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.BinaryExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transInterpolationExpr(interpolationExpr: NodeFormat_InterpolationExpr,
        preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let base = interpolationExpr.GetBase()
        moveCursorToBegin(base)
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = interpolationExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(interpolationExpr.GetDollarPos(), SyntaxNodeKind.DollarToken)
        if (let Some(block) <- interpolationExpr.GetBlock()) {
            addChild(ret, transBlock(block))
            resetGlobalVariables(ret, innerCmts)
        }
        moveCursorToEnd(base)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.InterpolationExpr, ret.toArray(), preChildren: preChildren)
    }

    private func buildLineStringLiteral(nodeBase: ?NodeFormat_NodeBase, value: ValuedTerminal, isSingle: Bool,
        interpols: Array<Option<NodeFormat_Expr>>, preChildren: Array<SyntaxNodeImpl>, isInterpol!: Bool = false): NonTerminal {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let quoteToken = builder.buildQuote(isSingle)
        if (isInterpol) {
            ret.add(value)
        } else {
            ret.add(quoteToken)
            moveCursorColumn()
            if (interpols.size == 0) {
                ret.add(value)
                moveCursorColumn(col: Int32(value.value.size))
            }
            for (interpol in interpols) {
                if (let Some(interp) <- interpol) {
                    addChild(ret, transExpr(interp, isInterpol: true))
                    resetGlobalVariables(ret, innerCmts)
                }
            }
            ret.add(quoteToken)
            moveCursorColumn()
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        builder.buildNonTerminal(SyntaxNodeKind.LineStringLiteral, ret.toArray(), preChildren: preChildren)
    }

    private func buildMultiLineStringLiteral(lit: NodeFormat_LitConstExpr, value: ValuedTerminal, isSingle: Bool,
        interpols: Array<Option<NodeFormat_Expr>>, preChildren: Array<SyntaxNodeImpl>, isInterpol!: Bool = false): NonTerminal {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        let nodeBase = lit.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let quoteToken = builder.buildTripleQuote(isSingle)
        if (isInterpol) {
            ret.add(value)
        } else {
            ret.add(quoteToken)
            moveCursorColumn(col: 3)
            ret.add(builder.buildNewline(1))
            moveCursorLine()
            if (interpols.size == 0) {
                ret.add(value)
            }
            for (interpol in interpols) {
                if (let Some(interp) <- interpol) {
                    addChild(ret, transExpr(interp, isInterpol: true))
                }
            }
            ret.add(quoteToken)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        builder.buildNonTerminal(SyntaxNodeKind.MultiLineStringLiteral, ret.toArray(), preChildren: preChildren)
    }

    private func transLitConst(lit: NodeFormat_LitConstExpr, preChildren: Array<SyntaxNodeImpl>,
        isInterpol!: Bool = false): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(lit.GetBase())

        let literal = lit.GetLiteral()
        let kind = lit.GetLiteralConstKind()
        let strKind = lit.GetStringKind()
        let isSingle = lit.GetIsSingleQuote()
        let litToken = builder.buildValuedTerminal(SyntaxNodeKind.StringLiteralToken, literal)
        let interpols = lit.GetInterpol()
        if (isInterpol && literal == "") { // filter empty value part in the end (if there is)
            return None
        }
        let ret = match (kind) {
            case 0 /*INTEGER*/ => transValuedLiteral(lit, preChildren)
            case 1 /*RUNE_BYTE*/ => throw Exception("Rune Byte literal is not supported in syntax")
            case 2 /*FLOAT*/ => transValuedLiteral(lit, preChildren)
            case 3 /*RUNE*/ => buildRuneLiteral(lit, litToken, isSingle)
            case 4 /*STRING*/ => match (strKind) {
                case 0 /*NORMAL*/ => buildLineStringLiteral(lit.GetBase(), litToken, isSingle, interpols, preChildren,
                    isInterpol: isInterpol)
                // JString is processed before case
                // case 1 /*JSTRING*/ => builder.buildValuedTerminal(SyntaxNodeKind.JStringLiteralToken, literal)
                case 2 /*MULTILINE*/ => buildMultiLineStringLiteral(lit, litToken, isSingle, interpols, preChildren,
                    isInterpol: isInterpol)
                case 3 /*MULTILINE_RAW*/ => buildMultiLineRawStringLiteral(lit, litToken, Int64(lit.GetDelimiterNum()), isSingle)
                case _ => builder.buildInvalidTerminal() // JString is processed before case
            }
            case 5 /*JSTRING*/ => builder.buildValuedTerminal(SyntaxNodeKind.JStringLiteralToken, literal)
            case 6 /*BOOL*/ => transValuedLiteral(lit, preChildren)
            case 7 /*UNIT*/ => transUnitLiteral(lit, preChildren)
            case _ => builder.buildInvalidTerminal() /* or return none*/
        }
        if (!isInterpol) {
            moveCursorToEnd(lit.GetBase())
        }
        ret
    }

    func buildRuneLiteral(lit: NodeFormat_LitConstExpr, value: ValuedTerminal, isSingle: Bool,
        preChildren!: Array<SyntaxNodeImpl> = []): NonTerminal {
        let ret = ArrayList<SyntaxNodeImpl>(preChildren)
        let nodeBase = lit.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let quoteToken = builder.buildQuote(isSingle)
        let prefix = builder.buildBasicTerminal(SyntaxNodeKind.RunePrefixToken)
        ret.add(all: [prefix, quoteToken, value, quoteToken])
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        builder.buildNonTerminal(SyntaxNodeKind.RuneLiteral, ret.toArray())
    }

    func buildMultiLineRawStringLiteral(lit: NodeFormat_LitConstExpr, value: ValuedTerminal, delimiterNum: Int64,
        isSingle: Bool, preChildren!: Array<SyntaxNodeImpl> = []): NonTerminal {
        let ret = ArrayList<SyntaxNodeImpl>(preChildren)
        let nodeBase = lit.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let quoteToken = builder.buildQuote(isSingle)
        let hashToken = builder.buildHash(delimiterNum)
        ret.add(all: [hashToken, quoteToken, value, quoteToken, hashToken])
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        builder.buildNonTerminal(SyntaxNodeKind.MultiLineRawStringLiteral, ret.toArray())
    }

    private func transValuedLiteral(lit: NodeFormat_LitConstExpr, preChildren: Array<SyntaxNodeImpl>): SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = lit.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let literal = lit.GetLiteral()
        let kind = lit.GetLiteralConstKind()
        let kindNode = match (kind) {
            case 0 /*INTEGER*/ => builder.buildValuedTerminal(SyntaxNodeKind.IntegerLiteralToken, literal)
            case 2 /*FLOAT*/ => builder.buildValuedTerminal(SyntaxNodeKind.FloatLiteralToken, literal)
            case 5 /*JSTRING*/ => builder.buildValuedTerminal(SyntaxNodeKind.JStringLiteralToken, literal)
            case 6 /*BOOL*/ => builder.buildValuedTerminal(SyntaxNodeKind.BooleanLiteralToken, literal)
            case _ => builder.buildInvalidTerminal() /* or return none*/
        }

        addChild(ret, kindNode)
        moveCursorColumn(col: Int32(literal.size))
        addWhitespaceAndMoveCursorToEnd(lit.GetBase())

        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ValuedLiteral, ret.toArray(), preChildren: preChildren)
    }

    private func transUnitLiteral(lit: NodeFormat_LitConstExpr, preChildren: Array<SyntaxNodeImpl>): SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = lit.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        ret.add(builder.buildBasicTerminal(SyntaxNodeKind.LParenToken))
        moveCursorColumn()
        addWhitespaceAndMoveCursorToEnd(lit.GetBase())
        ret.add(builder.buildBasicTerminal(SyntaxNodeKind.RParenToken))
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.UnitLiteral, ret.toArray(), preChildren: preChildren)
    }

    private func transLetPattern(letPattern: NodeFormat_LetPatternDestructor, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(letPattern.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = letPattern.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(db) <- letPattern.GetBase()) {
            transBasicTerminal(db.GetBegin(), SyntaxNodeKind.LetToken)
        }

        let patterns = letPattern.GetPatterns()
        let bitOrTokens = letPattern.GetBitOrPosVec()

        for (i in 0..patterns.size) {
            if (let Some(pattern) <- patterns[i]) {
                addChild(ret, transPattern(pattern))
                resetGlobalVariables(ret, innerCmts)
                if (i < bitOrTokens.size) {
                    transBasicTerminal(bitOrTokens[i], SyntaxNodeKind.BitOrToken)
                }
            }
        }

        resetGlobalVariables(ret, innerCmts)

        transBasicTerminal(letPattern.GetBackarrowPos(), SyntaxNodeKind.BackArrowToken)

        if (let Some(expr) <- letPattern.GetInitializer()) {
            transNoTerminalExpr(expr)
        }
        resetGlobalVariables(ret, innerCmts)
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.LetPattern, ret.toArray(), preChildren: preChildren)
    }

    // recursively parse the OR expressions in the DisjunctionCondition
    private func createOr(ret: ArrayList<SyntaxNodeImpl>, cond: NodeFormat_Expr): Unit {
        // current Expr is BinaryExpr and opkind is OR, split the Expr to two ConjunctionCond
        if (let Some(binaryExpr) <- cond.GetExprAsBinaryExpr() && getSyntaxImplKind(binaryExpr.GetOperatorKind()) == SyntaxNodeKind
            .OrToken) {
            if (let Some(lhs) <- binaryExpr.GetLeftExpr()) {
                createOr(ret, lhs)
                curChildren = ret
            }
            transBasicTerminal(binaryExpr.GetOperatorPos(), SyntaxNodeKind.OrToken)
            if (let Some(rhs) <- binaryExpr.GetRightExpr()) {
                createOr(ret, rhs)
                curChildren = ret
            }
        } else {
            // parse current expr as one ConjunctionCond
            addChild(ret, transConjunctionCondition(cond))
            curChildren = ret
        }
    }

    // parse left expr and right expr to AtomicConds separately
    private func createAnd(ret: ArrayList<SyntaxNodeImpl>, binaryExpr: NodeFormat_BinaryExpr): Unit {
        if (let Some(lhs) <- binaryExpr.GetLeftExpr()) {
            createAtomicCond(ret, lhs)
            curChildren = ret
        }
        transBasicTerminal(binaryExpr.GetOperatorPos(), SyntaxNodeKind.AndToken)
        if (let Some(rhs) <- binaryExpr.GetRightExpr()) {
            createAtomicCond(ret, rhs)
            curChildren = ret
        }
    }

    // recursively parse the AtomicCondition in the ConjunctionCondition
    // BNF: | letpattern | parenCond | expr
    private func createAtomicCond(ret: ArrayList<SyntaxNodeImpl>, cond: NodeFormat_Expr): Unit {
        curChildren = ret
        // current Expr is BinaryExpr and opkind is AND, split the Expr to two AtomicCond
        if (let Some(binaryExpr) <- cond.GetExprAsBinaryExpr() && getSyntaxImplKind(binaryExpr.GetOperatorKind()) == SyntaxNodeKind
            .AndToken) {
            createAnd(ret, binaryExpr)
        } else if (let Some(parenExpr) <- cond.GetExprAsParenExpr()) {
            // current Expr is ParenExpr, parse it as parenCond
            addChild(ret, transParenCondition(parenExpr))
            curChildren = ret
        } else {
            // parse current expr as one AtomicCond
            transNoTerminalExpr(cond)
        }
    }

    // BNF: conjunctionCond ||  conjunctionCond  || conjunctionCond ...
    private func transDisjunctionCondition(disjunctionCondition: NodeFormat_Expr): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(disjunctionCondition.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        createOr(ret, disjunctionCondition)
        builder.buildNonTerminal(SyntaxNodeKind.DisjunctionCondition, ret.toArray())
    }

    // BNF: atomicCond && atomicCond && atomicCond ...
    private func transConjunctionCondition(conjunctionCondition: NodeFormat_Expr): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(conjunctionCondition.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        createAtomicCond(ret, conjunctionCondition)
        builder.buildNonTerminal(SyntaxNodeKind.ConjunctionCondition, ret.toArray())
    }

    // BNF: ( disjunctionCond )
    private func transParenCondition(parenCondition: NodeFormat_ParenExpr): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(parenCondition.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = parenCondition.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        transBasicTerminal(parenCondition.GetLeftParenPos(), SyntaxNodeKind.LParenToken)

        if (let Some(expr) <- parenCondition.GetExpr()) {
            addChild(ret, transDisjunctionCondition(expr))
            resetGlobalVariables(ret, innerCmts)
        }
        transBasicTerminal(parenCondition.GetRightParenPos(), SyntaxNodeKind.RParenToken)

        moveCursorToEnd(parenCondition.GetBase())
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.ParenCondition, ret.toArray())
    }

    private func transQuoteTokenExpr(tokenPart: NodeFormat_TokenPart, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret
        for (tk in tokenPart.GetTokens()) {
            if (let Some(v) <- tk) {
                transTokenTerminal(v.GetPos(), getTokenKind(v.GetKind()), v.GetValue(), needNewLine: false,
                    delimiterNum: v.GetDelimiterNum(), isSingleQuote: v.GetIsSingleQuote(), hasEscape: v.GetHasEscape())
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.QuoteTokenExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transQuoteInterpolationExpr(expr: NodeFormat_Expr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = expr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        let table = expr.table
        let o: UInt16 = table.offset(expr.EXPR)
        let off: UInt32 = UInt32(o) + table.pos
        match (expr.GetExprType()) {
            case NodeFormat_AnyExpr.AnyExpr_REF_EXPR =>
                ret.add(builder.buildBasicTerminal(SyntaxNodeKind.DollarToken))
                addChild(ret, transExpr(expr))
                moveCursorToEnd(expr.GetBase())
            case NodeFormat_AnyExpr.AnyExpr_PAREN_EXPR =>
                let parenExpr = NodeFormat_ParenExpr(table.bytes, off)
                if (let Some(base) <- parenExpr.GetBase()) {
                    transBasicTerminal(base.GetBegin(), SyntaxNodeKind.DollarToken)
                }
                transBasicTerminal(parenExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
                if (let Some(expr1) <- parenExpr.GetExpr()) {
                    addChild(ret, transExpr(expr1))
                    curChildren = ret
                }
                transBasicTerminal(parenExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
            case _ => ()
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.QuoteInterpolationExpr, ret.toArray(), preChildren: preChildren)
    }

    func moveCursorByExpr(expr: NodeFormat_Expr): Unit {
        if (let Some(base) <- expr.GetBase()) {
            let begin = base.GetBegin()
            let (beginLine, beginColumn) = match (expr.GetExprType()) {
                case NodeFormat_AnyExpr.AnyExpr_REF_EXPR => (begin.line, begin.column - 1)
                case _ => (begin.line, begin.column)
            }
            addWhitespace(beginLine, beginColumn, needNewLine: false)
            // move cursor
            (cursorLine, cursorColumn) = (beginLine, beginColumn)
        }
    }

    private func transQuoteExpr(quoteExpr: NodeFormat_QuoteExpr, preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(quoteExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = quoteExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(exprBase) <- quoteExpr.GetBase()) {
            transBasicTerminal(exprBase.GetBegin(), SyntaxNodeKind.QuoteToken)
            transBasicTerminal(quoteExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
            let children = quoteExpr.GetExprs()
            for (expr in getElements<NodeFormat_Expr>(children)) {
                moveCursorByExpr(expr)
                let expr1 = match (expr.GetExprType()) {
                    case NodeFormat_AnyExpr.AnyExpr_TOKEN_PART => transExpr(expr)
                    case _ => transQuoteInterpolationExpr(expr)
                }
                addChild(ret, expr1)
                resetGlobalVariables(ret, innerCmts)
            }
            transBasicTerminal(quoteExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.QuoteExpr, ret.toArray(), preChildren: preChildren)
    }

    private func transTrailingClosureExpr(trailingClosureExpr: NodeFormat_TrailingClosureExpr,
        preChildren: Array<SyntaxNodeImpl>): ?SyntaxNodeImpl {
        addWhitespaceAndMoveCursorToBegin(trailingClosureExpr.GetBase())
        let ret = ArrayList<SyntaxNodeImpl>()
        addLeadCommentNodesToRet(ret)
        curChildren = ret

        let nodeBase = trailingClosureExpr.GetBase()
        let (leadCmts, innerCmts, trailCmts) = getCommentGroups(nodeBase)
        addLeadingComments(nodeBase, ret, leadCmts)
        innerComments = innerCmts

        if (let Some(expr) <- trailingClosureExpr.GetExpr()) {
            if (let Some(callExpr) <- expr.GetExprAsCallExpr()) {
                addWhitespaceAndMoveCursorToBegin(callExpr.GetBase())
                // baseFunc
                if (let Some(baseFunc) <- callExpr.GetBaseFunc()) {
                    transNoTerminalExpr(baseFunc)
                    resetGlobalVariables(ret, innerCmts)
                }
                transBasicTerminal(callExpr.GetLeftParenPos(), SyntaxNodeKind.LParenToken)
                // funcArgs
                let args = callExpr.GetArgs()
                for (arg in getElements<NodeFormat_FuncArg>(args)) {
                    addWhitespaceAndMoveCursorToBegin(arg.GetBase())
                    addChild(ret, transFuncArg(arg))
                    resetGlobalVariables(ret, innerCmts)
                    transBasicTerminal(arg.GetCommaPos(), SyntaxNodeKind.CommaToken)
                }
                resetGlobalVariables(ret, innerCmts)
                transBasicTerminal(callExpr.GetRightParenPos(), SyntaxNodeKind.RParenToken)
                moveCursorToEnd(callExpr.GetBase())
            } else if (let Some(refExpr) <- expr.GetExprAsRefExpr()) {
                addChild(ret, transRefExpr(refExpr))
                moveCursorToEnd(refExpr.GetBase())
                resetGlobalVariables(ret, innerCmts)
            } else if (let Some(memberAccess) <- expr.GetExprAsMemberAccess()) {
                addChild(ret, transMemberAccess(memberAccess))
                moveCursorToEnd(memberAccess.GetBase())
                resetGlobalVariables(ret, innerCmts)
            }
        }
        if (let Some(lambda) <- trailingClosureExpr.GetLambda()) {
            addChild(ret, transLambda(lambda))
            moveCursorToEnd(lambda.GetBase())
            resetGlobalVariables(ret, innerCmts)
        }
        if (trailCmts.size > 0) {
            addChild(ret, transCommentGroupList(trailCmts))
            resetGlobalVariables(ret, innerCmts)
        }
        innerComments = Array<Option<NodeFormat_CommentGroup>>()
        builder.buildNonTerminal(SyntaxNodeKind.TrailingClosureExpr, ret.toArray(), preChildren: preChildren)
    }

    private func getCommentGroups(nodeBase: ?NodeFormat_NodeBase) {
        if (let Some(node) <- nodeBase && let Some(cmts) <- node.GetComments()) {
            (cmts.GetLeadingComments(), cmts.GetInnerComments(), cmts.GetTrailingComments())
        } else {
            (Array<Option<NodeFormat_CommentGroup>>(), Array<Option<NodeFormat_CommentGroup>>(),
                Array<Option<NodeFormat_CommentGroup>>())
        }
    }

    private func getCommentGroupListBeginPos(groupList: Array<Option<NodeFormat_CommentGroup>>): ?NodeFormat_Position {
        if (groupList.size > 0) {
            let beginCmtGroup = groupList[0].getOrThrow()
            if (beginCmtGroup.GetCms().size > 0 && let Some(beginComment) <- beginCmtGroup.GetCms()[0] && let Some(tk) <- beginComment
                .GetInfo()) {
                return tk.GetPos()
            }
        }
        None
    }

    private func addLeadingComments(nodeBase: ?NodeFormat_NodeBase, ret: ArrayList<SyntaxNodeImpl>,
        leadCmts: Array<Option<NodeFormat_CommentGroup>>, isDecl!: Bool = false) {
        if (leadCmts.size > 0 && let Some(beginPos) <- getCommentGroupListBeginPos(leadCmts) && let Some(node) <- nodeBase) {
            addWhitespaceAndMoveCursor(beginPos)
            curChildren = ret
            addChild(ret, transCommentGroupList(leadCmts))
            curChildren = ret
            if (!isDecl) {
                addWhitespaceAndMoveCursor(node.GetBegin())
            }
        }
    }

    private func addLeadCommentNodesToRet(ret: ArrayList<SyntaxNodeImpl>) {
        if (leadCommentNodes.size > 0) {
            ret.add(all: leadCommentNodes)
            leadCommentNodes = ArrayList<SyntaxNodeImpl>()
        }
    }

    private func addTrailCommentNodesToRet(ret: ArrayList<SyntaxNodeImpl>,
        innerCmts: Array<Option<NodeFormat_CommentGroup>>) {
        if (trailComments.size > 0) {
            addChild(ret, transCommentGroupList(trailComments))
            trailComments = Array<Option<NodeFormat_CommentGroup>>()
            resetGlobalVariables(ret, innerCmts)
        }
    }

    private func transCommentGroupList(groupList: Array<Option<NodeFormat_CommentGroup>>): ?SyntaxNodeImpl {
        if (groupList.size == 0) {
            return None
        }
        let ret = ArrayList<SyntaxNodeImpl>()
        curChildren = ret

        for (node in groupList) {
            curChildren = ret
            if (let Some(cmtGroup) <- node) {
                addChild(ret, transCommentGroup(cmtGroup))
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.CommentGroupList, ret.toArray())
    }

    private func transCommentGroup(commentGroup: NodeFormat_CommentGroup): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()
        let cmts: Array<Option<NodeFormat_Comment>> = commentGroup.GetCms()
        if (cmts.size > 0 && let Some(cmt) <- cmts[0] && let Some(v) <- cmt.GetInfo()) {
            let begin = v.GetPos()
            addWhitespaceAndMoveCursor(begin)
        } else {
            return builder.buildNonTerminal(SyntaxNodeKind.CommentGroup, ret.toArray())
        }

        curChildren = ret

        for (node in cmts) {
            curChildren = ret
            if (let Some(cmt) <- node) {
                addChild(ret, transComment(cmt))
            }
        }
        builder.buildNonTerminal(SyntaxNodeKind.CommentGroup, ret.toArray())
    }

    private func transComment(comment: NodeFormat_Comment): ?SyntaxNodeImpl {
        let ret = ArrayList<SyntaxNodeImpl>()

        if (let Some(v) <- comment.GetInfo()) {
            addWhitespaceAndMoveCursor(v.GetPos(), needNewLine: true)
            curChildren = ret
            transTokenTerminal(v.GetPos(), getTokenKind(v.GetKind()), v.GetValue(), needNewLine: true,
                delimiterNum: v.GetDelimiterNum(), isSingleQuote: v.GetIsSingleQuote(), hasEscape: v.GetHasEscape())
        }
        builder.buildNonTerminal(SyntaxNodeKind.Comment, ret.toArray())
    }
}