js-on-sx: regex literal lex+parse+transpile+runtime stub
Lexer: js-regex-context? disambiguates / based on prior token;
read-regex handles [...] classes and \ escapes. Emits
{:type "regex" :value {:pattern :flags}}.
Parser: new primary branch → (js-regex pat flags).
Transpile: (js-regex-new pat flags).
Runtime: js-regex? predicate, js-regex-new builds tagged dict with
source/flags/global/ignoreCase/multiline/sticky/unicode/dotAll/
hasIndices/lastIndex. js-regex-invoke-method dispatches .test/.exec/
.toString. js-invoke-method detects regex receivers. Stub engine
uses js-string-index-of; __js_regex_platform__ + override! let a
real engine plug in later.
Runner: repeatable --filter flags (OR'd).
308/310 unit (+30 regex tests), 148/148 slice unchanged.
This commit is contained in:
@@ -386,6 +386,91 @@
|
||||
(and (= (len parts) 1) (= (nth (nth parts 0) 0) "str"))
|
||||
(nth (nth parts 0) 1)
|
||||
parts)))))
|
||||
(define
|
||||
js-regex-context?
|
||||
(fn
|
||||
()
|
||||
(if
|
||||
(= (len tokens) 0)
|
||||
true
|
||||
(let
|
||||
((tk (nth tokens (- (len tokens) 1))))
|
||||
(let
|
||||
((ty (dict-get tk "type")) (vv (dict-get tk "value")))
|
||||
(cond
|
||||
((= ty "punct")
|
||||
(and (not (= vv ")")) (not (= vv "]"))))
|
||||
((= ty "op") true)
|
||||
((= ty "keyword")
|
||||
(contains?
|
||||
(list
|
||||
"return"
|
||||
"typeof"
|
||||
"in"
|
||||
"of"
|
||||
"throw"
|
||||
"new"
|
||||
"delete"
|
||||
"instanceof"
|
||||
"void"
|
||||
"yield"
|
||||
"await"
|
||||
"case"
|
||||
"do"
|
||||
"else")
|
||||
vv))
|
||||
(else false)))))))
|
||||
(define
|
||||
read-regex
|
||||
(fn
|
||||
()
|
||||
(let
|
||||
((buf (list)) (in-class false))
|
||||
(advance! 1)
|
||||
(define
|
||||
body-loop
|
||||
(fn
|
||||
()
|
||||
(cond
|
||||
((>= pos src-len) nil)
|
||||
((= (cur) "\\")
|
||||
(begin
|
||||
(append! buf (cur))
|
||||
(advance! 1)
|
||||
(when
|
||||
(< pos src-len)
|
||||
(begin (append! buf (cur)) (advance! 1)))
|
||||
(body-loop)))
|
||||
((= (cur) "[")
|
||||
(begin
|
||||
(set! in-class true)
|
||||
(append! buf (cur))
|
||||
(advance! 1)
|
||||
(body-loop)))
|
||||
((= (cur) "]")
|
||||
(begin
|
||||
(set! in-class false)
|
||||
(append! buf (cur))
|
||||
(advance! 1)
|
||||
(body-loop)))
|
||||
((and (= (cur) "/") (not in-class)) (advance! 1))
|
||||
(else
|
||||
(begin (append! buf (cur)) (advance! 1) (body-loop))))))
|
||||
(body-loop)
|
||||
(let
|
||||
((flags-buf (list)))
|
||||
(define
|
||||
flags-loop
|
||||
(fn
|
||||
()
|
||||
(when
|
||||
(and (< pos src-len) (js-ident-char? (cur)))
|
||||
(begin
|
||||
(append! flags-buf (cur))
|
||||
(advance! 1)
|
||||
(flags-loop)))))
|
||||
(flags-loop)
|
||||
{:pattern (join "" buf) :flags (join "" flags-buf)}))))
|
||||
(define
|
||||
try-op-4!
|
||||
(fn
|
||||
@@ -510,6 +595,11 @@
|
||||
word
|
||||
start))
|
||||
(scan!)))
|
||||
((and (= ch "/") (js-regex-context?))
|
||||
(let
|
||||
((rx (read-regex)))
|
||||
(js-emit! "regex" rx start)
|
||||
(scan!)))
|
||||
((try-op-4! start) (scan!))
|
||||
((try-op-3! start) (scan!))
|
||||
((try-op-2! start) (scan!))
|
||||
|
||||
Reference in New Issue
Block a user