9 Commits

Author SHA1 Message Date
Andrew Gallant
b3e5fd2dde regex: remove old regex-syntax crate
This commit does the mechanical changes necessary to remove the old
regex-syntax crate and replace it with the rewrite. The rewrite now
subsumes the `regex-syntax` crate name, and gets a semver bump to 0.5.0.
2018-03-07 19:01:24 -05:00
Andrew Gallant
040a71f9d4 regex-debug: add utf8-ranges sub-command
This sub-command prints out the UTF-8 alternation machine for an
arbitrary character class.
2018-03-07 19:01:24 -05:00
Andrew Gallant
4ae3ae9d92 regex: move to regex-syntax-2
This commit moves the entire regex crate over to the regex-syntax-2
rewrite. Most of this is just rewriting types.

The compiler got the most interesting set of changes. It got simpler
in some respects, but not significantly so.
2018-03-07 19:01:24 -05:00
Andrew Gallant
715a807289 syntax: rewrite the regex-syntax crate
This commit represents a ground up rewrite of the regex-syntax crate.
This commit is also an intermediate state. That is, it adds a new
regex-syntax-2 crate without making any serious changes to any other
code. Subsequent commits will cover the integration of the rewrite and
the removal of the old crate.

The rewrite is intended to be the first phase in an effort to overhaul
the entire regex crate. To that end, this rewrite takes steps in that
direction:

* The principle change in the public API is an explicit split between a
  regular expression's abstract syntax (AST) and a high-level
  intermediate representation (HIR) that is easier to analyze. The old
  version of this crate mixes these two concepts, but leaned heavily
  towards an HIR. The AST in the rewrite has a much closer
  correspondence with the concrete syntax than the old `Expr` type does.
  The new HIR embraces its role; all flags are now compiled away
  (including the `i` flag), which will simplify subsequent passes,
  including literal detection and the compiler. ASTs are produced by
  ast::parse and HIR is produced by hir::translate. A top-level parser
  is provided that combines these so that callers can skip straight from
  concrete syntax to HIR.
* Error messages are vastly improved thanks to the span information that
  is now embedded in the AST. In addition to better formatting, error
  messages now also include helpful hints when trying to use features
  that aren't supported (like backreferences and look-around). In
  particular, octal support is now an opt-in option. (Octal support
  will continue to be enabled in regex proper to support backwards
  compatibility, but will be disabled in 1.0.)
* More robust support for Unicode Level 1 as described in UTS#18.
  In particular, we now fully support Unicode character classes
  including set notation (difference, intersection, symmetric
  difference) and correct support for named general categories, scripts,
  script extensions and age. That is, `\p{scx:Hira}` and `p{age:3.0}`
  now work. To make this work, we introduce an internal interval set
  data structure.
* With the exception of literal extraction (which will be overhauled in
  a later phase), all code in the rewrite uses constant stack space,
  even while performing analysis that requires structural induction over
  the AST or HIR. This is done by pushing the call stack onto the heap,
  and is abstracted by the `ast::Visitor` and `hir::Visitor` traits.
  The point of this method is to eliminate stack overflows in the
  general case.
* Empty sub-expressions are now properly supported. Expressions like
  `()`, `|`, `a|` and `b|()+` are now valid syntax.

The principle downsides of these changes are parse time and binary size.
Both seemed to have increased (slower and bigger) by about 1.5x. Parse
time is generally peanuts compared to the compiler, so we mostly don't
care about that. Binary size is mildly unfortunate, and if it becomes a
serious issue, it should be possible to introduce a feature that
disables some level of Unicode support and/or work on compressing the
Unicode tables. Compile times have increased slightly, but are still a
very small fraction of the overall time it takes to compile `regex`.

Fixes #174, Fixes #424
2018-03-07 19:01:24 -05:00
Andrew Gallant
65c4f8ee1f docs: link to docs.rs 2017-12-30 15:37:41 -05:00
Andrew Gallant
f0d2c3ce59 regex-debug: update deps
Principally, this updates docopt to 0.8, which replaces rustc-serialize
with serde.
2017-12-30 15:37:41 -05:00
Andrew Gallant
2f1e5b0e10 deps: setup workspace
There are a few sub-crates in this repository, so sharing a target
directory makes sense.
2017-12-30 15:37:41 -05:00
Andrew Gallant
ac3ab6d21b Bump versions everywhere and update CHANGELOG.
Fixes #296, Fixes #307
2016-12-31 17:01:54 -05:00
Andrew Gallant
31a317eadd Major literal optimization refactoring.
The principle change in this commit is a complete rewrite of how
literals are detected from a regular expression. In particular, we now
traverse the abstract syntax to discover literals instead of the
compiled byte code. This permits more tuneable control over which and
how many literals are extracted, and is now exposed in the
`regex-syntax` crate so that others can benefit from it.

Other changes in this commit:

* The Boyer-Moore algorithm was rewritten to use my own concoction based
  on frequency analysis. We end up regressing on a couple benchmarks
  slightly because of this, but gain in some others and in general should
  be faster in a broader number of cases. (Principally because we try to
  run `memchr` on the rarest byte in a literal.) This should also greatly
  improve handling of non-Western text.
* A "reverse suffix" literal optimization was added. That is, if suffix
  literals exist but no prefix literals exist, then we can quickly scan
  for suffix matches and then run the DFA in reverse to find matches.
  (I'm not aware of any other regex engine that does this.)
* The mutex-based pool has been replaced with a spinlock-based pool
  (from the new `mempool` crate). This reduces some amount of constant
  overhead and improves several benchmarks that either search short
  haystacks or find many matches in long haystacks.
* Search parameters have been refactored.
* RegexSet can now contain 0 or more regular expressions (previously, it
  could only contain 2 or more). The InvalidSet error variant is now
  deprecated.
* A bug in computing start states was fixed. Namely, the DFA assumed the
  start states was always the first instruction, which is trivially
  wrong for an expression like `^☃$`. This bug persisted because it
  typically occurred when a literal optimization would otherwise run.
* A new CLI tool, regex-debug, has been added as a non-published
  sub-crate. The CLI tool can answer various facts about regular
  expressions, such as printing its AST, its compiled byte code or its
  detected literals.

Closes #96, #188, #189
2016-03-27 20:07:46 -04:00