From 14f6dc66d5c50ed5efa349cd40491976199eac4f Mon Sep 17 00:00:00 2001 From: Chris Hanson Date: Sat, 29 Apr 2017 20:28:20 -0700 Subject: [PATCH] Rewrite regexp compiler to use bytevectors. Also add test. --- src/runtime/rgxcmp.scm | 375 +++++++++++++++++----------------- tests/check.scm | 3 +- tests/runtime/test-rgxcmp.scm | 240 ++++++++++++++++++++++ 3 files changed, 430 insertions(+), 188 deletions(-) create mode 100644 tests/runtime/test-rgxcmp.scm diff --git a/src/runtime/rgxcmp.scm b/src/runtime/rgxcmp.scm index ecb243f6b..b566c8904 100644 --- a/src/runtime/rgxcmp.scm +++ b/src/runtime/rgxcmp.scm @@ -38,17 +38,21 @@ USA. (let ((name (cadr form)) (prefix (caddr form)) (suffixes (cdddr form))) - `(BEGIN + `(begin ,@(let loop ((n 0) (suffixes suffixes)) (if (pair? suffixes) - (cons `(DEFINE-INTEGRABLE + (cons `(define-integrable ,(symbol prefix (car suffixes)) ,n) (loop (+ n 1) (cdr suffixes))) '())) - (DEFINE ,name - (VECTOR ,@(map (lambda (suffix) `',suffix) suffixes)))))))) + (define ,name + (vector ,@(map (lambda (suffix) `',suffix) suffixes)))))))) +(define (re-code-name byte) + (and (fix:< byte (vector-length re-codes)) + (vector-ref re-codes byte))) + (define-enumeration re-codes re-code: ;; Zero bytes may appear in the compiled regular expression. @@ -88,7 +92,7 @@ USA. ;; Matches any one character except for newline. any-char - + ;; Matches any one char belonging to specified set. First following ;; byte is # bitmap bytes. Then come bytes for a bit-map saying ;; which chars are in. Bits in each byte are ordered low-bit-first. @@ -130,8 +134,7 @@ USA. syntax-spec ;; Matches any character whose syntax differs from the specified. - not-syntax-spec - ) + not-syntax-spec) ;;;; Cache @@ -146,7 +149,7 @@ USA. ((null? items)) (set-car! items (cons (cons #f #f) #f))) (set-cdr! (last-pair items) items) - (cons* 'CACHE (make-thread-mutex) items))) + (cons* 'cache (make-thread-mutex) items))) (define-integrable (with-cache-locked cache thunk) (with-thread-mutex-lock (cadr cache) @@ -182,76 +185,61 @@ USA. ;;;; String Compiler (define (re-compile-char char case-fold?) - (let ((result (make-legacy-string 2))) - (vector-8b-set! result 0 re-code:exact-1) - (string-set! result 1 (if case-fold? (char-upcase char) char)) + (guarantee 8-bit-char? char 're-compile-char) + (let ((result (make-bytevector 2))) + (bytevector-u8-set! result 0 re-code:exact-1) + (bytevector-u8-set! result 1 + (char->integer (if case-fold? (char-upcase char) char))) (make-compiled-regexp result case-fold?))) (define re-compile-string (cached-procedure 16 (lambda (string case-fold?) - (let ((string (if case-fold? (string-upcase string) string))) - (let ((n (string-length string))) - (if (fix:zero? n) - (make-compiled-regexp string case-fold?) - (let ((result - (make-legacy-string - (let ((qr (integer-divide n 255))) - (fix:+ (fix:* 257 (integer-divide-quotient qr)) - (let ((r (integer-divide-remainder qr))) - (cond ((fix:zero? r) 0) - ((fix:= 1 r) 2) - (else (fix:+ r 2))))))))) - (let loop ((n n) (i 0) (p 0)) - (cond ((fix:= n 1) - (vector-8b-set! result p re-code:exact-1) - (vector-8b-set! result - (fix:1+ p) - (vector-8b-ref string i)) - (make-compiled-regexp result case-fold?)) - ((fix:< n 256) - (vector-8b-set! result p re-code:exact-n) - (vector-8b-set! result (fix:1+ p) n) - (string-copy! result (fix:+ p 2) string i (fix:+ i n)) - (make-compiled-regexp result case-fold?)) - (else - (vector-8b-set! result p re-code:exact-n) - (vector-8b-set! result (fix:1+ p) 255) - (let ((j (fix:+ i 255))) - (string-copy! result (fix:+ p 2) string i j) - (loop (fix:- n 255) j (fix:+ p 257))))))))))))) + (guarantee 8-bit-string? string 're-compile-string) + (let ((end (string-length string)) + (builder (bytevector-builder)) + (get-byte + (if case-fold? + (lambda (i) + (char->integer (char-upcase (string-ref string i)))) + (lambda (i) + (char->integer (string-ref string i)))))) + (let ((copy! + (lambda (start end) + (do ((i start (fix:+ i 1))) + ((not (fix:< i end))) + (builder (get-byte i)))))) + (let loop ((start 0)) + (if (fix:< start end) + (let ((n (fix:- end start))) + (if (fix:< n #x100) + (if (fix:= n 1) + (begin + (builder re-code:exact-1) + (builder (get-byte start))) + (begin + (builder re-code:exact-n) + (builder n) + (copy! start end))) + (begin + (builder re-code:exact-n) + (builder #xFF) + (let ((start* (fix:+ start #xFF))) + (copy! start start*) + (loop start*)))))))) + (make-compiled-regexp (builder) case-fold?))))) (define char-set:re-special (char-set #\[ #\] #\* #\. #\\ #\? #\+ #\^ #\$)) (define (re-quote-string string) - (let ((end (string-length string))) - (let ((n - (let loop ((start 0) (n 0)) - (let ((index - (string-find-next-char-in-set string char-set:re-special - start end))) - (if index - (loop (1+ index) (1+ n)) - n))))) - (if (zero? n) - string - (let ((result (make-legacy-string (+ end n)))) - (let loop ((start 0) (i 0)) - (let ((index - (string-find-next-char-in-set string char-set:re-special - start end))) - (if index - (begin - (string-copy! result i string start index) - (let ((i (+ i (- index start)))) - (string-set! result i #\\) - (string-set! result - (1+ i) - (string-ref string index)) - (loop (1+ index) (+ i 2)))) - (string-copy! result i string start end)))) - result))))) + (let ((builder (string-builder))) + (string-for-each (lambda (char) + (if (char-in-set? char char-set:re-special) + (builder #\\)) + (builder char)) + string) + (builder))) ;;;; Char-Set Compiler @@ -293,20 +281,15 @@ USA. ;;;; Translation Tables (define re-translation-table - (let ((normal-table (make-legacy-string 256))) - (let loop ((n 0)) - (if (< n 256) - (begin - (vector-8b-set! normal-table n n) - (loop (1+ n))))) - (let ((upcase-table (string-copy normal-table))) - (let loop ((n #x61)) - (if (< n #x7B) - (begin - (vector-8b-set! upcase-table n (- n #x20)) - (loop (1+ n))))) - (lambda (case-fold?) - (if case-fold? upcase-table normal-table))))) + (let ((normal-table (make-bytevector #x100)) + (upcase-table (make-bytevector #x100))) + (do ((i 0 (fix:+ i 1))) + ((not (fix:< i #x100))) + (bytevector-u8-set! normal-table i i) + (bytevector-u8-set! upcase-table i + (char->integer (char-upcase (integer->char i))))) + (lambda (case-fold?) + (if case-fold? upcase-table normal-table)))) ;;;; Pattern Compiler @@ -317,15 +300,15 @@ USA. re-number-of-registers) (define condition-type:re-compile-pattern - (make-condition-type 'RE-COMPILE-PATTERN condition-type:error - '(COMPILATION-CONTEXT MESSAGE) + (make-condition-type 're-compile-pattern condition-type:error + '(compilation-context message) (lambda (condition port) (write-string "Error compiling regular expression: " port) - (write-string (access-condition condition 'MESSAGE) port)))) + (write-string (access-condition condition 'message) port)))) (define compilation-error (condition-signaller condition-type:re-compile-pattern - '(COMPILATION-CONTEXT MESSAGE) + '(compilation-context message) standard-error-handler)) (define-structure (compiled-regexp @@ -334,8 +317,8 @@ USA. (byte-stream #f read-only #t) (translation-table #f read-only #t)) -(define (make-compiled-regexp byte-stream case-fold?) - (%make-compiled-regexp byte-stream (re-translation-table case-fold?))) +(define (make-compiled-regexp bytes case-fold?) + (%make-compiled-regexp bytes (re-translation-table case-fold?))) (define-structure (rgxcmpctx (conc-name #f)) input-list @@ -355,7 +338,8 @@ USA. (define re-compile-pattern (cached-procedure 16 (lambda (pattern case-fold?) - (let* ((output (list 'OUTPUT)) + (guarantee 8-bit-string? pattern 're-compile-pattern) + (let* ((output (list 'output)) (ctx (make-rgxcmpctx (map char->integer (string->list pattern)) #f ;current-byte (re-translation-table case-fold?) @@ -379,7 +363,7 @@ USA. (if (not (stack-empty? ctx)) (compilation-error ctx "Unmatched \\(")) (make-compiled-regexp - (list->string (map integer->char (cdr (output-head ctx)))) + (list->bytevector (cdr (output-head ctx))) case-fold?)) (begin (compile-pattern-char ctx) @@ -394,15 +378,13 @@ USA. (null? (cdr (input-list ctx)))) (define-integrable (input-peek ctx) - (vector-8b-ref (translation-table ctx) (car (input-list ctx)))) + (bytevector-u8-ref (translation-table ctx) (car (input-list ctx)))) (define-integrable (input-peek+1 ctx) - (vector-8b-ref (translation-table ctx) (cadr (input-list ctx)))) + (bytevector-u8-ref (translation-table ctx) (cadr (input-list ctx)))) (define-integrable (input-discard! ctx) - (let ((c ctx)) - (set-input-list! c (cdr (input-list c)))) - unspecific) + (set-input-list! ctx (cdr (input-list ctx)))) (define-integrable (input! ctx) (set-current-byte! ctx (input-peek ctx)) @@ -541,7 +523,7 @@ USA. unspecific) (define pattern-chars - (make-vector 256 normal-char)) + (make-vector #x100 normal-char)) (define-pattern-char #\\ (lambda (ctx) @@ -556,7 +538,7 @@ USA. unspecific) (define backslash-chars - (make-vector 256 normal-char)) + (make-vector #x100 normal-char)) (define-pattern-char #\$ ;; $ means succeed if at end of line, but only in special contexts. @@ -673,7 +655,7 @@ USA. (let ((invert? (and (input-match? (input-peek ctx) #\^) (begin (input-discard! ctx) #t))) - (charset (make-legacy-string 32 (integer->char 0)))) + (bitmap (make-bytevector #x20 0))) (if (input-end? ctx) (premature-end ctx)) (let loop @@ -687,30 +669,27 @@ USA. (premature-end ctx)) (let ((char (input-read! ctx))) (if (input-match? char #\]) - (begin - (for-each - (lambda (char) - ((ucode-primitive re-char-set-adjoin!) charset - (char->integer char))) - (char-set-members - (re-compile-char-set - (list->string (map integer->char (reverse! chars))) - #f)))) + (let ((charset + (re-compile-char-set + (list->string (map integer->char (reverse! chars))) + #f))) + (do ((i 0 (fix:+ i 1))) + ((not (fix:< i #x100))) + (if (code-point-in-char-set? i charset) + ((ucode-primitive re-char-set-adjoin!) bitmap i)))) (loop (cons char chars))))) (output-start! ctx (if invert? re-code:not-char-set re-code:char-set)) - ;; Discard any bitmap bytes that are all 0 at the end of - ;; the map. Decrement the map-length byte too. - (let loop ((n 31)) - (cond ((not (fix:= 0 (vector-8b-ref charset n))) - (output! ctx (fix:+ n 1)) - (let loop ((i 0)) - (output! ctx (vector-8b-ref charset i)) - (if (fix:< i n) - (loop (fix:+ i 1))))) - ((fix:= 0 n) - (output! ctx 0)) - (else - (loop (fix:- n 1)))))))) + (let ((end + ;; Discard any bitmap bytes that are all 0 at the end of the map. + (let loop ((i #x20)) + (if (and (fix:> i 0) + (fix:= 0 (bytevector-u8-ref bitmap (fix:- i 1)))) + (loop (fix:- i 1)) + i)))) + (output! ctx end) + (do ((i 0 (fix:+ i 1))) + ((not (fix:< i end))) + (output! ctx (bytevector-u8-ref bitmap i))))))) ;;;; Alternative Groups @@ -787,70 +766,92 @@ USA. ;;;; Compiled Pattern Disassembler -(define (re-disassemble-pattern compiled-pattern) - (let* ((bytes (compiled-regexp/byte-stream compiled-pattern)) - (n (string-length bytes))) - (let loop ((i 0)) - (newline) - (write i) - (write-string " (") - (if (< i n) - (case (let ((re-code-name - (vector-ref re-codes (vector-8b-ref bytes i)))) - (write re-code-name) - re-code-name) - ((UNUSED LINE-START LINE-END ANY-CHAR BUFFER-START BUFFER-END - WORD-CHAR NOT-WORD-CHAR WORD-START WORD-END WORD-BOUND - NOT-WORD-BOUND) - (write-string ")") - (loop (1+ i))) - ((EXACT-1) - (write-string " ") - (let ((end (+ i 2))) - (write (substring bytes (1+ i) end)) - (write-string ")") - (loop end))) - ((EXACT-N) - (write-string " ") - (let ((start (+ i 2)) - (n (vector-8b-ref bytes (1+ i)))) - (let ((end (+ start n))) - (write (substring bytes start end)) - (write-string ")") - (loop end)))) - ((JUMP ON-FAILURE-JUMP MAYBE-FINALIZE-JUMP DUMMY-FAILURE-JUMP) - (write-string " ") - (let ((end (+ i 3)) - (offset - (+ (* 256 (vector-8b-ref bytes (+ i 2))) - (vector-8b-ref bytes (1+ i))))) - (write (+ end (if (< offset #x8000) offset (- offset #x10000)))) - (write-string ")") - (loop end))) - ((CHAR-SET NOT-CHAR-SET) - (let ((end (+ (+ i 2) (vector-8b-ref bytes (1+ i))))) - (let spit ((i (+ i 2))) - (if (< i end) - (begin - (write-string " ") - (let ((n (vector-8b-ref bytes i))) - (if (< n 16) (write-char #\0)) - (write-string (number->string n 16))) - (spit (1+ i))) - (begin - (write-string ")") - (loop i)))))) - ((START-MEMORY STOP-MEMORY DUPLICATE) - (write-string " ") - (write (vector-8b-ref bytes (1+ i))) - (write-string ")") - (loop (+ i 2))) - ((SYNTAX-SPEC NOT-SYNTAX-SPEC) - (write-string " ") - (write (string-ref " .w_()'\"$\\/<>" - (vector-8b-ref bytes (1+ i)))) - (write-string ")") - (loop (+ i 2)))) - (begin - (write 'end) - (write-string ")")))))) \ No newline at end of file +(define (re-disassemble-pattern compiled-pattern #!optional output) + (let ((output (if (default-object? output) (current-output-port) output)) + (input + (open-input-bytevector + (compiled-regexp/byte-stream compiled-pattern)))) + + (define (get-byte) + (let ((byte (read-u8 input))) + (if (eof-object? byte) + (error "Premature pattern end.")) + byte)) + + (define (write-hex-byte byte) + (write-char (digit->char (fix:lsh byte -4) 16) output) + (write-char (digit->char (fix:and byte #x0F) 16) output)) + + (define (loop address) + (write address output) + (write-char #\space output) + (let ((byte (read-u8 input))) + (if (eof-object? byte) + (begin + (write-string "(end)" output) + (newline output)) + (let ((address (fix:+ address 1)) + (name (re-code-name byte))) + (write-char #\( output) + (write (or name 'unknown) output) + (let ((consumed + (if name + (known-code address name) + (begin + (write-string " #x" output) + (write-hex-byte byte) + 0)))) + (write-char #\) output) + (newline output) + (loop (fix:+ address consumed))))))) + + (define (known-code address name) + (case name + ((unused line-start line-end any-char buffer-start buffer-end + word-char not-word-char word-start word-end word-bound + not-word-bound) + 0) + ((exact-1) + (write-char #\space output) + (write (string (integer->char (get-byte))) output) + 1) + ((exact-n) + (write-char #\space output) + (let ((n (get-byte)) + (sbuilder (string-builder))) + (do ((i 0 (fix:+ i 1))) + ((not (fix:< i 1))) + (sbuilder (integer->char (get-byte)))) + (write (sbuilder) output) + (fix:+ 1 n))) + ((jump on-failure-jump maybe-finalize-jump dummy-failure-jump) + (write-char #\space output) + (write (fix:+ (fix:+ address 2) + (let* ((b1 (get-byte)) + (b2 (get-byte)) + (offset (fix:or b1 (fix:lsh b2 8)))) + (if (fix:< offset #x8000) + offset + (fix:- offset #x10000)))) + output) + 2) + ((char-set not-char-set) + (let ((n (get-byte))) + (do ((i 0 (fix:+ i 1))) + ((not (fix:< i n))) + (write-char #\space output) + (write-hex-byte (get-byte))) + (fix:+ 1 n))) + ((start-memory stop-memory duplicate) + (write-char #\space output) + (write (get-byte) output) + 1) + ((syntax-spec not-syntax-spec) + (write-char #\space output) + (write (string-ref " .w_()'\"$\\/<>" (get-byte)) + output) + 1) + (else + (error "Unknown code name:" name)))) + + (loop 0))) \ No newline at end of file diff --git a/tests/check.scm b/tests/check.scm index 22e57e7f9..cce540fb7 100644 --- a/tests/check.scm +++ b/tests/check.scm @@ -65,12 +65,13 @@ USA. ("runtime/test-parametric-predicate" (runtime parametric-predicate)) ("runtime/test-predicate-lattice" (runtime)) ("runtime/test-predicate-metadata" (runtime)) - "runtime/test-thread-queue" "runtime/test-process" "runtime/test-readwrite" "runtime/test-regsexp" + "runtime/test-rgxcmp" "runtime/test-string" "runtime/test-string-normalization" + "runtime/test-thread-queue" "runtime/test-url" ("runtime/test-wttree" (runtime wt-tree)) ;;"ffi/test-ffi" diff --git a/tests/runtime/test-rgxcmp.scm b/tests/runtime/test-rgxcmp.scm new file mode 100644 index 000000000..45515d7a1 --- /dev/null +++ b/tests/runtime/test-rgxcmp.scm @@ -0,0 +1,240 @@ +#| -*-Scheme-*- + +Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, + 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, + 2017 Massachusetts Institute of Technology + +This file is part of MIT/GNU Scheme. + +MIT/GNU Scheme is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +MIT/GNU Scheme is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with MIT/GNU Scheme; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, +USA. + +|# + +;;;; Tests for regular expression compiler + +(declare (usual-integrations)) + +(define-test 'test-compiler + (lambda () + (let ((compiled (re-compile-pattern regexp #f))) + (assert-equal (compiled-regexp/byte-stream compiled) + (hexadecimal->bytevector compiled-regexp)) + (assert-equal (call-with-output-string + (lambda (port) + (re-disassemble-pattern compiled port))) + disassembled-output)))) + +(define regexp + ".*\\([0-9][BEGKMPTY-Zk]?\\|)\\) +\\(\\(['A-Za-z\200-ÿ]['A-Za-z\200-ÿ]+\\.? +[ 0-3][0-9]\\|[ 0-3][0-9]\\.? ['A-Za-z\200-ÿ]['A-Za-z\200-ÿ]+\\.?\\) +\\([ 0-2][0-9][.:][0-5][0-9]\\|[0-9][0-9][0-9][0-9]\\)\\|['A-Za-z\200-ÿ]['A-Za-z\200-ÿ]+\\.? +[ 0-3][0-9], +[0-9][0-9][0-9][0-9]\\|\\([ 0-1]?[0-9][A-Za-z\200-ÿ]? [ 0-3][0-9][A-Za-z\200-ÿ]? +\\|[ 0-3][0-9] [ 0-1]?[0-9] +\\)\\([ 0-2][0-9][.:][0-5][0-9]\\|[0-9][0-9][0-9][0-9][A-Za-z\200-ÿ]?\\)\\|\\([0-9][0-9][0-9][0-9]-\\)?[0-1][0-9]-[0-3][0-9][ T][ 0-2][0-9][.:][0-5][0-9]\\(:[0-6][0-9]\\([,.][0-9]+\\)?\\( ?[-+][0-2][0-9][0-5][0-9]\\)?\\)?\\|[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]\\) +") + +(define compiled-regexp + "0604000a08f9ff0d010620000b08000000000000ff030610000b0e0000000000000000a428110600080503000201290e01090300060500012008f8ff0d020657010d030673000b200000000080000000feffff07feffff07ffffffffffffffffffffffffffffffff0903000625000b200000000080000000feffff07feffff07ffffffffffffffffffffffffffffffff08d8ff060200012e090300060500012008f8ff0b070000000001000f0b08000000000000ff03056d000b070000000001000f0b08000000000000ff03060200012e0201200b200000000080000000feffff07feffff07ffffffffffffffffffffffffffffffff0903000625000b200000000080000000feffff07feffff07ffffffffffffffffffffffffffffffff08d8ff060200012e0e03090300060500012008f8ff0d040633000b07000000000100070b08000000000000ff030b0800000000004000040b070000000000003f0b08000000000000ff030528000b08000000000000ff030b08000000000000ff030b08000000000000ff030b08000000000000ff030e0405a90006a9000b200000000080000000feffff07feffff07ffffffffffffffffffffffffffffffff0903000625000b200000000080000000feffff07feffff07ffffffffffffffffffffffffffffffff08d8ff060200012e090300060500012008f8ff0b070000000001000f0b08000000000000ff0302012c090300060500012008f8ff0b08000000000000ff030b08000000000000ff030b08000000000000ff030b08000000000000ff03054c01064c010d050684000609000b07000000000100030b08000000000000ff030622000b200000000000000000feffff07feffff07ffffffffffffffffffffffffffffffff0201200b070000000001000f0b08000000000000ff030622000b200000000000000000feffff07feffff07ffffffffffffffffffffffffffffffff090300060500012008f8ff0537000b070000000001000f0b08000000000000ff030201200609000b07000000000100030b08000000000000ff03090300060500012008f8ff0e050d060633000b07000000000100070b08000000000000ff030b0800000000004000040b070000000000003f0b08000000000000ff03054d000b08000000000000ff030b08000000000000ff030b08000000000000ff030b08000000000000ff030622000b200000000000000000feffff07feffff07ffffffffffffffffffffffffffffffff0e060510010610010d07062d000b08000000000000ff030b08000000000000ff030b08000000000000ff030b08000000000000ff0302012d0e070b07000000000000030b08000000000000ff0302012d0b070000000000000f0b08000000000000ff030b0b00000000010000000000100b07000000000100070b08000000000000ff030b0800000000004000040b070000000000003f0b08000000000000ff030d0806700002013a0b070000000000007f0b08000000000000ff030d09061d000b06000000000050090300060d000b08000000000000ff0308f0ff0e0906330006020001200b060000000000280b07000000000000070b08000000000000ff030b070000000000003f0b08000000000000ff030e080554000b08000000000000ff030b08000000000000ff030b08000000000000ff030b08000000000000ff0302012d0b07000000000000030b08000000000000ff0302012d0b070000000000000f0b08000000000000ff030e02090300060500012008f8ff") + +(define disassembled-output + "0 (on-failure-jump 7) +3 (any-char) +4 (maybe-finalize-jump 0) +7 (start-memory 1) +9 (on-failure-jump 44) +12 (char-set 00 00 00 00 00 00 ff 03) +22 (on-failure-jump 41) +25 (char-set 00 00 00 00 00 00 00 00 a4 28 11 06 00 08) +41 (jump 47) +44 (exact-n \")\") +47 (stop-memory 1) +49 (dummy-failure-jump 55) +52 (on-failure-jump 60) +55 (exact-1 \" \") +57 (maybe-finalize-jump 52) +60 (start-memory 2) +62 (on-failure-jump 408) +65 (start-memory 3) +67 (on-failure-jump 185) +70 (char-set 00 00 00 00 80 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +104 (dummy-failure-jump 110) +107 (on-failure-jump 147) +110 (char-set 00 00 00 00 80 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +144 (maybe-finalize-jump 107) +147 (on-failure-jump 152) +150 (exact-1 \".\") +152 (dummy-failure-jump 158) +155 (on-failure-jump 163) +158 (exact-1 \" \") +160 (maybe-finalize-jump 155) +163 (char-set 00 00 00 00 01 00 0f) +172 (char-set 00 00 00 00 00 00 ff 03) +182 (jump 294) +185 (char-set 00 00 00 00 01 00 0f) +194 (char-set 00 00 00 00 00 00 ff 03) +204 (on-failure-jump 209) +207 (exact-1 \".\") +209 (exact-n \" \") +212 (char-set 00 00 00 00 80 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +246 (dummy-failure-jump 252) +249 (on-failure-jump 289) +252 (char-set 00 00 00 00 80 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +286 (maybe-finalize-jump 249) +289 (on-failure-jump 294) +292 (exact-1 \".\") +294 (stop-memory 3) +296 (dummy-failure-jump 302) +299 (on-failure-jump 307) +302 (exact-1 \" \") +304 (maybe-finalize-jump 299) +307 (start-memory 4) +309 (on-failure-jump 363) +312 (char-set 00 00 00 00 01 00 07) +321 (char-set 00 00 00 00 00 00 ff 03) +331 (char-set 00 00 00 00 00 40 00 04) +341 (char-set 00 00 00 00 00 00 3f) +350 (char-set 00 00 00 00 00 00 ff 03) +360 (jump 403) +363 (char-set 00 00 00 00 00 00 ff 03) +373 (char-set 00 00 00 00 00 00 ff 03) +383 (char-set 00 00 00 00 00 00 ff 03) +393 (char-set 00 00 00 00 00 00 ff 03) +403 (stop-memory 4) +405 (jump 577) +408 (on-failure-jump 580) +411 (char-set 00 00 00 00 80 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +445 (dummy-failure-jump 451) +448 (on-failure-jump 488) +451 (char-set 00 00 00 00 80 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +485 (maybe-finalize-jump 448) +488 (on-failure-jump 493) +491 (exact-1 \".\") +493 (dummy-failure-jump 499) +496 (on-failure-jump 504) +499 (exact-1 \" \") +501 (maybe-finalize-jump 496) +504 (char-set 00 00 00 00 01 00 0f) +513 (char-set 00 00 00 00 00 00 ff 03) +523 (exact-n \",\") +526 (dummy-failure-jump 532) +529 (on-failure-jump 537) +532 (exact-1 \" \") +534 (maybe-finalize-jump 529) +537 (char-set 00 00 00 00 00 00 ff 03) +547 (char-set 00 00 00 00 00 00 ff 03) +557 (char-set 00 00 00 00 00 00 ff 03) +567 (char-set 00 00 00 00 00 00 ff 03) +577 (jump 912) +580 (on-failure-jump 915) +583 (start-memory 5) +585 (on-failure-jump 720) +588 (on-failure-jump 600) +591 (char-set 00 00 00 00 01 00 03) +600 (char-set 00 00 00 00 00 00 ff 03) +610 (on-failure-jump 647) +613 (char-set 00 00 00 00 00 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +647 (exact-n \" \") +650 (char-set 00 00 00 00 01 00 0f) +659 (char-set 00 00 00 00 00 00 ff 03) +669 (on-failure-jump 706) +672 (char-set 00 00 00 00 00 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +706 (dummy-failure-jump 712) +709 (on-failure-jump 717) +712 (exact-1 \" \") +714 (maybe-finalize-jump 709) +717 (jump 775) +720 (char-set 00 00 00 00 01 00 0f) +729 (char-set 00 00 00 00 00 00 ff 03) +739 (exact-n \" \") +742 (on-failure-jump 754) +745 (char-set 00 00 00 00 01 00 03) +754 (char-set 00 00 00 00 00 00 ff 03) +764 (dummy-failure-jump 770) +767 (on-failure-jump 775) +770 (exact-1 \" \") +772 (maybe-finalize-jump 767) +775 (stop-memory 5) +777 (start-memory 6) +779 (on-failure-jump 833) +782 (char-set 00 00 00 00 01 00 07) +791 (char-set 00 00 00 00 00 00 ff 03) +801 (char-set 00 00 00 00 00 40 00 04) +811 (char-set 00 00 00 00 00 00 3f) +820 (char-set 00 00 00 00 00 00 ff 03) +830 (jump 910) +833 (char-set 00 00 00 00 00 00 ff 03) +843 (char-set 00 00 00 00 00 00 ff 03) +853 (char-set 00 00 00 00 00 00 ff 03) +863 (char-set 00 00 00 00 00 00 ff 03) +873 (on-failure-jump 910) +876 (char-set 00 00 00 00 00 00 00 00 fe ff ff 07 fe ff ff 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff) +910 (stop-memory 6) +912 (jump 1187) +915 (on-failure-jump 1190) +918 (start-memory 7) +920 (on-failure-jump 968) +923 (char-set 00 00 00 00 00 00 ff 03) +933 (char-set 00 00 00 00 00 00 ff 03) +943 (char-set 00 00 00 00 00 00 ff 03) +953 (char-set 00 00 00 00 00 00 ff 03) +963 (exact-n \"-\") +966 (stop-memory 7) +968 (char-set 00 00 00 00 00 00 03) +977 (char-set 00 00 00 00 00 00 ff 03) +987 (exact-n \"-\") +990 (char-set 00 00 00 00 00 00 0f) +999 (char-set 00 00 00 00 00 00 ff 03) +1009 (char-set 00 00 00 00 01 00 00 00 00 00 10) +1022 (char-set 00 00 00 00 01 00 07) +1031 (char-set 00 00 00 00 00 00 ff 03) +1041 (char-set 00 00 00 00 00 40 00 04) +1051 (char-set 00 00 00 00 00 00 3f) +1060 (char-set 00 00 00 00 00 00 ff 03) +1070 (start-memory 8) +1072 (on-failure-jump 1187) +1075 (exact-n \":\") +1078 (char-set 00 00 00 00 00 00 7f) +1087 (char-set 00 00 00 00 00 00 ff 03) +1097 (start-memory 9) +1099 (on-failure-jump 1131) +1102 (char-set 00 00 00 00 00 50) +1110 (dummy-failure-jump 1116) +1113 (on-failure-jump 1129) +1116 (char-set 00 00 00 00 00 00 ff 03) +1126 (maybe-finalize-jump 1113) +1129 (stop-memory 9) +1131 (on-failure-jump 1185) +1134 (on-failure-jump 1139) +1137 (exact-1 \" \") +1139 (char-set 00 00 00 00 00 28) +1147 (char-set 00 00 00 00 00 00 07) +1156 (char-set 00 00 00 00 00 00 ff 03) +1166 (char-set 00 00 00 00 00 00 3f) +1175 (char-set 00 00 00 00 00 00 ff 03) +1185 (stop-memory 8) +1187 (jump 1274) +1190 (char-set 00 00 00 00 00 00 ff 03) +1200 (char-set 00 00 00 00 00 00 ff 03) +1210 (char-set 00 00 00 00 00 00 ff 03) +1220 (char-set 00 00 00 00 00 00 ff 03) +1230 (exact-n \"-\") +1233 (char-set 00 00 00 00 00 00 03) +1242 (char-set 00 00 00 00 00 00 ff 03) +1252 (exact-n \"-\") +1255 (char-set 00 00 00 00 00 00 0f) +1264 (char-set 00 00 00 00 00 00 ff 03) +1274 (stop-memory 2) +1276 (dummy-failure-jump 1282) +1279 (on-failure-jump 1287) +1282 (exact-1 \" \") +1284 (maybe-finalize-jump 1279) +1287 (end) +") \ No newline at end of file -- 2.25.1