Input:
import random
import copy
import sys
import os
import bitsandbytes as bnb
import torch.nn as nn
import transformers
import torch
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import CUDA_VISIBLE_DEVICES, USE_TORCH, CPU_NUMS  # from config
from transformers.models.auto.modeling_auto import MODEL_FOR_CAUSAL_LM_MAPPING_NAMES
from peft import (get_peft_model_state_dict, get_peft_model, LoraConfig)
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.modeling_utils import unwrap_model
from tensorboardX import SummaryWriter
from datasets import load_dataset
from macro_gpt.models.llama.modeling_llama import LlamaForCausalLM as LLMForCausalLM
from macro_gpt.models.llama.tokenization_llama import LlamaTokenizer as LLMTokenizer
from macro_gpt.models.llama.modeling_llama import LlamaConfig as LLMConfig
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import PATH_MODEL_PRETRAIN, DATA_PATH, MODEL_SAVE_DIR, REPO_ID
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import MICRO_BATCH_SIZE, BATCH_SIZE, GRADIENT_ACCUMULATION_STEPS
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import LEARNING_RATE, EPOCHS, SAVE_STEPS, VAL_SET_SIZE, TARGET_MODULES
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import IS_PARALLELIZABLE, MODEL_PARALLEL, USE_CACHE
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import MAX_LENGTH_Q, MAX_LENGTH_A, MAX_LENGTH_QA
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import LORA_DROPOUT, LORA_ALPHA, LORA_R
from macro_gpt.ft_gpt.config_macrogpt_1b3_float32 import PATH_MODEL_CONFIG, PATH_TOKENIZER_PRETRAIN

Context:
macro_gpt/ft_gpt/train.pt.py
# !/usr/bin/python
# -*- coding: utf-8 -*-
# @time    : 2023/3/5 21:04
# @author  : Mo
# @function: macro-gpt

path_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
sys.path.append(path_root)
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:3072"

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
MODEL_PARALLEL = False

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
REPO_ID = "Macropodus/macrogpt-tokenizer"

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
MODEL_SAVE_DIR = "model_macrogpt_1b3_float32"

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
DATA_PATH = "../datasets/tigerbot-train-00001-of-00097.json"

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
CPU_NUMS = "9"

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
TARGET_MODULES = ["query_key_value"]

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
LORA_ALPHA = 16

macro_gpt/models/llama/modeling_llama.py
def is_flash_attn_available():
    def _is_package_available(pkg_name: str, return_version: bool = False) -> Union[Tuple[bool, str], bool]:
def _get_unpad_data(padding_mask):
def _make_causal_mask(
    input_ids_shape: torch.Size, dtype: torch.dtype, device: torch.device, past_key_values_length: int = 0
):
def _expand_mask(mask: torch.Tensor, dtype: torch.dtype, tgt_len: Optional[int] = None):
    def __init__(self, hidden_size, eps=1e-6):
    def forward(self, hidden_states):
    def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None):
    def _set_cos_sin_cache(self, seq_len, device, dtype):
    def forward(self, x, seq_len=None):
    def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None, scaling_factor=1.0):
    def _set_cos_sin_cache(self, seq_len, device, dtype):
    def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None, scaling_factor=1.0):
    def _set_cos_sin_cache(self, seq_len, device, dtype):
def rotate_half(x):
def apply_rotary_pos_emb(q, k, cos, sin, position_ids):
    def __init__(self, config):
    def forward(self, x):
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
    def __init__(self, config: LlamaConfig):
    def _init_rope(self):
    def _shape(self, tensor: torch.Tensor, seq_len: int, bsz: int):
    def forward(
        self,
        hidden_states: torch.Tensor,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_value: Optional[Tuple[torch.Tensor]] = None,
        output_attentions: bool = False,
        use_cache: bool = False,
        padding_mask: Optional[torch.LongTensor] = None,
    ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
    def forward(
        self,
        hidden_states: torch.Tensor,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_value: Optional[Tuple[torch.Tensor]] = None,
        output_attentions: bool = False,
        use_cache: bool = False,
        padding_mask: Optional[torch.LongTensor] = None,
    ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
    def _flash_attention_forward(
        self, query_states, key_states, value_states, padding_mask, query_length, dropout=0.0, softmax_scale=None
    ):
    def _upad_input(self, query_layer, key_layer, value_layer, padding_mask, query_length):
    def __init__(self, config: LlamaConfig):
    def forward(
        self,
        hidden_states: torch.Tensor,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_value: Optional[Tuple[torch.Tensor]] = None,
        output_attentions: Optional[bool] = False,
        use_cache: Optional[bool] = False,
        padding_mask: Optional[torch.LongTensor] = None,
    ) -> Tuple[torch.FloatTensor, Optional[Tuple[torch.FloatTensor, torch.FloatTensor]]]:
    def _init_weights(self, module):
    def _set_gradient_checkpointing(self, module, value=False):
    def __init__(self, config: LlamaConfig):
    def get_input_embeddings(self):
    def set_input_embeddings(self, value):
    def _prepare_decoder_attention_mask(self, attention_mask, input_shape, inputs_embeds, past_key_values_length):
    def forward(
        self,
        input_ids: torch.LongTensor = None,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_values: Optional[List[torch.FloatTensor]] = None,
        inputs_embeds: Optional[torch.FloatTensor] = None,
        use_cache: Optional[bool] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
    ) -> Union[Tuple, BaseModelOutputWithPast]:
                def create_custom_forward(module):
                    def custom_forward(*inputs):
    def __init__(self, config):
    def get_input_embeddings(self):
    def set_input_embeddings(self, value):
    def get_output_embeddings(self):
    def set_output_embeddings(self, new_embeddings):
    def set_decoder(self, decoder):
    def get_decoder(self):
    def forward(
        self,
        input_ids: torch.LongTensor = None,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_values: Optional[List[torch.FloatTensor]] = None,
        inputs_embeds: Optional[torch.FloatTensor] = None,
        labels: Optional[torch.LongTensor] = None,
        use_cache: Optional[bool] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
    ) -> Union[Tuple, CausalLMOutputWithPast]:
    def prepare_inputs_for_generation(
        self, input_ids, past_key_values=None, attention_mask=None, inputs_embeds=None, **kwargs
    ):
    def _reorder_cache(past_key_values, beam_idx):
    def __init__(self, config):
    def get_input_embeddings(self):
    def set_input_embeddings(self, value):
    def forward(
        self,
        input_ids: torch.LongTensor = None,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_values: Optional[List[torch.FloatTensor]] = None,
        inputs_embeds: Optional[torch.FloatTensor] = None,
        labels: Optional[torch.LongTensor] = None,
        use_cache: Optional[bool] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
    ) -> Union[Tuple, SequenceClassifierOutputWithPast]:
_CONFIG_FOR_DOC = "LlamaConfig"
LLAMA_START_DOCSTRING = r"""
    This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the
    library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads
    etc.)

    This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.
    Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage
    and behavior.

    Parameters:
        config ([`LlamaConfig`]):
            Model configuration class with all the parameters of the model. Initializing with a config file does not
            load the weights associated with the model, only the configuration. Check out the
            [`~PreTrainedModel.from_pretrained`] method to load the model weights.
"""
LLAMA_INPUTS_DOCSTRING = r"""
    Args:
        input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
            Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
            it.

            Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
            [`PreTrainedTokenizer.__call__`] for details.

            [What are input IDs?](../glossary#input-ids)
        attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
            Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:

            - 1 for tokens that are **not masked**,
            - 0 for tokens that are **masked**.

            [What are attention masks?](../glossary#attention-mask)

            Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
            [`PreTrainedTokenizer.__call__`] for details.

            If `past_key_values` is used, optionally only the last `input_ids` have to be input (see
            `past_key_values`).

            If you want to change padding behavior, you should read [`modeling_opt._prepare_decoder_attention_mask`]
            and modify to your needs. See diagram 1 in [the paper](https://arxiv.org/abs/1910.13461) for more
            information on the default strategy.

            - 1 indicates the head is **not masked**,
            - 0 indicates the head is **masked**.
        position_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
            Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
            config.n_positions - 1]`.

            [What are position IDs?](../glossary#position-ids)
        past_key_values (`tuple(tuple(torch.FloatTensor))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
            Tuple of `tuple(torch.FloatTensor)` of length `config.n_layers`, with each tuple having 2 tensors of shape
            `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape
            `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.

            Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
            blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.

            If `past_key_values` are used, the user can optionally input only the last `input_ids` (those that don't
            have their past key value states given to this model) of shape `(batch_size, 1)` instead of all `input_ids`
            of shape `(batch_size, sequence_length)`.
        inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
            Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This
            is useful if you want more control over how to convert `input_ids` indices into associated vectors than the
            model's internal embedding lookup matrix.
        use_cache (`bool`, *optional*):
            If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding (see
            `past_key_values`).
        output_attentions (`bool`, *optional*):
            Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
            tensors for more detail.
        output_hidden_states (`bool`, *optional*):
            Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
            more detail.
        return_dict (`bool`, *optional*):
            Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
"""
class LlamaRMSNorm(nn.Module):
class LlamaRotaryEmbedding(nn.Module):
class LlamaLinearScalingRotaryEmbedding(LlamaRotaryEmbedding):
class LlamaDynamicNTKScalingRotaryEmbedding(LlamaRotaryEmbedding):
class LlamaMLP(nn.Module):
class LlamaAttention(nn.Module):
class LlamaFlashAttention2(LlamaAttention):
class LlamaDecoderLayer(nn.Module):
class LlamaPreTrainedModel(PreTrainedModel):
class LlamaModel(LlamaPreTrainedModel):
class LlamaForCausalLM(LlamaPreTrainedModel):
class LlamaForSequenceClassification(LlamaPreTrainedModel):

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
PATH_MODEL_PRETRAIN = ""

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
GRADIENT_ACCUMULATION_STEPS = BATCH_SIZE // MICRO_BATCH_SIZE

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
MAX_LENGTH_QA = MAX_LENGTH_Q + MAX_LENGTH_A + 4

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
MAX_LENGTH_A = 1024 - 2  # default=128 - 2

macro_gpt/models/llama/modeling_llama.py
class LlamaForCausalLM(LlamaPreTrainedModel):
    _tied_weights_keys = ["lm_head.weight"]

    def __init__(self, config):
        super().__init__(config)
        self.model = LlamaModel(config)
        self.vocab_size = config.vocab_size
        self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
        # Initialize weights and apply final processing
        self.post_init()

    def get_input_embeddings(self):
        return self.model.embed_tokens

    def set_input_embeddings(self, value):
        self.model.embed_tokens = value

    def get_output_embeddings(self):
        return self.lm_head

    def set_output_embeddings(self, new_embeddings):
        self.lm_head = new_embeddings

    def set_decoder(self, decoder):
        self.model = decoder

    def get_decoder(self):
        return self.model

    @add_start_docstrings_to_model_forward(LLAMA_INPUTS_DOCSTRING)
    @replace_return_docstrings(output_type=CausalLMOutputWithPast, config_class=_CONFIG_FOR_DOC)
    def forward(
        self,
        input_ids: torch.LongTensor = None,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_values: Optional[List[torch.FloatTensor]] = None,
        inputs_embeds: Optional[torch.FloatTensor] = None,
        labels: Optional[torch.LongTensor] = None,
        use_cache: Optional[bool] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
    ) -> Union[Tuple, CausalLMOutputWithPast]:
        r"""
        Args:
            labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
                Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
                config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
                (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.

        Returns:

        Example:

        ```python
        >>> from transformers import AutoTokenizer, LlamaForCausalLM

        >>> model = LlamaForCausalLM.from_pretrained(PATH_TO_CONVERTED_WEIGHTS)
        >>> tokenizer = AutoTokenizer.from_pretrained(PATH_TO_CONVERTED_TOKENIZER)

        >>> prompt = "Hey, are you conscious? Can you talk to me?"
        >>> inputs = tokenizer(prompt, return_tensors="pt")

        >>> # Generate
        >>> generate_ids = model.generate(inputs.input_ids, max_length=30)
        >>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
        "Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you."
        ```"""

        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
        output_hidden_states = (
            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
        )
        return_dict = return_dict if return_dict is not None else self.config.use_return_dict

        # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)
        outputs = self.model(
            input_ids=input_ids,
            attention_mask=attention_mask,
            position_ids=position_ids,
            past_key_values=past_key_values,
            inputs_embeds=inputs_embeds,
            use_cache=use_cache,
            output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,
            return_dict=return_dict,
        )

        hidden_states = outputs[0]
        if self.config.pretraining_tp > 1:
            lm_head_slices = self.lm_head.weight.split(self.vocab_size // self.config.pretraining_tp, dim=0)
            logits = [F.linear(hidden_states, lm_head_slices[i]) for i in range(self.config.pretraining_tp)]
            logits = torch.cat(logits, dim=-1)
        else:
            # logits = self.lm_head(hidden_states)
            logits = self.lm_head(hidden_states.to(self.lm_head.weight.dtype))
        logits = logits.float()

        loss = None
        if labels is not None:
            # Shift so that tokens < n predict n
            shift_logits = logits[..., :-1, :].contiguous()
            shift_labels = labels[..., 1:].contiguous()
            # Flatten the tokens
            loss_fct = CrossEntropyLoss()
            shift_logits = shift_logits.view(-1, self.config.vocab_size)
            shift_labels = shift_labels.view(-1)
            # Enable model parallelism
            shift_labels = shift_labels.to(shift_logits.device)
            loss = loss_fct(shift_logits, shift_labels)

        if not return_dict:
            output = (logits,) + outputs[1:]
            return (loss,) + output if loss is not None else output

        return CausalLMOutputWithPast(
            loss=loss,
            logits=logits,
            past_key_values=outputs.past_key_values,
            hidden_states=outputs.hidden_states,
            attentions=outputs.attentions,
        )

    def prepare_inputs_for_generation(
        self, input_ids, past_key_values=None, attention_mask=None, inputs_embeds=None, **kwargs
    ):
        if past_key_values is not None:
            past_length = past_key_values[0][0].shape[2]

            # Some generation methods already pass only the last input ID
            if input_ids.shape[1] > past_length:
                remove_prefix_length = past_length
            else:
                # Default to old behavior: keep only final ID
                remove_prefix_length = input_ids.shape[1] - 1

            input_ids = input_ids[:, remove_prefix_length:]

        position_ids = kwargs.get("position_ids", None)
        if attention_mask is not None and position_ids is None:
            # create position_ids on the fly for batch generation
            position_ids = attention_mask.long().cumsum(-1) - 1
            position_ids.masked_fill_(attention_mask == 0, 1)
            if past_key_values:
                position_ids = position_ids[:, -input_ids.shape[1] :]

        # if `inputs_embeds` are passed, we only want to use them in the 1st generation step
        if inputs_embeds is not None and past_key_values is None:
            model_inputs = {"inputs_embeds": inputs_embeds}
        else:
            model_inputs = {"input_ids": input_ids}

        model_inputs.update(
            {
                "position_ids": position_ids,
                "past_key_values": past_key_values,
                "use_cache": kwargs.get("use_cache"),
                "attention_mask": attention_mask,
            }
        )
        return model_inputs

    @staticmethod
    def _reorder_cache(past_key_values, beam_idx):
        reordered_past = ()
        for layer_past in past_key_values:
            reordered_past += (
                tuple(past_state.index_select(0, beam_idx.to(past_state.device)) for past_state in layer_past),
            )
        return reordered_past

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
MICRO_BATCH_SIZE = 4  # default=4  # this could actually be 5 but i like powers of 2

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
PATH_MODEL_CONFIG = "config_macrogpt_1b3_float32.json" or MODEL_SAVE_DIR

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
USE_CACHE = False

macro_gpt/ft_gpt/config_macrogpt_1b3_float32.py
VAL_SET_SIZE = 0

macro_gpt/models/llama/tokenization_llama.py
class LlamaTokenizer(PreTrainedTokenizer):
    """
    Construct a Llama tokenizer. Based on byte-level Byte-Pair-Encoding. The default padding token is unset as there is
    no padding token in the original model.

    Args:
        vocab_file (`str`):
            Path to the vocabulary file.
        unk_token (`str` or `tokenizers.AddedToken`, *optional*, defaults to `"<unk>"`):
            The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
            token instead.
        bos_token (`str` or `tokenizers.AddedToken`, *optional*, defaults to `"<s>"`):
            The beginning of sequence token that was used during pretraining. Can be used a sequence classifier token.
        eos_token (`str` or `tokenizers.AddedToken`, *optional*, defaults to `"</s>"`):
            The end of sequence token.
        pad_token (`str` or `tokenizers.AddedToken`, *optional*):
            A special token used to make arrays of tokens the same size for batching purpose. Will then be ignored by
            attention mechanisms or loss computation.
        sp_model_kwargs (`Dict[str, Any]`, `Optional`, *optional*):
            Will be passed to the `SentencePieceProcessor.__init__()` method. The [Python wrapper for
            SentencePiece](https://github.com/google/sentencepiece/tree/master/python) can be used, among other things,
            to set:

            - `enable_sampling`: Enable subword regularization.
            - `nbest_size`: Sampling parameters for unigram. Invalid for BPE-Dropout.

              - `nbest_size = {0,1}`: No sampling is performed.
              - `nbest_size > 1`: samples from the nbest_size results.
              - `nbest_size < 0`: assuming that nbest_size is infinite and samples from the all hypothesis (lattice)
                using forward-filtering-and-backward-sampling algorithm.

            - `alpha`: Smoothing parameter for unigram sampling, and dropout probability of merge operations for
              BPE-dropout.

        add_bos_token (`bool`, *optional*, defaults to `True`):
            Whether or not to add an `bos_token` at the start of sequences.
        add_eos_token (`bool`, *optional*, defaults to `False`):
            Whether or not to add an `eos_token` at the end of sequences.
        clean_up_tokenization_spaces (`bool`, *optional*, defaults to `False`):
            Whether or not to cleanup spaces after decoding, cleanup consists in removing potential artifacts like
            extra spaces.
        use_default_system_prompt (`bool`, *optional*, defaults to `True`):
            Whether or not the default system prompt for Llama should be used.
        spaces_between_special_tokens (`bool`, *optional*, defaults to `False`):
            Whether or not to add spaces between special tokens.
        legacy (`bool`, *optional*):
            Whether or not the `legacy` behavior of the tokenizer should be used. Legacy is before the merge of #24622
            and #25224 which includes fixes to properly handle tokens that appear after special tokens. A simple
            example:

            - `legacy=True`:
            ```python
            >>> from transformers import T5Tokenizer

            >>> tokenizer = T5Tokenizer.from_pretrained("t5-base", legacy=True)
            >>> tokenizer.encode("Hello <extra_id_0>.")
            [8774, 32099, 3, 5, 1]
            ```
            - `legacy=False`:
            ```python
            >>> from transformers import T5Tokenizer

            >>> tokenizer = T5Tokenizer.from_pretrained("t5-base", legacy=False)
            >>> tokenizer.encode("Hello <extra_id_0>.")  # the extra space `[3]` is no longer here
            [8774, 32099, 5, 1]
            ```
            Checkout the [pull request](https://github.com/huggingface/transformers/pull/24565) for more details.

    """

    vocab_files_names = VOCAB_FILES_NAMES
    pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP
    max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
    model_input_names = ["input_ids", "attention_mask"]

    def __init__(
        self,
        vocab_file,
        unk_token="<unk>",
        bos_token="<s>",
        eos_token="</s>",
        pad_token=None,
        sp_model_kwargs: Optional[Dict[str, Any]] = None,
        add_bos_token=True,
        add_eos_token=False,
        clean_up_tokenization_spaces=False,
        use_default_system_prompt=True,
        spaces_between_special_tokens=False,
        legacy=None,
        **kwargs,
    ):
        self.sp_model_kwargs = {} if sp_model_kwargs is None else sp_model_kwargs
        bos_token = AddedToken(bos_token, lstrip=False, rstrip=False) if isinstance(bos_token, str) else bos_token
        eos_token = AddedToken(eos_token, lstrip=False, rstrip=False) if isinstance(eos_token, str) else eos_token
        unk_token = AddedToken(unk_token, lstrip=False, rstrip=False) if isinstance(unk_token, str) else unk_token
        pad_token = AddedToken(pad_token, lstrip=False, rstrip=False) if isinstance(pad_token, str) else pad_token

        if legacy is None:
            logger.warning_once(
                f"You are using the default legacy behaviour of the {self.__class__}. This is"
                " expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you."
                " If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it"
                " means, and thouroughly read the reason why this was added as explained in"
                " https://github.com/huggingface/transformers/pull/24565"
            )
            legacy = True

        self.legacy = legacy
        self.vocab_file = vocab_file
        self.add_bos_token = add_bos_token
        self.add_eos_token = add_eos_token
        self.use_default_system_prompt = use_default_system_prompt
        self.sp_model = self.get_spm_processor(kwargs.pop("from_slow", False))

        super().__init__(
            bos_token=bos_token,
            eos_token=eos_token,
            unk_token=unk_token,
            pad_token=pad_token,
            add_bos_token=add_bos_token,
            add_eos_token=add_eos_token,
            sp_model_kwargs=self.sp_model_kwargs,
            clean_up_tokenization_spaces=clean_up_tokenization_spaces,
            use_default_system_prompt=use_default_system_prompt,
            spaces_between_special_tokens=spaces_between_special_tokens,
            legacy=legacy,
            **kwargs,
        )

    @property
    def unk_token_length(self):
        return len(self.sp_model.encode(str(self.unk_token)))

    # Copied from transformers.models.t5.tokenization_t5.T5Tokenizer.get_spm_processor
    def get_spm_processor(self, from_slow=False):
        tokenizer = spm.SentencePieceProcessor(**self.sp_model_kwargs)
        if self.legacy or from_slow:  # no dependency on protobuf
            tokenizer.Load(self.vocab_file)
            return tokenizer

        with open(self.vocab_file, "rb") as f:
            sp_model = f.read()
            model_pb2 = import_protobuf(f"The new behaviour of {self.__class__.__name__} (with `self.legacy = False`)")
            model = model_pb2.ModelProto.FromString(sp_model)
            normalizer_spec = model_pb2.NormalizerSpec()
            normalizer_spec.add_dummy_prefix = False
            model.normalizer_spec.MergeFrom(normalizer_spec)
            sp_model = model.SerializeToString()
            tokenizer.LoadFromSerializedProto(sp_model)
        return tokenizer

    def __getstate__(self):
        state = self.__dict__.copy()
        state["sp_model"] = None
        state["sp_model_proto"] = self.sp_model.serialized_model_proto()
        return state

    def __setstate__(self, d):
        self.__dict__ = d
        self.sp_model = spm.SentencePieceProcessor(**self.sp_model_kwargs)
        self.sp_model.LoadFromSerializedProto(self.sp_model_proto)

    @property
    def vocab_size(self):
        """Returns vocab size"""
        return self.sp_model.get_piece_size()

    def get_vocab(self):
        """Returns vocab as a dict"""
        vocab = {self.convert_ids_to_tokens(i): i for i in range(self.vocab_size)}
        vocab.update(self.added_tokens_encoder)
        return vocab

    # Copied from transformers.models.t5.tokenization_t5.T5Tokenizer.tokenize
    def tokenize(self, text: "TextInput", add_special_tokens=False, **kwargs) -> List[str]:
        """
        Converts a string to a list of tokens. If `self.legacy` is set to `False`, a prefix token is added unless the
        first token is special.
        """
        if self.legacy or len(text) == 0:
            return super().tokenize(text, **kwargs)

        tokens = super().tokenize(SPIECE_UNDERLINE + text.replace(SPIECE_UNDERLINE, " "), **kwargs)

        if len(tokens) > 1 and tokens[0] == SPIECE_UNDERLINE and tokens[1] in self.all_special_tokens:
            tokens = tokens[1:]
        return tokens

    # Copied from transformers.models.t5.tokenization_t5.T5Tokenizer._tokenize
    def _tokenize(self, text, **kwargs):
        """
        Returns a tokenized string.

        We de-activated the `add_dummy_prefix` option, thus the sentencepiece internals will always strip any
        SPIECE_UNDERLINE. For example: `self.sp_model.encode(f"{SPIECE_UNDERLINE}Hey", out_type = str)` will give
        `['H', 'e', 'y']` instead of `['▁He', 'y']`. Thus we always encode `f"{unk_token}text"` and strip the
        `unk_token`. Here is an example with `unk_token = "<unk>"` and `unk_token_length = 4`.
        `self.tokenizer.sp_model.encode("<unk> Hey", out_type = str)[4:]`.
        """
        tokens = self.sp_model.encode(text, out_type=str)
        if self.legacy or not text.startswith((SPIECE_UNDERLINE, " ")):
            return tokens

        # 1. Encode string + prefix ex: "<unk> Hey"
        tokens = self.sp_model.encode(self.unk_token + text, out_type=str)
        # 2. Remove self.unk_token from ['<','unk','>', '▁Hey']
        return tokens[self.unk_token_length :] if len(tokens) >= self.unk_token_length else tokens

    def _convert_token_to_id(self, token):
        """Converts a token (str) in an id using the vocab."""
        return self.sp_model.piece_to_id(token)

    def _convert_id_to_token(self, index):
        """Converts an index (integer) in a token (str) using the vocab."""
        token = self.sp_model.IdToPiece(index)
        return token

    def convert_tokens_to_string(self, tokens):
        """Converts a sequence of tokens (string) in a single string."""
        # since we manually add the prefix space, we have to remove it when decoding
        if tokens[0].startswith(SPIECE_UNDERLINE):
            tokens[0] = tokens[0][1:]

        current_sub_tokens = []
        out_string = ""
        prev_is_special = False
        for i, token in enumerate(tokens):
            # make sure that special tokens are not decoded using sentencepiece model
            if token in self.all_special_tokens:
                if not prev_is_special and i != 0 and self.legacy:
                    out_string += " "
                out_string += self.sp_model.decode(current_sub_tokens) + token
                prev_is_special = True
                current_sub_tokens = []
            else:
                current_sub_tokens.append(token)
                prev_is_special = False
        out_string += self.sp_model.decode(current_sub_tokens)
        return out_string

    def save_vocabulary(self, save_directory, filename_prefix: Optional[str] = None) -> Tuple[str]:
        """
        Save the vocabulary and special tokens file to a directory.

        Args:
            save_directory (`str`):
                The directory in which to save the vocabulary.

        Returns:
            `Tuple(str)`: Paths to the files saved.
        """
        if not os.path.isdir(save_directory):
            logger.error(f"Vocabulary path ({save_directory}) should be a directory")
            return
        out_vocab_file = os.path.join(
            save_directory, (filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["vocab_file"]
        )

        if os.path.abspath(self.vocab_file) != os.path.abspath(out_vocab_file) and os.path.isfile(self.vocab_file):
            copyfile(self.vocab_file, out_vocab_file)
        elif not os.path.isfile(self.vocab_file):
            with open(out_vocab_file, "wb") as fi:
                content_spiece_model = self.sp_model.serialized_model_proto()
                fi.write(content_spiece_model)

        return (out_vocab_file,)

    def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):
        bos_token_id = [self.bos_token_id] if self.add_bos_token else []
        eos_token_id = [self.eos_token_id] if self.add_eos_token else []

        output = bos_token_id + token_ids_0 + eos_token_id

        if token_ids_1 is not None:
            output = output + bos_token_id + token_ids_1 + eos_token_id

        return output

    def get_special_tokens_mask(
        self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None, already_has_special_tokens: bool = False
    ) -> List[int]:
        """
        Retrieve sequence ids from a token list that has no special tokens added. This method is called when adding
        special tokens using the tokenizer `prepare_for_model` method.

        Args:
            token_ids_0 (`List[int]`):
                List of IDs.
            token_ids_1 (`List[int]`, *optional*):
                Optional second list of IDs for sequence pairs.
            already_has_special_tokens (`bool`, *optional*, defaults to `False`):
                Whether or not the token list is already formatted with special tokens for the model.

        Returns:
            `List[int]`: A list of integers in the range [0, 1]: 1 for a special token, 0 for a sequence token.
        """
        if already_has_special_tokens:
            return super().get_special_tokens_mask(
                token_ids_0=token_ids_0, token_ids_1=token_ids_1, already_has_special_tokens=True
            )

        bos_token_id = [1] if self.add_bos_token else []
        eos_token_id = [1] if self.add_eos_token else []

        if token_ids_1 is None:
            return bos_token_id + ([0] * len(token_ids_0)) + eos_token_id
        return (
            bos_token_id
            + ([0] * len(token_ids_0))
            + eos_token_id
            + bos_token_id
            + ([0] * len(token_ids_1))
            + eos_token_id
        )

    def create_token_type_ids_from_sequences(
        self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
    ) -> List[int]:
        """
        Creates a mask from the two sequences passed to be used in a sequence-pair classification task. An ALBERT
        sequence pair mask has the following format:

        ```
        0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
        | first sequence    | second sequence |
        ```

        if token_ids_1 is None, only returns the first portion of the mask (0s).

        Args:
            token_ids_0 (`List[int]`):
                List of ids.
            token_ids_1 (`List[int]`, *optional*):
                Optional second list of IDs for sequence pairs.

        Returns:
            `List[int]`: List of [token type IDs](../glossary#token-type-ids) according to the given sequence(s).
        """
        bos_token_id = [self.bos_token_id] if self.add_bos_token else []
        eos_token_id = [self.eos_token_id] if self.add_eos_token else []

        output = [0] * len(bos_token_id + token_ids_0 + eos_token_id)

        if token_ids_1 is not None:
            output += [1] * len(bos_token_id + token_ids_1 + eos_token_id)

        return output

    @property
    def default_chat_template(self):
        """
        LLaMA uses [INST] and [/INST] to indicate user messages, and <<SYS>> and <</SYS>> to indicate system messages.
        Assistant messages do not have special tokens, because LLaMA chat models are generally trained with strict
        user/assistant/user/assistant message ordering, and so assistant messages can be identified from the ordering
        rather than needing special tokens. The system message is partly 'embedded' in the first user message, which
        results in an unusual token ordering when it is present. This template should definitely be changed if you wish
        to fine-tune a model with more flexible role ordering!

        The output should look something like:

        <bos>[INST] B_SYS SystemPrompt E_SYS Prompt [/INST] Answer <eos> <bos>[INST] Prompt [/INST] Answer <eos>
        <bos>[INST] Prompt [/INST]
        """

        template = (
            "{% if messages[0]['role'] == 'system' %}"
            "{% set loop_messages = messages[1:] %}"  # Extract system message if it's present
            "{% set system_message = messages[0]['content'] %}"
            "{% elif USE_DEFAULT_PROMPT == true and not '<<SYS>>' in messages[0]['content'] %}"
            "{% set loop_messages = messages %}"  # Or use the default system message if the flag is set
            "{% set system_message = 'DEFAULT_SYSTEM_MESSAGE' %}"
            "{% else %}"
            "{% set loop_messages = messages %}"
            "{% set system_message = false %}"
            "{% endif %}"
            "{% for message in loop_messages %}"  # Loop over all non-system messages
            "{% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}"
            "{{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}"
            "{% endif %}"
            "{% if loop.index0 == 0 and system_message != false %}"  # Embed system message in first message
            "{% set content = '<<SYS>>\\n' + system_message + '\\n<</SYS>>\\n\\n' + message['content'] %}"
            "{% else %}"
            "{% set content = message['content'] %}"
            "{% endif %}"
            "{% if message['role'] == 'user' %}"  # After all of that, handle messages/roles in a fairly normal way
            "{{ bos_token + '[INST] ' + content.strip() + ' [/INST]' }}"
            "{% elif message['role'] == 'system' %}"
            "{{ '<<SYS>>\\n' + content.strip() + '\\n<</SYS>>\\n\\n' }}"
            "{% elif message['role'] == 'assistant' %}"
            "{{ ' '  + content.strip() + ' ' + eos_token }}"
            "{% endif %}"
            "{% endfor %}"
        )
        template = template.replace("USE_DEFAULT_PROMPT", "true" if self.use_default_system_prompt else "false")
        default_message = DEFAULT_SYSTEM_PROMPT.replace("\n", "\\n").replace("'", "\\'")
        template = template.replace("DEFAULT_SYSTEM_MESSAGE", default_message)

        return template

Answer: os.environ["CUDA_VISIBLE_DEVICES"] = CUDA_VISIBLE_DEVICES

<think>
After the series of imports, the script typically configures the CUDA devices using the imported CUDA_VISIBLE_DEVICES variable. The next logical line sets the environment variable so that PyTorch respects the desired GPU selection.
</think>
os.environ["CUDA_VISIBLE_DEVICES"] = CUDA_VISIBLE_DEVICES


Input:
import com.fasterxml.jackson.databind.JsonNode;
import io.fiber.net.common.async.Maybe;
import io.fiber.net.script.ast.Block;
import io.fiber.net.script.parse.CompiledScript;
import io.fiber.net.script.parse.ParseException;
import io.fiber.net.script.parse.Parser;
import io.fiber.net.script.std.StdLibrary;

Context:
fiber-gateway-script/src/main/java/io/fiber/net/script/Script.java
package io.fiber.net.script;

public interface Script {

    static Script compile(String script) throws ParseException {
        return compile(script, StdLibrary.getDefInstance());
    }

    static Script compileWithoutAssign(String script) throws ParseException {

fiber-gateway-script/src/main/java/io/fiber/net/script/parse/ParseException.java
public class ParseException extends RuntimeException {
    protected String expressionString;
    protected int position; // -1 if not known - but should be known in all reasonable cases

    /**
     * Creates a new expression exception.
     *
     * @param expressionString the expression string
     * @param message          a descriptive message
     */
    public ParseException(String expressionString, String message) {
        super(message);
        this.position = -1;
        this.expressionString = expressionString;
    }

    /**
     * Creates a new expression exception.
     *
     * @param expressionString the expression string
     * @param position         the position in the expression string where the problem occurred
     * @param message          a descriptive message
     */
    public ParseException(String expressionString, int position, String message) {
        super(message);
        this.position = position;
        this.expressionString = expressionString;
    }

    /**
     * Creates a new expression exception.
     *
     * @param position the position in the expression string where the problem occurred
     * @param message  a descriptive message
     */
    public ParseException(int position, String message) {
        super(message);
        this.position = position;
    }

    /**
     * Creates a new expression exception.
     *
     * @param position the position in the expression string where the problem occurred
     * @param message  a descriptive message
     * @param cause    the underlying cause of this exception
     */
    public ParseException(int position, String message, Throwable cause) {
        super(message, cause);
        this.position = position;
    }

    public ParseException(int position, SpelMessage spelMessage, Object... addition) {
        super(spelMessage.formatMessage(position, addition));
        this.position = position;
    }

    public ParseException(Throwable cause, int position, SpelMessage spelMessage, Object... addition) {
        super(spelMessage.formatMessage(position, addition), cause);
        this.position = position;
    }

    /**
     * Creates a new expression exception.
     */
    public ParseException(String expressionString, int position, SpelMessage spelMessage, Object... addition) {
        super(toDetailedString(expressionString, position, spelMessage, addition));
        this.expressionString = expressionString;
        this.position = position;
    }

    public ParseException(String message) {
        super(message);
    }

    public ParseException(String message, Throwable cause) {
        super(message, cause);
    }

    private static String toDetailedString(String expressionString, int position, SpelMessage spelMessage, Object... addition) {
        StringBuilder output = new StringBuilder();
        if (expressionString != null) {
            output.append("Expression '");
            output.append(expressionString);
            output.append("'");
            if (position != -1) {
                output.append(" @ ");
                output.append(position);
            }
            output.append(": ");
        }
        output.append(spelMessage.formatMessagePos(position, addition));
        return output.toString();
    }

    public final String getExpressionString() {
        return this.expressionString;
    }

    public final int getPosition() {
        return position;
    }
}

fiber-gateway-script/src/main/java/io/fiber/net/script/std/StdLibrary.java
public class StdLibrary implements Library {
    private static final Map<String, Library.Function> DEF_FUNC_MAP = new HashMap<>();

    static {
        DEF_FUNC_MAP.put("random", new RandomFunc());
        DEF_FUNC_MAP.put("now", new NowFunc());
        DEF_FUNC_MAP.put("canary", new CanaryFunc());
        DEF_FUNC_MAP.put("crc32", new Crc32Func());
        DEF_FUNC_MAP.put("includes", new IncludesFunc());
        DEF_FUNC_MAP.putAll(ArrayFuncs.FUNC);
        DEF_FUNC_MAP.putAll(ObjectsFuncs.FUNC);
        DEF_FUNC_MAP.putAll(StringsFuncs.FUNC);
        DEF_FUNC_MAP.putAll(MathFuncs.FUNC);
        DEF_FUNC_MAP.putAll(BinaryFunc.FUNC);
    }

    protected static Map<String, Library.Function> getDefFuncMap() {
        return DEF_FUNC_MAP;
    }

    private final static StdLibrary DEF_INSTANCE = new StdLibrary(DEF_FUNC_MAP);

    public static StdLibrary getDefInstance() {
        return DEF_INSTANCE;
    }

    protected final Map<String, Library.Function> functionMap;

    public StdLibrary(Map<String, Library.Function> functionMap) {
        this.functionMap = functionMap;
    }

    @Override
    public Library.Function findFunc(String name) {
        return functionMap.get(name);
    }

    @Override
    public Constant findConstant(String namespace, String key) {
        return null;
    }

    @Override
    public DirectiveDef findDirectiveDef(String type, String name, List<Literal> literals) {
        return null;
    }
}

fiber-gateway-common/src/main/java/io/fiber/net/common/async/Maybe.java
public interface Maybe<T> {

    interface Emitter<T> {
        void onSuccess(T t);

        void onError(Throwable t);

        void onComplete();

        boolean isDisposed();
    }

    interface Observer<T> {
        void onSubscribe(Disposable d);

        void onSuccess(T t);

        void onError(Throwable e);

        void onComplete();

        Scheduler scheduler();
    }

    interface OnSubscribe<T> {

        void subscribe(Emitter<T> emitter) throws Throwable;
    }

    void subscribe(Observer<? super T> observer);

    default Maybe<T> onNotify(BiConsumer<? super T, Throwable> onNotify) {
        return new OnNotifyWrapMaybe<>(onNotify, this);
    }

    default <U> Maybe<U> map(Function<? super T, ? extends U> function) {
        return new MappedMaybe<>(function, this);
    }

    default Disposable subscribe(java.util.function.BiConsumer<T, Throwable> consumer) {
        FuncMaybeObserver<T> tFuncMaybeObserver = new FuncMaybeObserver<>(consumer);
        subscribe(tFuncMaybeObserver);
        return tFuncMaybeObserver.getDisposable();
    }

    static <T> Maybe<T> create(OnSubscribe<T> onSubscribe) {
        return new MaybeCreate<>(onSubscribe);
    }

    @SuppressWarnings("unchecked")
    static <T> Maybe<T> ofErr(Throwable err) {
        return (Maybe<T>) new ErrMaybe(err);
    }
}

fiber-gateway-script/src/main/java/io/fiber/net/script/parse/Parser.java
public class Parser {
    static final String[] EMPTY_STR_ARR = Constant.EMPTY_STR_ARR;
    static final ExpressionNode[] EMPTY_NODE_ARR = new ExpressionNode[0];
    private static final Pattern VALID_QUALIFIED_ID_PATTERN = Pattern.compile("[\\p{L}\\p{N}_$]+");

    private final Library library;
    private boolean hasAssign = true;

    // The token stream constructed from that expression string
    private List<Token> tokenStream;

    // length of a populated token stream
    private int tokenStreamLength;

    // Current location in the token stream when processing tokens
    private int tokenStreamPointer;

    private final Map<String, DirectiveStatement> directiveMap = new HashMap<>();

    private static final Keyword[] KW_VALUES = Keyword.values();

    private static Keyword tryMatchKeyWords(String name) {
        for (Keyword kw : KW_VALUES) {
            if (kw.idt.equals(name)) {
                return kw;
            }
        }
        return null;
    }

    enum Keyword {
        LET, IF, ELSE, FOR, OF, CONTINUE, BREAK, RETURN, DIRECTIVE, FROM, TRY, CATCH, THROW;

        final String idt;

        Keyword() {
            idt = name().toLowerCase();
        }

        public String getIdt() {
            return idt;
        }

    }

    private Parser(Library library) {
        this.library = library;
    }

    public Parser(Library library, boolean hasAssign) {
        this.library = library;
        this.hasAssign = hasAssign;
    }

    public Block parseScript(String script) throws ParseException {
        Tokenizer tokenizer = new Tokenizer(script);
        tokenizer.process();
        return parseScriptFromTokens(tokenizer.getTokens(), script);
    }

    public Block parseScriptFromTokens(List<Token> tokens, String originScript) {
        this.tokenStream = tokens;
        this.tokenStreamLength = tokens.size();
        this.tokenStreamPointer = 0;
        Block block;
        try {
            block = eatBlock(false);
        } catch (ParseException e) {
            e.expressionString = originScript;
            throw e;
        }
        if (moreTokens()) {
            throw new ParseException(originScript, peekToken().startpos, SpelMessage.MORE_INPUT, toString(nextToken()));
        }
        return block;
    }

    public ExpressionNode parseExpression(String exp) throws ParseException {
        Tokenizer tokenizer = new Tokenizer(exp);
        tokenizer.process();
        return parseExpression(tokenizer.getTokens(), exp);
    }

    public ExpressionNode parseExpression(List<Token> tokens, String originExp) throws ParseException {
        this.tokenStream = tokens;
        this.tokenStreamLength = tokens.size();
        this.tokenStreamPointer = 0;
        ExpressionNode expressionNode;
        try {
            expressionNode = eatExpression();
        } catch (ParseException e) {
            e.expressionString = originExp;
            throw e;
        }
        if (moreTokens()) {
            throw new ParseException(originExp, peekToken().startpos, SpelMessage.MORE_INPUT, toString(nextToken()));
        }
        return expressionNode;
    }

    private Statement eatStatement() throws ParseException {
        Statement statement = tryEatIfStatement();
        if (statement != null) {
            return statement;
        }
        statement = tryEatForeachStatement();
        if (statement != null) {
            return statement;
        }

        statement = tryEatBreakStatement();
        if (statement != null) {
            return statement;
        }
        statement = tryEatContinueStatement();
        if (statement != null) {
            return statement;
        }
        statement = tryEatReturnStatement();
        if (statement != null) {
            return statement;
        }

        statement = tryEatThrowStatement();
        if (statement != null) {
            return statement;
        }

        statement = tryEatTryCatchStatement();
        if (statement != null) {
            return statement;
        }

        statement = tryEatVariableDeclareStatement();
        if (statement != null) {
            return statement;
        }

        statement = tryEatDirectiveStatement();
        if (statement != null) {
            return statement;
        }

        ExpressionNode eatExpression = eatExpression();
        peekToken(TokenKind.SEMICOLON, true);
        return new ExpressionStatement(eatExpression);
    }

    private Statement tryEatThrowStatement() {
        if (!moreTokens() || !peekIdentifierToken(Keyword.THROW.idt)) {
            return null;
        }
        Token token = nextToken();

        ExpressionNode node = eatExpression();
        peekToken(TokenKind.SEMICOLON, true);
        return new ThrowStatement(toPos(token.startpos, node.getEndPosition()), node);
    }

    private Statement tryEatTryCatchStatement() {
        if (!moreTokens() || !peekIdentifierToken(Keyword.TRY.idt)) {
            return null;
        }

        Token tryTk = eatKeyWord(Keyword.TRY);
        Block tryBk = eatBlock(true);
        eatKeyWord(Keyword.CATCH);
        eatToken(TokenKind.LPAREN);
        Identifier identifier = eatIdentifier();
        eatToken(TokenKind.RPAREN);
        Block catchBk = eatBlock(true);
        return new TryCatchStatement(toPos(tryTk.startpos, catchBk.getEndPosition()), identifier, tryBk, catchBk);
    }

    private ContinueStatement tryEatContinueStatement() {
        if (!moreTokens() || !peekIdentifierToken(Keyword.CONTINUE.idt)) {
            return null;
        }

        Token token = nextToken();
        peekToken(TokenKind.SEMICOLON, true);
        return new ContinueStatement(toPos(token));
    }

    private BreakStatement tryEatBreakStatement() {
        if (!moreTokens() || !peekIdentifierToken(Keyword.BREAK.idt)) {
            return null;
        }

        Token token = nextToken();
        peekToken(TokenKind.SEMICOLON, true);
        return new BreakStatement(toPos(token));
    }

    private ReturnStatement tryEatReturnStatement() {
        if (!moreTokens() || !peekIdentifierToken(Keyword.RETURN.idt)) {
            return null;
        }
        Token token = nextToken();

        if (peekToken(TokenKind.SEMICOLON, true)) {
            return new ReturnStatement(toPos(token), null);
        }

        ExpressionNode node = eatExpression();
        peekToken(TokenKind.SEMICOLON, true);
        return new ReturnStatement(toPos(token.startpos, node.getEndPosition()), node);
    }

    private DirectiveStatement tryEatDirectiveStatement() {
        if (!moreTokens() || !peekIdentifierToken(Keyword.DIRECTIVE.idt)) {
            return null;
        }
        int startpos = nextToken().startpos;

        Identifier name = eatIdentifier();

        if (!peekIdentifierToken(Keyword.FROM.idt)) {
            raiseInternalException(name.getEndPosition() + 1, SpelMessage.KEYWORD_DIRECTIVE_NOT_EXPECTED, "");
        }
        nextToken();

        Identifier type = eatIdentifier();

        List<Literal> literals = new ArrayList<>();
        for (; ; ) {
            Literal literal = maybeEatLiteral();
            if (literal == null) {
                break;
            }
            literals.add(literal);
        }
        if (directiveMap.containsKey(name.getName())) {
            raiseInternalException(startpos, SpelMessage.DIRECTIVE_EXISTS, name.getName(), type.getName());
            return null;
        }

        int endpos = eatToken(TokenKind.SEMICOLON).endpos;

        Library.DirectiveDef directiveDef = library.findDirectiveDef(type.getName(), name.getName(), literals);
        if (directiveDef == null) {
            raiseInternalException(startpos, SpelMessage.DIRECTIVE_NOT_FOUND, name.getName(), type.getName());
        }
        return new DirectiveStatement(toPos(startpos, endpos), type, name, directiveDef);
    }

    private VariableDeclareStatement tryEatVariableDeclareStatement() throws ParseException {
        if (!moreTokens() || !peekIdentifierToken(Keyword.LET.idt)) {
            return null;
        }

        Token let = eatKeyWord(Keyword.LET);
        Identifier identifier = eatIdentifier();
        ExpressionNode initializer = null;
        if (peekToken(TokenKind.ASSIGN, true)) {
            initializer = eatExpression();
        }
        Token token = eatToken(TokenKind.SEMICOLON);
        return new VariableDeclareStatement(toPos(let.startpos, token.endpos), identifier, initializer);
    }

    private ForeachStatement tryEatForeachStatement() throws ParseException {
        if (!peekIdentifierToken(Keyword.FOR.idt)) {
            return null;
        }
        Token forKW = eatKeyWord(Keyword.FOR);
        eatToken(TokenKind.LPAREN);
        eatKeyWord(Keyword.LET);

        Identifier key = eatIdentifier();
        eatToken(TokenKind.COMMA);
        Identifier val = eatIdentifier();

        eatKeyWord(Keyword.OF);

        ExpressionNode collection = eatExpression();
        eatToken(TokenKind.RPAREN);
        Block block = eatBlock(true);

        return new ForeachStatement(toPos(forKW.startpos, block.getEndPosition()), key, val, collection, block);
    }

    private IfStatement tryEatIfStatement() throws ParseException {
        if (!peekIdentifierToken(Keyword.IF.idt)) {
            return null;
        }

        Token ifKW = eatKeyWord(Keyword.IF);
        eatToken(TokenKind.LPAREN);
        ExpressionNode prediction = eatExpression();
        eatToken(TokenKind.RPAREN);
        Block trueBlock = eatBlock(true);
        int endPos = trueBlock.getEndPosition();
        Statement elseBlock = null;

        if (peekIdentifierToken(Keyword.ELSE.idt)) {
            eatToken(TokenKind.IDENTIFIER);
            if (peekIdentifierToken(Keyword.IF.idt)) { // else if
                //
                elseBlock = tryEatIfStatement();
            } else {
                elseBlock = eatBlock(true);
            }
            assert elseBlock != null;
            endPos = elseBlock.getEndPosition();
        }

        return new IfStatement(toPos(ifKW.startpos, endPos), prediction, trueBlock, elseBlock);
    }

    private Block eatBlock(boolean mustCurly) {

        Token s = mustCurly ? eatToken(TokenKind.LCURLY) : null;
        List<Statement> statements = new ArrayList<>();
        while (moreTokens()) {
            if (s != null && peekToken(TokenKind.RCURLY)) {
                break;
            }
            if (peekToken(TokenKind.SEMICOLON, true)) {
                continue;
            }
            Statement e = eatStatement();
            if (e instanceof DirectiveStatement) {
                DirectiveStatement directiveStatement = (DirectiveStatement) e;
                directiveMap.put(directiveStatement.getName().getName(), directiveStatement);
            } else {
                statements.add(e);
            }
        }
        Token e = s != null ? eatToken(TokenKind.RCURLY) : null;
        int pos;
        if (e != null) {
            pos = toPos(s.startpos, e.endpos);
        } else if (!statements.isEmpty()) {
            pos = toPos(statements.get(0).getStartPosition(), statements.get(statements.size() - 1).getEndPosition());
        } else {
            raiseInternalException(0, SpelMessage.MORE_INPUT);
            // not hit
            return null;
        }

        return new Block(pos, statements);
    }

    private Identifier eatIdentifier() {
        Token token = eatToken(TokenKind.IDENTIFIER);
        if (tryMatchKeyWords(token.data) != null) {
            raiseInternalException(token.startpos, SpelMessage.KEYWORD_DIRECTIVE_NOT_EXPECTED, token.data);
        }
        return new Identifier(toPos(token), token.data);
    }

    //	expression
    //    : logicalOrExpression
    //      ( (ASSIGN^ logicalOrExpression)
    //	    | (DEFAULT^ logicalOrExpression)
    //	    | (QMARK^ expression COLON! expression)
    //      | (ELVIS^ expression))?;
    private ExpressionNode eatExpression() {
        ExpressionNode expr = eatLogicalOrExpression();
        if (moreTokens()) {
            Token t = peekToken();
            if (hasAssign && t.kind == TokenKind.ASSIGN) { // a=b
                nextToken();
                ExpressionNode assignedValue = eatLogicalOrExpression();
                if (expr instanceof MaybeLValue) {
                    MaybeLValue lValue = (MaybeLValue) expr;
                    lValue.markLValue();
                    return new Assign(toPos(t), lValue, assignedValue);
                } else {
                    throw new ParseException("需要 LValue:" + expr.getPos());
                }
            }

            if (t.kind == TokenKind.QMARK) { // a?b:c
                if (expr == null) {
                    expr = Literal.ofNull(toPos(t.startpos - 1, t.endpos - 1));
                }
                nextToken();
                ExpressionNode ifTrueExprValue = eatExpression();
                eatToken(TokenKind.COLON);
                ExpressionNode ifFalseExprValue = eatExpression();
                return new Ternary(toPos(t), expr, ifTrueExprValue, ifFalseExprValue);
            }
        }
        return expr;
    }

    //logicalOrExpression : logicalAndExpression (OR^ logicalAndExpression)*;
    private ExpressionNode eatLogicalOrExpression() {
        ExpressionNode expr = eatLogicalAndExpression();
        while (peekToken(TokenKind.SYMBOLIC_OR)) {
            Token t = nextToken(); //consume OR
            ExpressionNode rhExpr = eatLogicalAndExpression();
            checkOperands(t, expr, rhExpr);
            expr = new LogicRelationalExpression(toPos(t), expr, Operator.OR, rhExpr);
        }
        return expr;
    }

    // logicalAndExpression : relationalExpression (AND^ relationalExpression)*;
    private ExpressionNode eatLogicalAndExpression() {
        ExpressionNode expr = eatRelationalExpression();
        while (peekToken(TokenKind.SYMBOLIC_AND)) {
            Token t = nextToken();// consume 'AND'
            ExpressionNode rhExpr = eatRelationalExpression();
            checkOperands(t, expr, rhExpr);
            expr = new LogicRelationalExpression(toPos(t), expr, Operator.AND, rhExpr);
        }
        return expr;
    }

    // relationalExpression : sumExpression (relationalOperator^ sumExpression)?;
    private ExpressionNode eatRelationalExpression() {
        ExpressionNode expr = eatSumExpression();
        Token relationalOperatorToken = maybeEatRelationalOperator();
        if (relationalOperatorToken != null) {
            Token t = nextToken(); //consume relational operator token
            ExpressionNode rhExpr = eatSumExpression();
            checkOperands(t, expr, rhExpr);
            TokenKind tk = relationalOperatorToken.kind;

            if (relationalOperatorToken.isNumericRelationalOperator()) {
                return new BinaryOperator(toPos(t), expr, Operator.fromToken(t.kind), rhExpr);
            }

            if (tk == TokenKind.TILDE) {
                return new BinaryOperator(toPos(t), expr, Operator.MATCH, rhExpr);
            }
            Assert.isTrue(tk == TokenKind.IDENTIFIER);
            if (relationalOperatorToken.data.equals(Operator.IN.getPayload())) {
                return new BinaryOperator(toPos(t), expr, Operator.IN, rhExpr);
            }
        }
        return expr;
    }

    //sumExpression: productExpression ( (PLUS^ | MINUS^) productExpression)*;
    private ExpressionNode eatSumExpression() {
        ExpressionNode expr = eatProductExpression();
        while (peekToken(TokenKind.PLUS, TokenKind.MINUS)) {
            Token t = nextToken();//consume PLUS or MINUS
            ExpressionNode rhExpr = eatProductExpression();
            checkRightOperand(t, rhExpr);
            if (t.kind == TokenKind.PLUS || t.kind == TokenKind.MINUS) {
                expr = new BinaryOperator(toPos(t), expr, Operator.fromToken(t.kind), rhExpr);
            }
        }
        return expr;
    }

    // productExpression: powerExpr ((STAR^ | DIV^| MOD^) powerExpr)* ;
    private ExpressionNode eatProductExpression() {
        ExpressionNode expr = eatPowerIncDecExpression();
        while (peekToken(TokenKind.STAR, TokenKind.DIV, TokenKind.MOD)) {
            Token t = nextToken(); // consume STAR/DIV/MOD
            ExpressionNode rhExpr = eatPowerIncDecExpression();
            checkOperands(t, expr, rhExpr);
            expr = new BinaryOperator(toPos(t), expr, Operator.fromToken(t.kind), rhExpr);
        }
        return expr;
    }

    // powerExpr  : unaryExpression (POWER^ unaryExpression)? (INC || DEC) ;
    private ExpressionNode eatPowerIncDecExpression() {
        return eatUnaryExpression();
    }

    // unaryExpression: (PLUS^ | MINUS^ | BANG^ | INC^ | DEC^) unaryExpression | primaryExpression ;
    private ExpressionNode eatUnaryExpression() {
        if (peekToken(TokenKind.PLUS, TokenKind.MINUS, TokenKind.NOT)) {
            Token t = nextToken();
            ExpressionNode expr = eatUnaryExpression();
            return new UnaryOperator(toPos(t), Operator.fromToken(t.kind), expr);
        }

        if (peekIdentifierToken("typeof")) {
            Token t = nextToken();
            ExpressionNode expr = eatUnaryExpression();
            return new UnaryOperator(toPos(t), Operator.TYPEOF, expr);
        }
        return eatPrimaryExpression();
    }

    private FunctionCall maybeEatFuncCall(VariableReference prefix) {
        int tokenIdx = this.tokenStreamPointer;
        int dotSize = 0;
        StringBuilder sb = new StringBuilder(prefix.getName());
        while (peekToken(TokenKind.DOT, true)) {
            if (peekToken(TokenKind.IDENTIFIER)) {
                Token token = nextToken();
                sb.append('.').append(token.data);
                dotSize++;
                if (peekToken(TokenKind.LPAREN)) {
                    ExpressionNode[] args = maybeEatMethodArgs();
                    if (args != null) {
                        String funcName = sb.toString();
                        Library.Function func = library.findFunc(funcName);

                        if (func == null && dotSize == 1 && directiveMap.containsKey(prefix.getName())) {
                            DirectiveStatement directiveStatement = directiveMap.get(prefix.getName());
                            func = directiveStatement.getDirectiveDef().findFunc(prefix.getName(), token.data);
                        }

                        if (func == null) {
                            raiseInternalException(prefix.getStartPosition(), SpelMessage.FUNCTION_NOT_DEFINED, funcName);
                        }
                        return new FunctionCall(func, funcName, toPos(prefix.getStartPosition(), args.length > 0 ? args[args.length - 1].getEndPosition() + 1 : prefix.getStartPosition() + funcName.length() + 2), args);
                    }
                }
            } else {
                break;
            }
        }

        this.tokenStreamPointer = tokenIdx;
        return null;
    }

    // primaryExpression : startNode (node)? -> ^(EXPRESSION startNode (node)?);
    private ExpressionNode eatPrimaryExpression() {
        ExpressionNode start = eatStartNode(); // always a start node

        if ((start instanceof VariableReference) && !((VariableReference) start).isRoot()) {
            FunctionCall functionCall = maybeEatFuncCall((VariableReference) start);
            if (functionCall != null) {
                start = functionCall;
            }
        }

        ExpressionNode current;
        while ((current = maybeEatNode(start)) != null) {
            start = current;
        }
        return start;
    }

    // node : ((DOT dottedNode) | (SAFE_NAVI dottedNode) | nonDottedNode)+;
    private ExpressionNode maybeEatNode(ExpressionNode parent) {
        ExpressionNode expr;
        if (peekToken(TokenKind.DOT)) {
            expr = eatDottedNode(parent);
        } else {
            expr = maybeEatNonDottedNode(parent);
        }

        return expr;
    }

    // nonDottedNode: indexer;
    private ExpressionNode maybeEatNonDottedNode(ExpressionNode parent) {
        if (peekToken(TokenKind.LSQUARE)) {
            return maybeEatIndexer(parent);
        }
        return null;
    }

    private ConstantVal maybeConstant(Token prefix) {
        int tokenIdx = this.tokenStreamPointer;
        if (!peekToken(TokenKind.DOT, true)) {
            return null;
        }
        Token token = peekToken();
        if (token == null || token.kind != TokenKind.IDENTIFIER) {
            this.tokenStreamPointer = tokenIdx;
            return null;
        }

        String key = token.data;
        if ("$".equals(prefix.data)) {
            library.markRootProp(key);
            this.tokenStreamPointer = tokenIdx;
            return null;
        }
        nextToken();
        Library.Constant constant = library.findConstant(prefix.data, key);
        if (constant == null) {
            raiseInternalException(prefix.startpos, SpelMessage.CONSTANT_NOT_FIND, prefix.data, key);
            return null;
        }
        return new ConstantVal(toPos(prefix.startpos, token.endpos), prefix.data + "." + key, constant);
    }

    //dottedNode
    // : ((methodOrProperty
    //	  | functionOrVar
    //    | projection
    //    | selection
    //    | firstSelection
    //    | lastSelection
    //    ))
    //	;
    private ExpressionNode eatDottedNode(ExpressionNode parent) {
        ExpressionNode result;
        Token t = nextToken();// it was a '.' or a '?.'
        if ((result = maybeEatProperty(parent)) != null) {
            return result;
        }
        if (peekToken() == null) {
            // unexpectedly ran out of data
            raiseInternalException(t.startpos, SpelMessage.OOD);
        } else {
            raiseInternalException(t.startpos, SpelMessage.UNEXPECTED_DATA_AFTER_DOT, toString(peekToken()));
        }
        return null;
    }

    // functionOrVar
    // : (POUND ID LPAREN) => function
    // | var
    //
    // function : POUND id=ID methodArgs -> ^(FUNCTIONREF[$id] methodArgs);
    // var : POUND id=ID -> ^(VARIABLEREF[$id]);
    private ExpressionNode maybeEatFunctionOrVar() {
        Token t = eatToken(TokenKind.IDENTIFIER);
        ExpressionNode[] args = maybeEatMethodArgs();
        if (args != null) {
            Library.Function func = library.findFunc(t.data);
            if (func == null) {
                raiseInternalException(t.startpos, SpelMessage.FUNCTION_NOT_DEFINED, t.data);
            }
            return new FunctionCall(func, t.data, toPos(t.startpos, t.endpos), args);

        }
        if (t.data.charAt(0) == '$') {
            ConstantVal constantVal = maybeConstant(t);
            if (constantVal != null) {
                return constantVal;
            }
        }
        return new VariableReference(t.data, toPos(t.startpos, t.endpos));
    }

    // methodArgs : LPAREN! (argument (COMMA! argument)* (COMMA!)?)? RPAREN!;
    private ExpressionNode[] maybeEatMethodArgs() {
        if (!peekToken(TokenKind.LPAREN)) {
            return null;
        }
        List<ExpressionNode> args = new ArrayList<>();
        consumeArguments(args);
        eatToken(TokenKind.RPAREN);
        return args.toArray(new ExpressionNode[args.size()]);
    }

    /**
     * Used for consuming arguments for either a method or a constructor call
     */
    private void consumeArguments(List<ExpressionNode> accumulatedArguments) {
        int pos = peekToken().startpos;
        Token next = null;
        do {
            nextToken();// consume ( (first time through) or comma (subsequent times)
            Token t = peekToken();
            if (t == null) {
                raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS);
            }
            if (t.kind != TokenKind.RPAREN) {
                ExpressionNode e;
                if (t.kind == TokenKind.EXPAND) {
                    nextToken();
                    e = new ExpandArrArg(toPos(t), eatExpression());
                } else {
                    e = eatExpression();
                }
                accumulatedArguments.add(e);
            }
            next = peekToken();
        } while (next != null && next.kind == TokenKind.COMMA);

        if (next == null) {
            raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS);
        }
    }

    //startNode
    // : parenExpr | literal
    //	    | type
    //	    | methodOrProperty
    //	    | functionOrVar
    //	    | projection
    //	    | selection
    //	    | firstSelection
    //	    | lastSelection
    //	    | indexer
    //	    | constructor
    private ExpressionNode eatStartNode() {
        ExpressionNode node;
        if ((node = maybeEatLiteral()) != null) {
            return node;
        } else if ((node = maybeEatInlineList()) != null || (node = maybeEatInlineObject()) != null) {
            return node;
        } else if ((node = maybeEatParenExpression()) != null || (node = maybeEatNullReference()) != null) {
            return node;
        }
        return maybeEatFunctionOrVar();
    }

    private InlineObject maybeEatInlineObject() {
        Token t = peekToken();
        if (!peekToken(TokenKind.LCURLY, true)) {
            return null;
        }
        InlineObject expr;
        Token closingCurly = peekToken();
        if (peekToken(TokenKind.RCURLY, true)) {
            // empty object '{}'
            expr = new InlineObject(toPos(t.startpos, closingCurly.endpos), EMPTY_STR_ARR, EMPTY_NODE_ARR);
        } else {
            Map<Object, ExpressionNode> map = new LinkedHashMap<>();
            do {
                Token k = peekToken();
                if (k == null) {
                    raiseInternalException(t.startpos, SpelMessage.MISSING_INLINE_OBJECT_ELEMENT);
                }
                if (k.kind == TokenKind.EXPAND) {
                    nextToken();
                    ExpandArrArg expand = new ExpandArrArg(toPos(t), eatExpression());
                    map.put(InlineObject.expandKey(), expand);
                } else {
                    String key = null;
                    if (k.kind == TokenKind.LITERAL_STRING) {
                        nextToken();
                        try {
                            JsonNode node = JsonUtil.MAPPER.readTree(k.data);
                            if (!node.isTextual()) {
                                raiseInternalException(t.startpos, SpelMessage.NOT_SUPPORT_INLINE_OBJECT_KEY, k);
                            }
                            key = node.asText();
                        } catch (ParseException e) {
                            throw e;
                        } catch (Exception e) {
                            throw new ParseException(e.getMessage());
                        }
                    } else if (k.kind == TokenKind.IDENTIFIER) {
                        key = k.data;
                        nextToken();
                        if (peekToken(TokenKind.COMMA) || peekToken(TokenKind.RCURLY)) {
                            ExpressionNode old = map.put(key, new VariableReference(key, toPos(k)));
                            if (old != null) {
                                raiseInternalException(t.startpos, SpelMessage.INLINE_OBJECT_DUPLICATE_KEY, k);
                            }
                            continue;
                        }
                    } else if (k.kind == TokenKind.RCURLY) {
                        break;
                    } else {
                        raiseInternalException(t.startpos, SpelMessage.NOT_SUPPORT_INLINE_OBJECT_KEY, k);
                    }
                    eatToken(TokenKind.COLON);
                    ExpressionNode old = map.put(key, eatExpression());
                    if (old != null) {
                        raiseInternalException(t.startpos, SpelMessage.INLINE_OBJECT_DUPLICATE_KEY, k);
                    }
                }
            } while (peekToken(TokenKind.COMMA, true));
            closingCurly = eatToken(TokenKind.RCURLY);

            Object[] keys = new Object[map.size()];
            keys = map.keySet().toArray(keys);
            ExpressionNode[] values = new ExpressionNode[map.size()];
            values = map.values().toArray(values);
            expr = new InlineObject(toPos(t.startpos, closingCurly.endpos), keys, values);
        }
        return expr;
    }

    private Literal maybeEatNullReference() {
        if (peekToken(TokenKind.IDENTIFIER)) {
            Token nullToken = peekToken();
            if (!nullToken.stringValue().equals("null")) {
                return null;
            }
            nextToken();
            return Literal.ofNull(toPos(nullToken));
        }
        return null;
    }

    // list = LCURLY (element (COMMA element)*) RCURLY
    private InlineList maybeEatInlineList() {
        Token t = peekToken();
        if (!peekToken(TokenKind.LSQUARE, true)) {
            return null;
        }
        InlineList expr;
        Token closingCurly = peekToken();
        if (peekToken(TokenKind.RSQUARE, true)) {
            // empty list '[]'
            expr = new InlineList(toPos(t.startpos, closingCurly.endpos));
        } else {
            List<ExpressionNode> listElements = new ArrayList<>();
            do {
                ExpressionNode e;
                Token ct = peekToken();
                if (ct == null) {
                    // unexpectedly ran out of data
                    raiseInternalException(t.startpos, SpelMessage.OOD);
                }
                if (ct.kind == TokenKind.EXPAND) {
                    nextToken();
                    e = new ExpandArrArg(toPos(ct), eatExpression());
                } else {
                    e = eatExpression();
                }
                listElements.add(e);
            } while (peekToken(TokenKind.COMMA, true));

            closingCurly = eatToken(TokenKind.RSQUARE);
            expr = new InlineList(toPos(t.startpos, closingCurly.endpos), listElements.toArray(new ExpressionNode[listElements.size()]));
        }
        return expr;
    }

    private Indexer maybeEatIndexer(ExpressionNode parent) {
        Token t = peekToken();
        if (!peekToken(TokenKind.LSQUARE, true)) {
            return null;
        }
        ExpressionNode expr = eatExpression();
        eatToken(TokenKind.RSQUARE);
        return new Indexer(toPos(t), parent, expr);
    }

    private boolean isValidQualifiedId(Token node) {
        if (node == null || node.kind == TokenKind.LITERAL_STRING) {
            return false;
        }
        if (node.kind == TokenKind.DOT || node.kind == TokenKind.IDENTIFIER) {
            return true;
        }
        String value = node.stringValue();
        return StringUtils.hasLength(value) && VALID_QUALIFIED_ID_PATTERN.matcher(value).matches();
    }

    // This is complicated due to the support for dollars in identifiers.  Dollars are normally separate tokens but
    // there we want to combine a series of identifiers and dollars into a single identifier
    private PropertyReference maybeEatProperty(ExpressionNode parent) {
        if (peekToken(TokenKind.IDENTIFIER)) {
            Token methodOrPropertyName = nextToken();
            // property
            return new PropertyReference(methodOrPropertyName.data, toPos(methodOrPropertyName), parent);
        }
        return null;
    }

    //	literal
    //  : INTEGER_LITERAL
    //	| boolLiteral
    //	| STRING_LITERAL
    //  | HEXADECIMAL_INTEGER_LITERAL
    //  | REAL_LITERAL
    //	| DQ_STRING_LITERAL
    //	| NULL_LITERAL
    private Literal maybeEatLiteral() {
        Token t = peekToken();
        if (t == null) {
            return null;
        }
        Literal result;
        if (t.kind == TokenKind.LITERAL_INT) {
            result = (Literal.getIntLiteral(t.data, toPos(t), 10));
        } else if (t.kind == TokenKind.LITERAL_LONG) {
            result = (Literal.getLongLiteral(t.data, toPos(t), 10));
        } else if (t.kind == TokenKind.LITERAL_HEXINT) {
            result = (Literal.getIntLiteral(t.data, toPos(t), 16));
        } else if (t.kind == TokenKind.LITERAL_HEXLONG) {
            result = (Literal.getLongLiteral(t.data, toPos(t), 16));
        } else if (t.kind == TokenKind.LITERAL_REAL) {
            result = (Literal.getRealLiteral(t.data, toPos(t), false));
        } else if (t.kind == TokenKind.LITERAL_REAL_FLOAT) {
            result = (Literal.getRealLiteral(t.data, toPos(t), true));
        } else if (peekIdentifierToken("true")) {
            result = (Literal.ofBoolean(toPos(t), true));
        } else if (peekIdentifierToken("false")) {
            result = (Literal.ofBoolean(toPos(t), false));
        } else if (t.kind == TokenKind.LITERAL_STRING) {
            result = (Literal.ofString(toPos(t), t.data));
        } else {
            return null;
        }
        nextToken();
        return result;
    }

    //parenExpr : LPAREN! expression RPAREN!;
    private ExpressionNode maybeEatParenExpression() {
        if (peekToken(TokenKind.LPAREN)) {
            nextToken();
            ExpressionNode expr = eatExpression();
            eatToken(TokenKind.RPAREN);
            return expr;
        } else {
            return null;
        }
    }

    // relationalOperator
    // : EQUAL | NOT_EQUAL | LESS_THAN | LESS_THAN_OR_EQUAL | GREATER_THAN
    // | GREATER_THAN_OR_EQUAL | INSTANCEOF | BETWEEN | MATCHES
    private Token maybeEatRelationalOperator() {
        Token t = peekToken();
        if (t == null) {
            return null;
        }
        if (t.isNumericRelationalOperator()) {
            return t;
        }
        if (t.kind == TokenKind.TILDE) {
            return t;
        }
        if (t.kind == TokenKind.IDENTIFIER && Operator.IN.getPayload().equals(t.data)) {
            return t;
        }
        return null;
    }

    private Token eatToken(TokenKind expectedKind) {
        Token t = nextToken();
        if (t == null) {
            raiseInternalException(-1, SpelMessage.OOD);
        }
        if (t.kind != expectedKind) {
            raiseInternalException(t.startpos, SpelMessage.NOT_EXPECTED_TOKEN, expectedKind.toString().toLowerCase(), t.getKind().toString().toLowerCase());
        }
        return t;
    }

    private boolean peekToken(TokenKind desiredTokenKind) {
        return peekToken(desiredTokenKind, false);
    }

    private boolean peekToken(TokenKind desiredTokenKind, boolean consumeIfMatched) {
        if (!moreTokens()) {
            return false;
        }
        Token t = peekToken();
        if (t.kind == desiredTokenKind) {
            if (consumeIfMatched) {
                this.tokenStreamPointer++;
            }
            return true;
        }

        if (desiredTokenKind == TokenKind.IDENTIFIER) {
            // might be one of the textual forms of the operators (e.g. NE for != ) - in which case we can treat it as an identifier
            // The list is represented here: Tokenizer.alternativeOperatorNames and those ones are in order in the TokenKind enum
            if (t.kind.ordinal() >= TokenKind.DIV.ordinal() && t.kind.ordinal() <= TokenKind.NOT.ordinal() && t.data != null) {
                // if t.data were null, we'd know it wasn't the textual form, it was the symbol form
                return true;
            }
        }
        return false;
    }

    private boolean peekToken(TokenKind possible1, TokenKind possible2) {
        if (!moreTokens()) {
            return false;
        }
        Token t = peekToken();
        return (t.kind == possible1 || t.kind == possible2);
    }

    private boolean peekToken(TokenKind possible1, TokenKind possible2, TokenKind possible3) {
        if (!moreTokens()) {
            return false;
        }
        Token t = peekToken();
        return t.kind == possible1 || t.kind == possible2 || t.kind == possible3;
    }

    private boolean peekIdentifierToken(String identifierString) {
        if (!moreTokens()) {
            return false;
        }
        Token t = peekToken();
        return t.kind == TokenKind.IDENTIFIER && t.stringValue().equals(identifierString);
    }

    private Token eatKeyWord(Keyword keyword) {
        Token t = eatToken(TokenKind.IDENTIFIER);

        if (!t.stringValue().equals(keyword.idt)) {
            raiseInternalException(t.startpos, SpelMessage.KEYWORD_NOT_MATCH, keyword.idt, t.stringValue());
        }
        return t;
    }

    private boolean moreTokens() {
        return this.tokenStreamPointer < this.tokenStream.size();
    }

    private Token nextToken() {
        if (this.tokenStreamPointer >= this.tokenStreamLength) {
            return null;
        }
        return this.tokenStream.get(this.tokenStreamPointer++);
    }

    private Token peekToken() {
        if (this.tokenStreamPointer >= this.tokenStreamLength) {
            return null;
        }
        return this.tokenStream.get(this.tokenStreamPointer);
    }

    private void raiseInternalException(int pos, SpelMessage message, Object... inserts) {
        throw new ParseException((String) null, pos, message, inserts);
    }

    public String toString(Token t) {
        if (t.getKind().hasPayload()) {
            return t.stringValue();
        }
        return t.kind.toString().toLowerCase();
    }

    private void checkOperands(Token token, ExpressionNode left, ExpressionNode right) {
        checkLeftOperand(token, left);
        checkRightOperand(token, right);
    }

    private void checkLeftOperand(Token token, ExpressionNode operandExpression) {
        if (operandExpression == null) {
            raiseInternalException(token.startpos, SpelMessage.LEFT_OPERAND_PROBLEM);
        }
    }

    private void checkRightOperand(Token token, ExpressionNode operandExpression) {
        if (operandExpression == null) {
            raiseInternalException(token.startpos, SpelMessage.RIGHT_OPERAND_PROBLEM);
        }
    }

    /**
     * Compress the start and end of a token into a single int.
     */
    private int toPos(Token t) {
        return (t.startpos << 16) + t.endpos;
    }

    private int toPos(int start, int end) {
        return (start << 16) + end;
    }

}

Answer: return compile(script, StdLibrary.getDefInstance(), false);

<think>
The interface defines a static compile method that delegates to compile(script, StdLibrary.getDefInstance()). The next method, compileWithoutAssign, should similarly delegate but indicate that assignment statements are not allowed. The Parser constructor accepts a boolean hasAssign flag, so the implementation likely calls a three‑argument compile overload with false. Therefore the next line is the return statement invoking compile with the library instance and false.
</think>
return compile(script, StdLibrary.getDefInstance(), false);