Zerg(3pm)

πŸ’œ Zerg πŸ’œ

okay so bestie, welcome to the Zerg(3pm) page β€” it's a User Contributed Perl Documentation situation, and we're about to get into a lexical scanner for BLAST reports. yes really. stay with me, it's gonna slay. πŸ¦‹


✨ NAME ✨

Zerg β€” a lexical scanner for BLAST reports. that's it, that's the whole vibe check. πŸŽ€


✨ SYNOPSIS ✨

use Zerg;

one line. iconic behavior. πŸ’…


✨ DESCRIPTION ✨

so this manpage is basically the tour of the Zerg library and how you (my darling bestie) talk to it from Perl. 🫢

the Zerg library ships a C/flex lexical scanner for BLAST reports plus a little squad of supporting functions. everything revolves around a get_token function β€” it scans the input hunting for specific lexical elements, and the moment it finds one, it hands you back its code and its value. like a lil assistant that only speaks in tokens. ✨

it's meant to be fast, fr fr: that's why they used flex, which gives you simple regular expression matching and input buffering inside the generated C scanner. and it's meant to be simple, in the sense that it's just a lexical scanner β€” no extra features that could slow down the main event. no bloat, no drama. 🌸

🧚 FUNCTIONS 🧚

  • zerg_get_token() β€” this is THE core function of the module, the main character, the moment. every time you call it, it scans the input BLAST report for the next "interesting" lexical element and returns its code and value. the codes live in the section "EXPORTED CONSTANTS (TOKEN CODES)" (scroll down, bestie, I got you). and heads up: code zero (not listed) means end of file. πŸ’€
($code, $value) = Zerg::zerg_get_token();
  • zerg_open_file($filename) β€” opens $filename in read-only mode and sets it as the input to the scanner. and if you don't call this one? standard input gets used instead. the default is just vibes, basically. 🐚
Zerg::zerg_open_file($filename);
  • zerg_close_file() β€” closes the file you opened with zerg_open_file(). clean up after yourself, queen. πŸŽ€
  • zerg_get_token_offset() β€” returns the byte offset (relative to the beginning of file) of the last token read. (and yes, see the BUGS section, it's giving caveats 😭)
  • zerg_ignore($code) β€” tells zerg_get_token to not return when it finds a token with code $code. silent treatment energy.
  • zerg_ignore_all() β€” does zerg_ignore on all token codes. ghost everything. πŸ’€
  • zerg_unignore($code) β€” tells zerg_get_token to actually return when it finds a token with code $code. letting them back in.
  • zerg_unignore_all() β€” does zerg_unignore on all token codes. everyone's invited again. πŸŽ‰

Example:

Zerg::zerg_ignore_all();
Zerg::zerg_unignore(QUERY_NAME);
Zerg::zerg_unignore(SUBJECT_NAME);

✨ EXPORTED CONSTANTS (TOKEN CODES) ✨

here's the full roster, no skips, no cuts, all of them:

ALIGNMENT_LENGTH
BLAST_VERSION
CONVERGED
DATABASE
DESCRIPTION_ANNOTATION
DESCRIPTION_EVALUE
DESCRIPTION_HITNAME
DESCRIPTION_SCORE
END_OF_REPORT
EVALUE
GAPS
HSP_METHOD
IDENTITIES
NOHITS
PERCENT_IDENTITIES
PERCENT_POSITIVES
POSITIVES
QUERY_ALI
QUERY_ANNOTATION
QUERY_END
QUERY_FRAME
QUERY_LENGTH
QUERY_NAME
QUERY_ORIENTATION
QUERY_START
REFERENCE
ROUND_NUMBER
ROUND_SEQ_FOUND
ROUND_SEQ_NEW
SCORE
SCORE_BITS
SEARCHING
SUBJECT_ALI
SUBJECT_ANNOTATION
SUBJECT_END
SUBJECT_FRAME
SUBJECT_LENGTH
SUBJECT_NAME
SUBJECT_ORIENTATION
SUBJECT_START
TAIL_OF_REPORT
UNMATCHED

periodt. πŸ‘‘


✨ NOTES ON THE SCANNER ✨

okay so this is the part where Zerg gently drags other parsers and honestly? deserved. 😭

some BLAST parsers rely on some simple regular expression matches to figure out token types and values. for example: an input line matching /^Query=\s(\S+)/ would make such a "loose" parser infer that a token was found, it's a query name, and its value is $1. and like... although it's improbable, it's perfectly possible for an annotation field to match /^Query=\s(\S+)/. oops! 🫠 and worse than that: those parsers are often unable to detect corrupt or truncated BLAST reports, possibly producing inaccurate information. not the slay we wanted.

the scanner this library provides is much more stringent: for a token to match, it must be in its place in the context of a BLAST report. for example: in a single BLAST report, a QUERY_NAME cannot follow another QUERY_NAME. you can think of the scanner as β€” and in fact it is β€” a big regular expression that matches an entire BLAST report. that's highkey the whole concept. 🧠✨

there's a special token code, UNMATCHED, for cases where the input text doesn't match any other lexical rule of the scanner. when an unmatched character shows up, either the report is corrupt or the scanner has a bug. so like... somebody's in trouble, and it might be you or it might be the scanner. πŸ™ˆ

and here's your optimization tip from the source itself: if you're interested in only a few token codes, try to zerg_ignore() as many codes as you can. this avoids unnecessary function calls that eat a lot of CPU. protect your CPU's peace. πŸ”₯


✨ EXAMPLES ✨

this program prints the code and the value of each token it finds. cute, simple, effective:

#!/usr/bin/perl -w
use strict;
use Zerg;

my ($code, $value);
while((($code, $value)= Zerg::zerg_get_token()) && $code)
{
    print "$code\t$value\n";
}

and the program below is a "syntax checker". the presence of UNMATCHEDs is a strong indicator of problems in the BLAST report. (go back and peep the NOTES ON THE SCANNER section, bestie) πŸ‘€

#!/usr/bin/perl -w
use strict;
use Zerg;

my ($code, $value);

Zerg::zerg_ignore_all();
Zerg::zerg_unignore(UNMATCHED);

while((($code, $value)= Zerg::zerg_get_token()) && $code)
{
    print "UNMATCHED CHAR:\t$value\n";
}

✨ BUGS ✨

okay bestie, listen up, this part matters: 🚨

the tokens DESCRIPTION_ANNOTATION, DESCRIPTION_SCORE and DESCRIPTION_EVALUE are scanned all at once and released one by one on user request. so β€” if you want to get any of these fields, they must be unignored BEFORE scanning DESCRIPTION_ANNOTATION. order matters. do not skip this step. 😀

also, zerg_get_token_offset() may return incorrect values for these tokens and those that are modified by the parser, namely: QUERY_LENGTH, SUBJECT_LENGTH, EVALUE, GAPS. yes that's a list of four (4) tokens and yes it's exactly those. noted and archived. πŸ“Œ


✨ TODO ✨

add more tokens to the scanner as the need for that appears. queen behavior honestly β€” growing when the moment calls for it. 🌱


✨ AUTHOR ✨

  • ApuΓ£ Paquola, IQ-USP Bioinformatics Lab, apua@iq.usp.br
  • Laszlo Kajan <lkajan@rostlab.org>, Technical University of Munich, Germany

two absolute icons, we thank them for their service. πŸ«ΆπŸ‘‘


✨ SEE ALSO ✨

perl(1), flex(1), http://www.bioperl.org, http://www.ncbi.nlm.nih.gov/BLAST


and that's the whole page, bestie!! πŸŽ€ this was perl v5.42.3, dated 2026-08-19, brought to you by the Zerg(3pm) girlies. now go parse some BLAST reports and remember: ignore what you don't need, unignore what you do, and never let a QUERY_NAME follow a QUERY_NAME. bye mwah πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from