如何使用fparsec解析由双倍空格分隔的单词的序列?

时间:2018-09-19 17:41:39

标签: parsing f# fparsec

输入:

alpha beta gamma  one two three

如何将其解析为以下内容?

[["alpha"; "beta"; "gamma"]; ["one"; "two"; "three"]]

当有更好的分隔符(例如__)时,我可以这样写,

sepBy (sepBy word (pchar ' ')) (pstring "__")

有效,但是在双倍空格的情况下,第一个sepBy中的pchar占用了第一个空格,然后解析器失败。

2 个答案:

答案 0 :(得分:2)

我建议将public ViewHolder(View itemView) { super(itemView); this.ticketTitle = itemView.findViewById(R.id.ticket_agent); this.ticketDescription = itemView.findViewById(R.id.ticket_description); this.ticketDate = itemView.findViewById(R.id.ticket_date); this.ticketStatus = itemView.findViewById(R.id.ticket_attachment); this.attachmentProgressBar = itemView.findViewById(R.id.attachment_progressbar); attachmentProgressBar.setVisibility(View.GONE); ticketStatus.setOnClickListener(new View.OnClickListener() { boolean counter = false; @Override public void onClick(View v) { if (requestPermission() == true) { File attachmentFile = new File((Environment.getExternalStorageDirectory() + "/" + context.getResources().getString(R.string.app_name) + "/" + context.getResources().getString(R.string.ticket_directory) + "/" + ticket.get(getAdapterPosition()).getCreatedAt().replaceAll("\\s|:|-","") + ".jpeg" )); if (!counter && !attachmentFile.exists()) { attachmentProgressBar.setVisibility(View.VISIBLE); ticketStatus.setVisibility(View.GONE); downloadAttachment(ticket.get(getAdapterPosition()).getAttachment(), ticket.get(getAdapterPosition()).getCreatedAt().replaceAll("\\s|:|-","") + ".jpeg", ticketStatus, attachmentProgressBar); counter = true; // Update UI only for this item. notifyItemChanged(getAdapterPosition()); } else { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); File file = new File((Environment.getExternalStorageDirectory() + "/" + context.getResources().getString(R.string.app_name) + "/" + context.getResources().getString(R.string.ticket_directory)), ticket.get(getAdapterPosition()).getCreatedAt().replaceAll("\\s|:|-","") + ".jpeg" ); intent.setDataAndType(FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file),"image/*"); activity.startActivity(intent); } } } }); 替换为以下内容:

sepBy word (pchar ' ')

注意:未经测试(因为我目前没有时间),只需在答案框中输入即可。因此,请进行测试,以防万一我在某个地方犯了错误。

答案 1 :(得分:0)

FParsec手册sayssepBy p sep中,如果sep成功并且随后的p失败(不更改状态),则整个sepBy都会失败也一样因此,您的目标是:

  1. 如果分隔符遇到多个空格字符,则使分隔符失败
  2. 进行回溯,以便“内部” sepBy循环愉快地关闭,并将控制权传递给“外部” sepBy循环。

这两种方法都是这样做的:

// this is your word parser; it can be different of course,
// I just made it as simple as possible;
let pWord = many1Satisfy isAsciiLetter

// this is the Inner separator to separate individual words
let pSepInner =
    pchar ' '
    .>> notFollowedBy (pchar ' ') // guard rule to prevent 2nd space
    |> attempt                    // a wrapper that would fail NON-fatally

// this is the Outer separator
let pSepOuter =
    pchar ' '
    |> many1  // loop

// this is the parser that would return String list list
let pMain =
    pWord
    |> sepBy <| pSepInner         // the Inner loop
    |> sepBy <| pSepOuter         // the Outer loop

使用:

run pMain "alpha beta gamma  one two three"
Success: [["alpha"; "beta"; "gamma"]; ["one"; "two"; "three"]]
相关问题