modern: add to core to eventually take over as the new parser. same as code-factor's version except i added support for :foo words.
parent
507957eae3
commit
5e8244c47e
|
@ -0,0 +1 @@
|
||||||
|
Doug Coleman
|
|
@ -0,0 +1 @@
|
||||||
|
Doug Coleman
|
|
@ -0,0 +1,370 @@
|
||||||
|
! Copyright (C) 2016 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors arrays assocs classes.mixin combinators
|
||||||
|
combinators.short-circuit definitions effects effects.parser fry
|
||||||
|
graphs io.pathnames kernel lexer locals math math.statistics
|
||||||
|
memoize modern multiline parser quotations sequences
|
||||||
|
sequences.extras sets splitting strings unicode words ;
|
||||||
|
IN: modern.compiler
|
||||||
|
|
||||||
|
: vocab>core2-path ( vocab -- path )
|
||||||
|
".private" ?tail drop
|
||||||
|
"." split "/" join
|
||||||
|
[ "resource:core2/" prepend-path ]
|
||||||
|
[ file-name ".factor" append append-path ] bi ;
|
||||||
|
|
||||||
|
: filter-using ( using -- using' )
|
||||||
|
{ "accessors" "threads.private" "threads" } diff ;
|
||||||
|
|
||||||
|
<<
|
||||||
|
SYNTAX: STRING-DISPATCH:
|
||||||
|
[
|
||||||
|
scan-new-word scan-effect
|
||||||
|
H{ } clone over [ in>> but-last ] [ out>> ] bi <effect>
|
||||||
|
'[ _ ?at [ throw ] unless _ call-effect ]
|
||||||
|
swap
|
||||||
|
] with-definition define-declared ;
|
||||||
|
|
||||||
|
SYNTAX: STRING-M:
|
||||||
|
[
|
||||||
|
scan-token scan-word parse-definition
|
||||||
|
over changed-definition
|
||||||
|
swap def>> first swapd set-at
|
||||||
|
] with-definition ;
|
||||||
|
>>
|
||||||
|
|
||||||
|
|
||||||
|
TUPLE: holder literal ;
|
||||||
|
TUPLE: comment' < holder ;
|
||||||
|
TUPLE: using' < holder ;
|
||||||
|
TUPLE: use' < holder ;
|
||||||
|
TUPLE: in' < holder ;
|
||||||
|
TUPLE: qualified-with' < holder ;
|
||||||
|
TUPLE: qualified' < holder ;
|
||||||
|
TUPLE: script' < holder ;
|
||||||
|
TUPLE: m' < holder ;
|
||||||
|
TUPLE: instance' < holder ;
|
||||||
|
TUPLE: word' < holder ;
|
||||||
|
TUPLE: generic' < holder ;
|
||||||
|
TUPLE: generic#' < holder ;
|
||||||
|
TUPLE: hook' < holder ;
|
||||||
|
TUPLE: math' < holder ;
|
||||||
|
TUPLE: constant' < holder ;
|
||||||
|
TUPLE: c' < holder ;
|
||||||
|
TUPLE: initialize' < holder ;
|
||||||
|
TUPLE: startup-hook' < holder ;
|
||||||
|
TUPLE: shutdown-hook' < holder ;
|
||||||
|
TUPLE: primitive' < holder ;
|
||||||
|
TUPLE: defer' < holder ;
|
||||||
|
TUPLE: symbols' < holder ;
|
||||||
|
TUPLE: symbol' < holder ;
|
||||||
|
TUPLE: slot' < holder ;
|
||||||
|
TUPLE: mixin' < holder ;
|
||||||
|
TUPLE: singletons' < holder ;
|
||||||
|
TUPLE: singleton' < holder ;
|
||||||
|
TUPLE: tuple' < holder ;
|
||||||
|
TUPLE: error' < holder ;
|
||||||
|
TUPLE: builtin' < holder ;
|
||||||
|
TUPLE: predicate' < holder ;
|
||||||
|
TUPLE: union' < holder ;
|
||||||
|
|
||||||
|
! generated definitions
|
||||||
|
TUPLE: define' holder name ;
|
||||||
|
TUPLE: generate-accessor' < define' ;
|
||||||
|
TUPLE: generate-predicate' < define' ;
|
||||||
|
|
||||||
|
: make-holder ( literal class -- obj )
|
||||||
|
new
|
||||||
|
swap >>literal ; inline
|
||||||
|
|
||||||
|
GENERIC: split-decorators ( seq -- base left right )
|
||||||
|
M: compound-literal split-decorators
|
||||||
|
sequence>>
|
||||||
|
[ decorator-literal? not ] partition
|
||||||
|
[ first ] dip
|
||||||
|
[ left-decorator-literal? ] partition ;
|
||||||
|
M: object split-decorators f f ;
|
||||||
|
|
||||||
|
! GENERIC: apply-decorator ( base decorator -- )
|
||||||
|
! : apply-decorators ( obj seq -- obj ) ;
|
||||||
|
|
||||||
|
GENERIC: base-literal ( obj -- obj )
|
||||||
|
M: compound-literal base-literal
|
||||||
|
sequence>> [ decorator-literal? not ] find nip ;
|
||||||
|
M: object base-literal ;
|
||||||
|
|
||||||
|
|
||||||
|
GENERIC: literal>tag ( class -- string/f )
|
||||||
|
M: line-comment-literal literal>tag drop f ;
|
||||||
|
M: uppercase-colon-literal literal>tag
|
||||||
|
tag>> [ "word" ] [ >lower ] if-empty ;
|
||||||
|
M: compound-literal literal>tag
|
||||||
|
base-literal literal>tag ;
|
||||||
|
|
||||||
|
: literal>holder ( literal -- obj )
|
||||||
|
[ ] [
|
||||||
|
literal>tag [ "'" append "modern.compiler" lookup-word ]
|
||||||
|
[ \ comment' ] if*
|
||||||
|
] bi
|
||||||
|
'[ _ make-holder ] call( obj -- obj ) ;
|
||||||
|
|
||||||
|
: literals>holders ( literals -- holders )
|
||||||
|
[ literal>holder ] map ;
|
||||||
|
|
||||||
|
GENERIC: holder>definitions' ( literal -- assoc )
|
||||||
|
M: comment' holder>definitions' drop f ;
|
||||||
|
M: using' holder>definitions' drop f ;
|
||||||
|
M: use' holder>definitions' drop f ;
|
||||||
|
M: in' holder>definitions' drop f ;
|
||||||
|
M: qualified-with' holder>definitions' drop f ;
|
||||||
|
M: qualified' holder>definitions' drop f ;
|
||||||
|
M: script' holder>definitions' drop f ;
|
||||||
|
M: m' holder>definitions' drop f ;
|
||||||
|
M: instance' holder>definitions' drop f ;
|
||||||
|
|
||||||
|
! Single words
|
||||||
|
M: word' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: generic' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: generic#' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: hook' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: math' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: constant' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: c' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: initialize' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: startup-hook' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: shutdown-hook' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: primitive' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
M: defer' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> first tag>> define' boa ;
|
||||||
|
|
||||||
|
! Multiple words
|
||||||
|
M: symbols' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> [ tag>> ] map [ define' boa ] with map ;
|
||||||
|
M: symbol' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> [ tag>> ] map [ define' boa ] with map ;
|
||||||
|
M: slot' holder>definitions'
|
||||||
|
dup literal>> base-literal payload>> [ tag>> ] map
|
||||||
|
[ generate-accessor' boa ] with map ;
|
||||||
|
|
||||||
|
! these also make class predicate? words
|
||||||
|
|
||||||
|
GENERIC: slot-accessor-name ( obj -- string )
|
||||||
|
M: single-matched-literal slot-accessor-name
|
||||||
|
payload>> first tag>> ">>" append ;
|
||||||
|
M: tag-literal slot-accessor-name tag>> ">>" append ;
|
||||||
|
|
||||||
|
M: tuple' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> define' boa ]
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> "?" append generate-predicate' boa ]
|
||||||
|
[
|
||||||
|
dup literal>> base-literal payload>> rest
|
||||||
|
[ slot-accessor-name generate-accessor' boa ] with map
|
||||||
|
] tri [ 2array ] dip append ;
|
||||||
|
|
||||||
|
M: error' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> define' boa ]
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> "?" append generate-predicate' boa ]
|
||||||
|
[
|
||||||
|
dup literal>> base-literal payload>> rest
|
||||||
|
[ slot-accessor-name generate-accessor' boa ] with map
|
||||||
|
] tri [ 2array ] dip append ;
|
||||||
|
|
||||||
|
M: builtin' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> define' boa ]
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> "?" append generate-predicate' boa ] bi 2array ;
|
||||||
|
M: predicate' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> define' boa ]
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> "?" append generate-predicate' boa ] bi 2array ;
|
||||||
|
M: union' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> define' boa ]
|
||||||
|
[ dup literal>> base-literal payload>> first tag>> "?" append generate-predicate' boa ] bi 2array ;
|
||||||
|
|
||||||
|
! Multiple and class predicates
|
||||||
|
M: mixin' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> [ tag>> ] map [ define' boa ] with map ]
|
||||||
|
[ dup literal>> base-literal payload>> [ tag>> "?" append ] map [ generate-predicate' boa ] with map ] bi append ;
|
||||||
|
|
||||||
|
M: singletons' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> [ tag>> ] map [ define' boa ] with map ]
|
||||||
|
[ dup literal>> base-literal payload>> [ tag>> "?" append ] map [ generate-predicate' boa ] with map ] bi append ;
|
||||||
|
|
||||||
|
M: singleton' holder>definitions'
|
||||||
|
[ dup literal>> base-literal payload>> [ tag>> ] map [ define' boa ] with map ]
|
||||||
|
[ dup literal>> base-literal payload>> [ tag>> "?" append ] map [ generate-predicate' boa ] with map ] bi append ;
|
||||||
|
|
||||||
|
: holder>definitions ( obj -- seq )
|
||||||
|
holder>definitions' dup sequence? [ 1array ] unless ;
|
||||||
|
|
||||||
|
: holders>definitions ( holders -- seq )
|
||||||
|
[ holder>definitions ] map concat ;
|
||||||
|
|
||||||
|
|
||||||
|
: holders>using ( holders -- using )
|
||||||
|
[ { [ using'? ] [ use'? ] } 1|| ] filter
|
||||||
|
[ literal>> payload>> [ tag>> ] map ] map concat ;
|
||||||
|
|
||||||
|
: holders>in ( holders -- using )
|
||||||
|
[ in'? ] filter
|
||||||
|
[ literal>> payload>> [ tag>> ] map ] map concat ;
|
||||||
|
|
||||||
|
GENERIC: handle-colon-tag ( seq tag -- obj )
|
||||||
|
GENERIC: handle-paren-tag ( seq tag -- obj )
|
||||||
|
! M: f handle-paren-tag drop <effect> ;
|
||||||
|
GENERIC: handle-brace-tag ( seq tag -- obj )
|
||||||
|
GENERIC: handle-bracket-tag ( seq tag -- obj )
|
||||||
|
GENERIC: handle-string-tag ( seq tag -- obj )
|
||||||
|
|
||||||
|
ERROR: word-not-found word ;
|
||||||
|
: lookup-in-namespace ( key namespace -- obj/f )
|
||||||
|
?at [
|
||||||
|
] [
|
||||||
|
word-not-found
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
GENERIC# lookup-literal 1 ( literal namespace -- obj )
|
||||||
|
|
||||||
|
M: tag-literal lookup-literal
|
||||||
|
[ tag>> ] dip lookup-in-namespace ;
|
||||||
|
|
||||||
|
: lookup-sequence ( seq namespace -- obj )
|
||||||
|
'[ _ lookup-literal ] map ;
|
||||||
|
|
||||||
|
ERROR: unknown-tag tag ;
|
||||||
|
|
||||||
|
ERROR: unknown-single-matched-delimiter sequence tag ch ;
|
||||||
|
M: single-matched-literal lookup-literal
|
||||||
|
[ [ payload>> ] dip lookup-sequence ]
|
||||||
|
[ [ tag>> ] dip over empty? [ 2drop f ] [ lookup-literal ] if ]
|
||||||
|
[ drop delimiter>> ] 2tri
|
||||||
|
{
|
||||||
|
{ "(" [ handle-paren-tag ] }
|
||||||
|
{ "{" [ handle-brace-tag ] }
|
||||||
|
{ "[" [ handle-bracket-tag ] }
|
||||||
|
{ ":" [ handle-colon-tag ] }
|
||||||
|
{ "\"" [ handle-string-tag ] }
|
||||||
|
[ unknown-single-matched-delimiter ]
|
||||||
|
} case ;
|
||||||
|
|
||||||
|
|
||||||
|
GENERIC: definition>quotation ( namespace name definition -- quot )
|
||||||
|
M: define' definition>quotation
|
||||||
|
holder>> definition>quotation
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
! Done by update-classes
|
||||||
|
M: generate-predicate' definition>quotation 3drop f ;
|
||||||
|
|
||||||
|
|
||||||
|
GENERIC: stack-effect? ( obj -- ? )
|
||||||
|
M: single-matched-literal stack-effect? { [ tag>> ] [ delimiter>> "(" = ] } 1&& ;
|
||||||
|
M: object stack-effect? drop f ;
|
||||||
|
|
||||||
|
ERROR: word-expects-stack-effect ;
|
||||||
|
: ensure-stack-effect ( obj -- ? )
|
||||||
|
dup stack-effect? [ word-expects-stack-effect ] unless ;
|
||||||
|
|
||||||
|
ERROR: word-expects-name-effect-body payload ;
|
||||||
|
: name-effect-body ( payload -- name effect body )
|
||||||
|
payload>> dup length 2 < [ word-expects-name-effect-body ] when
|
||||||
|
[ first2 ensure-stack-effect ] [ 2 tail ] bi ;
|
||||||
|
|
||||||
|
: body>quotation ( body namespace -- quot )
|
||||||
|
2drop [ ]
|
||||||
|
;
|
||||||
|
|
||||||
|
M:: word' definition>quotation ( namespace name definition -- quot )
|
||||||
|
definition literal>> base-literal
|
||||||
|
name-effect-body :> ( name' effect body )
|
||||||
|
name
|
||||||
|
body namespace body>quotation
|
||||||
|
effect namespace lookup-literal
|
||||||
|
'[ _ _ _ define-declared ] ;
|
||||||
|
|
||||||
|
M: mixin' definition>quotation
|
||||||
|
! literal>> base-literal payload>> first tag>> >string
|
||||||
|
drop nip '[ _ define-mixin-class ] ;
|
||||||
|
|
||||||
|
M: object definition>quotation
|
||||||
|
3drop [ ] ;
|
||||||
|
|
||||||
|
TUPLE: manifest2 name literals holders definitions definition-assoc namespaces ;
|
||||||
|
|
||||||
|
: <manifest2> ( name literals holders definitions -- manifest2 )
|
||||||
|
manifest2 new
|
||||||
|
swap >>definitions
|
||||||
|
dup definitions>> [ [ name>> ] keep ] { } map>assoc >>definition-assoc
|
||||||
|
swap >>holders
|
||||||
|
swap >>literals
|
||||||
|
swap ".private" ?tail drop >>name ; inline
|
||||||
|
|
||||||
|
: manifest>scoped-words ( manifest -- seq )
|
||||||
|
[ name>> ] [ definition-assoc>> keys ] bi
|
||||||
|
[ ":" glue ] with map ;
|
||||||
|
|
||||||
|
: manifest>own-namespace ( manifest -- namespace )
|
||||||
|
[ definition-assoc>> keys ] [ manifest>scoped-words [ 1array ] map ] bi
|
||||||
|
zip ;
|
||||||
|
|
||||||
|
: manifest>using ( manifest -- seq )
|
||||||
|
holders>> holders>using ;
|
||||||
|
|
||||||
|
DEFER: load-modern
|
||||||
|
: manifest>combined-namespace ( manifest -- namespaces )
|
||||||
|
[ manifest>using [ load-modern manifest>own-namespace ] map sift members H{ } clone [ assoc-union ] reduce ]
|
||||||
|
[ manifest>own-namespace ] bi assoc-union ;
|
||||||
|
|
||||||
|
: manifest>quotation ( manifest -- quot )
|
||||||
|
[ manifest>combined-namespace ] [ definitions>> ] bi
|
||||||
|
[ [ name>> ] [ ] bi definition>quotation ] with { } map-as concat ;
|
||||||
|
|
||||||
|
GENERIC: add-predicates ( obj -- seq )
|
||||||
|
M: string add-predicates dup "?" append 2array ;
|
||||||
|
M: sequence add-predicates [ add-predicates ] map concat ;
|
||||||
|
|
||||||
|
|
||||||
|
: manifest>definitions ( manifest -- namespace )
|
||||||
|
[ name>> ]
|
||||||
|
[ definitions>> [ name>> ] map ] bi
|
||||||
|
[ ":" glue ] with map ;
|
||||||
|
|
||||||
|
: literals>manifest ( name/f literals -- manifest )
|
||||||
|
dup literals>holders
|
||||||
|
dup holders>definitions <manifest2> ;
|
||||||
|
|
||||||
|
: string>manifest ( string -- manifest )
|
||||||
|
string>literals f swap literals>manifest ;
|
||||||
|
|
||||||
|
MEMO: load-modern ( name -- literals )
|
||||||
|
dup vocab>core2-path path>literals
|
||||||
|
literals>manifest ;
|
||||||
|
|
||||||
|
: load-modern-closure ( vocab -- manifests )
|
||||||
|
\ load-modern reset-memoized
|
||||||
|
load-modern [ holders>using [ load-modern ] map ] closure ;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
"sequences" load-modern
|
||||||
|
[ holder>definitions ] map sift
|
||||||
|
[ dup array? [ [ name>> ] map ] [ name>> ] if ] map flatten
|
||||||
|
describe
|
||||||
|
|
||||||
|
|
||||||
|
clear
|
||||||
|
"sequences" load-modern
|
||||||
|
definitions>> [ define'? ] filter
|
||||||
|
[ holder>> word'? ] filter
|
||||||
|
first
|
||||||
|
*/
|
|
@ -0,0 +1,98 @@
|
||||||
|
! Copyright (C) 2016 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors kernel modern sequences strings tools.test ;
|
||||||
|
IN: modern.tests
|
||||||
|
|
||||||
|
{ 0 } [ "" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "a" string>literals length ] unit-test
|
||||||
|
{ 1 } [ " a" string>literals length ] unit-test
|
||||||
|
{ 1 } [ " a " string>literals length ] unit-test
|
||||||
|
{ 3 } [ "a b c" string>literals length ] unit-test
|
||||||
|
|
||||||
|
{ 1 } [ "`abc" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "`abc `cba" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "\"abc\" \"cba\"" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "[[abc]] [[cba]]" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "{{abc}} {{cba}}" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "((abc)) ((cba))" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "[=[abc]=] [=[cba]=]" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "{={abc}=} {={cba}=}" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "(=(abc)=) (=(cba)=)" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "[==[abc]==] [==[cba]==]" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "{=={abc}==} {=={cba}==}" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "(==(abc)==) (==(cba)==)" string>literals length ] unit-test
|
||||||
|
|
||||||
|
{ 1 } [ "hex`abc" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex`abc hex`cba" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex\"abc\" hex\"cba\"" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex[[abc]] hex[[cba]]" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex{{abc}} hex{{cba}}" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex((abc)) hex((cba))" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex[=[abc]=] hex[=[cba]=]" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex{={abc}=} hex{={cba}=}" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex(=(abc)=) hex(=(cba)=)" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex[==[abc]==] hex[==[cba]==]" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex{=={abc}==} hex{=={cba}==}" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "hex(==(abc)==) hex(==(cba)==)" string>literals length ] unit-test
|
||||||
|
|
||||||
|
|
||||||
|
{ 1 } [ "[ ]" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc[ ]" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc[ 1 ]" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc[ 1 abc]" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "{ }" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc{ }" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc{ 1 }" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc{ 1 abc}" string>literals length ] unit-test
|
||||||
|
|
||||||
|
{ 1 } [ "( )" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc( )" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc( 1 )" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "abc( 1 abc)" string>literals length ] unit-test
|
||||||
|
|
||||||
|
[ "A{ B}" string>literals ] must-fail
|
||||||
|
[ "A( B)" string>literals ] must-fail
|
||||||
|
[ "A[ B]" string>literals ] must-fail
|
||||||
|
[ "A: B;" string>literals ] must-fail
|
||||||
|
[ "A: AA;" string>literals ] must-fail
|
||||||
|
[ "A: B{ C} A;" string>literals ] must-fail
|
||||||
|
|
||||||
|
{ 1 } [ "!omg" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "! omg" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "![[omg]]" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "![[
|
||||||
|
omg]]" string>literals length
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ 1 } [ "\\ a" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "\\ \\" string>literals length ] unit-test
|
||||||
|
{ 1 } [ " \\ abcd " string>literals length ] unit-test
|
||||||
|
|
||||||
|
{ "omg" } [ "!omg" string>literals first payload>> >string ] unit-test
|
||||||
|
|
||||||
|
! Comment character should be #, and should not be allowed in word names
|
||||||
|
! For now, we have exclamation as comment character and words
|
||||||
|
! like suffix! which aren't allowed to start comments
|
||||||
|
{ 2 } [ "a!omg lol" string>literals length ] unit-test
|
||||||
|
{ 3 } [ "a! omg lol" string>literals length ] unit-test
|
||||||
|
{ 2 } [ "a![[omg]] lol" string>literals length ] unit-test
|
||||||
|
|
||||||
|
{ t } [ "[ ][ ][ ]" string>literals length 1 = ] unit-test
|
||||||
|
{ t } [ "[ ][ ][ ]" string>literals first compound-literal? ] unit-test
|
||||||
|
{ t } [ "[ ][ ][ ]" string>literals first sequence>> length 3 = ] unit-test
|
||||||
|
|
||||||
|
! This is broken.
|
||||||
|
! hex[[abc]] -> hex#[[abc]] ! commented out hex literal!
|
||||||
|
! $hex[[abc${0}]] ! interpolate
|
||||||
|
! { 2 } [ "a![[
|
||||||
|
! omg]] lol" string>literals length
|
||||||
|
! ] unit-test
|
||||||
|
|
||||||
|
|
||||||
|
{ 1 } [ "a@ b@ hi @c @d" string>literals length ] unit-test
|
||||||
|
|
||||||
|
{ 1 } [ "{ 1 }@ { 2 }@ hi @{ 3 } @{ 4 }" string>literals length ] unit-test
|
||||||
|
|
||||||
|
|
||||||
|
{ 1 } [ ":foo" string>literals length ] unit-test
|
||||||
|
{ 1 } [ "( :integer )" string>literals length ] unit-test
|
|
@ -0,0 +1,469 @@
|
||||||
|
! Copyright (C) 2016 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors arrays assocs assocs.extras combinators
|
||||||
|
combinators.short-circuit constructors continuations fry
|
||||||
|
io.encodings.utf8 io.files kernel locals macros make math
|
||||||
|
math.order modern.paths modern.slices multiline namespaces
|
||||||
|
quotations sequences sequences.extras splitting
|
||||||
|
splitting.monotonic strings unicode ;
|
||||||
|
IN: modern
|
||||||
|
|
||||||
|
<<
|
||||||
|
! Base rules, everything should have a generator macro
|
||||||
|
TUPLE: lexer generator ;
|
||||||
|
|
||||||
|
! Declarative rules, add more!
|
||||||
|
TUPLE: tag-lexer < lexer ; ! default, if nothing else matches, add one with regexp for c-style names etc
|
||||||
|
TUPLE: dquote-lexer < lexer delimiter escape ignore-whitespace? ; ! ``close`` slot someday to allow ` '
|
||||||
|
TUPLE: matched-lexer < lexer delimiter double-char ; ! ``close`` slot someday, to allow `` ''
|
||||||
|
TUPLE: backtick-lexer < lexer delimiter ;
|
||||||
|
TUPLE: backslash-lexer < lexer delimiter payload-exception? ; ! payload-exception is \n words
|
||||||
|
TUPLE: line-comment-lexer < lexer delimiter word-name-exception? ; ! escape-newline-exception? (like C)
|
||||||
|
TUPLE: colon-lexer < lexer delimiter ;
|
||||||
|
TUPLE: semicolon-lexer < lexer delimiter ; ! ; inline foldable
|
||||||
|
TUPLE: whitespace-lexer < lexer delimiter ; ! \s \r \n \t?
|
||||||
|
TUPLE: terminator-lexer < lexer delimiter ;
|
||||||
|
TUPLE: decorator-lexer < lexer delimiter ;
|
||||||
|
|
||||||
|
! Base lexer result
|
||||||
|
TUPLE: literal underlying seq lexer left-decorators right-decorators ;
|
||||||
|
TUPLE: tag-literal < literal tag ;
|
||||||
|
TUPLE: matched-literal < tag-literal delimiter payload closing-tag ;
|
||||||
|
TUPLE: delimited-literal < tag-literal delimiter payload ;
|
||||||
|
TUPLE: decorator-literal < literal delimiter payload ;
|
||||||
|
|
||||||
|
TUPLE: dquote-literal < delimited-literal ;
|
||||||
|
TUPLE: single-matched-literal < matched-literal ;
|
||||||
|
TUPLE: double-matched-literal < matched-literal ;
|
||||||
|
TUPLE: uppercase-colon-literal < single-matched-literal ;
|
||||||
|
TUPLE: lowercase-colon-literal < delimited-literal ;
|
||||||
|
! TUPLE: standalone-colon-literal < delimited-literal ; ! :foo
|
||||||
|
TUPLE: backtick-literal < delimited-literal ;
|
||||||
|
TUPLE: backslash-literal < delimited-literal ;
|
||||||
|
TUPLE: semicolon-literal < delimited-literal ;
|
||||||
|
TUPLE: line-comment-literal < delimited-literal ;
|
||||||
|
TUPLE: terminator-literal < tag-literal ;
|
||||||
|
TUPLE: whitespace-literal < tag-literal ;
|
||||||
|
|
||||||
|
TUPLE: left-decorator-literal < decorator-literal ;
|
||||||
|
TUPLE: right-decorator-literal < decorator-literal ;
|
||||||
|
|
||||||
|
TUPLE: compound-sequence-literal sequence ;
|
||||||
|
CONSTRUCTOR: <compound-sequence-literal> compound-sequence-literal ( sequence -- obj ) ;
|
||||||
|
>>
|
||||||
|
|
||||||
|
GENERIC: lexed-underlying ( obj -- slice )
|
||||||
|
M: f lexed-underlying ;
|
||||||
|
M: object lexed-underlying underlying>> ;
|
||||||
|
M: slice lexed-underlying ;
|
||||||
|
|
||||||
|
TUPLE: compound-literal sequence ;
|
||||||
|
CONSTRUCTOR: <compound-literal> compound-literal ( sequence -- obj ) ;
|
||||||
|
|
||||||
|
! Ensure that we only have one decorated thing in a compound-literal
|
||||||
|
ERROR: bad-compound-literal seq decorators words ;
|
||||||
|
: check-compound-literal ( seq -- seq ) ;
|
||||||
|
|
||||||
|
GENERIC: make-compound-literals ( seq -- seq' )
|
||||||
|
M: object make-compound-literals ;
|
||||||
|
M: array make-compound-literals
|
||||||
|
[
|
||||||
|
{
|
||||||
|
[ [ lexed-underlying ] bi@ slices-touch? ]
|
||||||
|
[ [ ] [ left-decorator-literal? ] bi* and ]
|
||||||
|
[ [ right-decorator-literal? ] [ ] bi* and ]
|
||||||
|
} 2||
|
||||||
|
] monotonic-split
|
||||||
|
[ dup length 1 > [ <compound-literal> ] [ first ] if ] map ;
|
||||||
|
|
||||||
|
! We have empty decorators, just the @ right here
|
||||||
|
! wrap the decorated object in the payload slot
|
||||||
|
GENERIC: collapse-decorators ( seq -- seq' )
|
||||||
|
M: object collapse-decorators ;
|
||||||
|
M: array collapse-decorators
|
||||||
|
[
|
||||||
|
{
|
||||||
|
[ [ left-decorator-literal? ] [ ] bi* and ]
|
||||||
|
[ [ ] [ right-decorator-literal? ] bi* and ]
|
||||||
|
} 2||
|
||||||
|
] monotonic-split
|
||||||
|
[
|
||||||
|
dup length 1 > [
|
||||||
|
first2
|
||||||
|
2dup [ left-decorator-literal? ] [ ] bi* and [
|
||||||
|
>>payload
|
||||||
|
] [
|
||||||
|
[ payload<< ] keep
|
||||||
|
] if
|
||||||
|
] [
|
||||||
|
first
|
||||||
|
] if
|
||||||
|
] map ;
|
||||||
|
|
||||||
|
: split-double-dash ( seq -- seqs )
|
||||||
|
dup [ { [ tag-literal? ] [ tag>> "--" = ] } 1&& ] split-when
|
||||||
|
dup length 1 > [
|
||||||
|
nip <compound-sequence-literal>
|
||||||
|
] [
|
||||||
|
drop
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: postprocess-lexed ( seq -- seq' )
|
||||||
|
collapse-decorators make-compound-literals ;
|
||||||
|
|
||||||
|
|
||||||
|
ERROR: whitespace-expected-after n string ch ;
|
||||||
|
ERROR: expected-more-tokens n string expected ;
|
||||||
|
ERROR: string-expected-got-eof n string ;
|
||||||
|
|
||||||
|
:: make-tag-literal ( tag -- literal )
|
||||||
|
tag-literal new
|
||||||
|
tag >string >>tag
|
||||||
|
tag >>underlying
|
||||||
|
tag 1array >>seq ; inline
|
||||||
|
|
||||||
|
:: make-tag-class-literal ( tag class -- literal )
|
||||||
|
class new
|
||||||
|
tag >string >>tag
|
||||||
|
tag >>underlying
|
||||||
|
tag 1array >>seq ; inline
|
||||||
|
|
||||||
|
:: make-tag-payload-literal ( payload last tag class -- literal )
|
||||||
|
class new
|
||||||
|
tag >string >>tag
|
||||||
|
payload >string >>payload
|
||||||
|
tag last [ dup tag-literal? [ lexed-underlying ] when ] bi@ ?span-slices >>underlying
|
||||||
|
tag payload 2array >>seq ; inline
|
||||||
|
|
||||||
|
:: make-delimited-literal ( payload last tag delimiter class -- literal )
|
||||||
|
class new
|
||||||
|
tag >string >>tag
|
||||||
|
payload dup slice? [ >string ] when >>payload
|
||||||
|
tag last [ dup tag-literal? [ lexed-underlying ] when ] bi@ ?span-slices >>underlying
|
||||||
|
delimiter >string >>delimiter
|
||||||
|
tag delimiter payload 3array >>seq ; inline
|
||||||
|
|
||||||
|
ERROR: mismatched-closing opening closing ;
|
||||||
|
:: make-matched-literal ( payload closing tag opening-delimiter class -- literal )
|
||||||
|
class new
|
||||||
|
tag >string >>tag
|
||||||
|
payload postprocess-lexed opening-delimiter "\"" = [ split-double-dash ] unless >>payload
|
||||||
|
tag closing [ dup tag-literal? [ lexed-underlying ] when ] bi@ ?span-slices >>underlying
|
||||||
|
opening-delimiter >string >>delimiter
|
||||||
|
dup single-matched-literal? [
|
||||||
|
closing tag>> length 1 > [
|
||||||
|
tag opening-delimiter append
|
||||||
|
matching-delimiter-string closing tag>> sequence= [ opening-delimiter closing tag>> mismatched-closing ] unless
|
||||||
|
] when
|
||||||
|
closing tag>> >>closing-tag
|
||||||
|
] when
|
||||||
|
tag opening-delimiter payload closing 4array >>seq ; inline
|
||||||
|
|
||||||
|
:: make-decorator-literal ( payload delimiter class -- literal )
|
||||||
|
class new
|
||||||
|
delimiter >>delimiter
|
||||||
|
payload >>payload
|
||||||
|
payload delimiter [ lexed-underlying ] bi@ ?span-slices >>underlying
|
||||||
|
class left-decorator-literal = [
|
||||||
|
delimiter payload 2array
|
||||||
|
] [
|
||||||
|
payload delimiter 2array
|
||||||
|
] if >>seq ; inline
|
||||||
|
|
||||||
|
:: make-decorator-sentinel ( delimiter left? -- literal )
|
||||||
|
left? left-decorator-literal right-decorator-literal ? new
|
||||||
|
delimiter >>delimiter
|
||||||
|
delimiter 1array >>seq
|
||||||
|
delimiter >>underlying ; inline
|
||||||
|
|
||||||
|
ERROR: long-opening-mismatch tag open n string ch ;
|
||||||
|
|
||||||
|
! (( )) [[ ]] {{ }}
|
||||||
|
MACRO:: read-double-matched ( open-ch -- quot: ( n string tag ch -- n' string seq ) )
|
||||||
|
open-ch dup matching-delimiter {
|
||||||
|
[ drop 2 swap <string> ]
|
||||||
|
[ drop 1string ]
|
||||||
|
[ nip 2 swap <string> ]
|
||||||
|
} 2cleave :> ( openstr2 openstr1 closestr2 )
|
||||||
|
[| n string tag! ch |
|
||||||
|
ch {
|
||||||
|
{ CHAR: = [
|
||||||
|
n string openstr1 slice-til-separator-inclusive [ -1 modify-from ] dip :> ( n' string' opening ch )
|
||||||
|
ch open-ch = [ tag openstr2 n string ch long-opening-mismatch ] unless
|
||||||
|
opening matching-delimiter-string :> needle
|
||||||
|
|
||||||
|
n' string' needle slice-til-string :> ( n'' string'' payload closing )
|
||||||
|
n'' string
|
||||||
|
payload closing tag opening double-matched-literal make-matched-literal
|
||||||
|
] }
|
||||||
|
{ open-ch [
|
||||||
|
tag 1 cut-slice* swap tag! 1 modify-to :> opening
|
||||||
|
n 1 + string closestr2 slice-til-string :> ( n' string' payload closing )
|
||||||
|
n' string
|
||||||
|
payload closing tag opening double-matched-literal make-matched-literal
|
||||||
|
] }
|
||||||
|
[ [ tag openstr2 n string ] dip long-opening-mismatch ]
|
||||||
|
} case
|
||||||
|
] ;
|
||||||
|
|
||||||
|
: read-double-matched-paren ( n string tag ch -- n' string seq ) CHAR: ( read-double-matched ;
|
||||||
|
: read-double-matched-bracket ( n string tag ch -- n' string seq ) CHAR: [ read-double-matched ;
|
||||||
|
: read-double-matched-brace ( n string tag ch -- n' string seq ) CHAR: { read-double-matched ;
|
||||||
|
|
||||||
|
DEFER: lex
|
||||||
|
DEFER: lex-factor
|
||||||
|
ERROR: lex-expected-but-got-eof n string expected ;
|
||||||
|
! For implementing [ { (
|
||||||
|
: lex-until ( n string tags -- n' string payload closing )
|
||||||
|
pick [
|
||||||
|
3dup '[
|
||||||
|
[
|
||||||
|
lex-factor dup , [
|
||||||
|
dup tag-literal? [
|
||||||
|
! } gets a chance, but then also full seq { } after recursion...
|
||||||
|
[ _ ] dip underlying>> '[ _ sequence= ] any? not
|
||||||
|
] [
|
||||||
|
drop t ! loop again?
|
||||||
|
] if
|
||||||
|
] [
|
||||||
|
_ _ _ lex-expected-but-got-eof
|
||||||
|
] if*
|
||||||
|
] loop
|
||||||
|
] { } make unclip-last
|
||||||
|
] [
|
||||||
|
lex-expected-but-got-eof
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
MACRO:: read-matched ( ch -- quot: ( n string tag -- n' string slice' ) )
|
||||||
|
ch dup matching-delimiter {
|
||||||
|
[ drop "=" swap prefix ]
|
||||||
|
[ nip 1string ]
|
||||||
|
} 2cleave :> ( openstreq closestr1 ) ! [= ]
|
||||||
|
[| n string tag |
|
||||||
|
n string tag
|
||||||
|
2over nth-check-eof {
|
||||||
|
{ [ dup openstreq member? ] [ ch read-double-matched ] } ! (=( or ((
|
||||||
|
{ [ dup blank? ] [ drop dup '[ _ matching-delimiter-string closestr1 2array lex-until ] dip 1 cut-slice* single-matched-literal make-matched-literal ] } ! ( foo )
|
||||||
|
[ drop [ slice-til-whitespace drop ] dip span-slices make-tag-literal ] ! (foo)
|
||||||
|
} cond
|
||||||
|
] ;
|
||||||
|
|
||||||
|
: read-bracket ( n string slice -- n' string slice' ) CHAR: [ read-matched ;
|
||||||
|
: read-brace ( n string slice -- n' string slice' ) CHAR: { read-matched ;
|
||||||
|
: read-paren ( n string slice -- n' string slice' ) CHAR: ( read-matched ;
|
||||||
|
|
||||||
|
: read-backtick ( n string opening -- n' string obj )
|
||||||
|
[
|
||||||
|
slice-til-whitespace drop
|
||||||
|
dup
|
||||||
|
] dip 1 cut-slice* backtick-literal make-delimited-literal ;
|
||||||
|
|
||||||
|
: read-string-payload ( n string -- n' string )
|
||||||
|
over [
|
||||||
|
{ CHAR: \ CHAR: " } slice-til-separator-inclusive {
|
||||||
|
{ f [ drop ] }
|
||||||
|
{ CHAR: " [ drop ] }
|
||||||
|
{ CHAR: \ [ drop next-char-from drop read-string-payload ] }
|
||||||
|
} case
|
||||||
|
] [
|
||||||
|
string-expected-got-eof
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
:: read-string ( n string tag -- n' string seq )
|
||||||
|
n string read-string-payload drop :> n'
|
||||||
|
n' string
|
||||||
|
n' [ n string string-expected-got-eof ] unless
|
||||||
|
n n' 1 - string <slice>
|
||||||
|
n' 1 - n' string <slice>
|
||||||
|
tag 1 cut-slice* dquote-literal make-matched-literal ;
|
||||||
|
|
||||||
|
: take-comment ( n string slice -- n' string comment )
|
||||||
|
2over ?nth CHAR: [ = [
|
||||||
|
[ 1 + ] 2dip 2over ?nth read-double-matched-bracket
|
||||||
|
] [
|
||||||
|
[ slice-til-eol drop dup ] dip 1 cut-slice* line-comment-literal make-delimited-literal
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: read-til-semicolon ( n string slice -- n' string semi )
|
||||||
|
dup '[ but-last ";" append ";" 2array lex-until ] dip
|
||||||
|
1 cut-slice* uppercase-colon-literal make-matched-literal ;
|
||||||
|
|
||||||
|
: read-word-or-til-semicolon ( n string slice -- n' string obj )
|
||||||
|
2over next-char-from* "\s\r\n" member? [
|
||||||
|
read-til-semicolon
|
||||||
|
] [
|
||||||
|
merge-slice-til-whitespace make-tag-literal
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: read-lowercase-colon ( n string slice -- n' string lowercase-colon )
|
||||||
|
[ lex-factor dup ] dip 1 cut-slice*
|
||||||
|
lowercase-colon-literal make-delimited-literal ;
|
||||||
|
|
||||||
|
: strict-upper? ( string -- ? )
|
||||||
|
[ { [ CHAR: A CHAR: Z between? ] [ "#:-" member? ] } 1|| ] all? ;
|
||||||
|
|
||||||
|
ERROR: colon-word-must-be-all-uppercase-or-lowercase n string word ;
|
||||||
|
: read-colon ( n string slice -- n' string colon )
|
||||||
|
dup length 1 = [
|
||||||
|
dup prev-char-from-slice { CHAR: \s CHAR: \r CHAR: \n f } member? [
|
||||||
|
dup next-char-from-slice { CHAR: \s CHAR: \r CHAR: \n f } member? [
|
||||||
|
read-til-semicolon
|
||||||
|
] [
|
||||||
|
merge-slice-til-whitespace make-tag-literal
|
||||||
|
] if
|
||||||
|
] [
|
||||||
|
read-lowercase-colon
|
||||||
|
] if
|
||||||
|
] [
|
||||||
|
{
|
||||||
|
{ [ dup strict-upper? ] [ read-til-semicolon ] }
|
||||||
|
[ read-lowercase-colon ]
|
||||||
|
} cond
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
! Words like append! and suffix! are allowed for now.
|
||||||
|
: read-exclamation ( n string slice -- n' string obj )
|
||||||
|
dup { [ "!" sequence= ] [ "#!" sequence= ] } 1||
|
||||||
|
[ take-comment ] [ merge-slice-til-whitespace make-tag-literal ] if ;
|
||||||
|
|
||||||
|
ERROR: backslash-expects-whitespace slice ;
|
||||||
|
: read-backslash ( n string slice -- n' string obj )
|
||||||
|
2over peek-from blank? [
|
||||||
|
! \ foo, M\ foo
|
||||||
|
[ skip-blank-from slice-til-whitespace drop dup ] dip 1 cut-slice* backslash-literal make-delimited-literal
|
||||||
|
] [
|
||||||
|
! M\N
|
||||||
|
merge-slice-til-whitespace make-tag-literal
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
! If the slice is 0 width, we stopped on whitespace.
|
||||||
|
! Advance the index and read again!
|
||||||
|
: read-token-or-whitespace ( n string slice -- n' string slice )
|
||||||
|
dup length 0 =
|
||||||
|
[ drop [ 1 + ] dip lex-factor ]
|
||||||
|
[ make-tag-literal ] if ;
|
||||||
|
|
||||||
|
ERROR: mismatched-terminator n string slice ;
|
||||||
|
: read-terminator ( n string slice -- n' string slice )
|
||||||
|
terminator-literal make-tag-class-literal ;
|
||||||
|
|
||||||
|
: ?blank? ( ch/f -- blank/f )
|
||||||
|
{ [ blank? ] [ f = ] } 1|| ;
|
||||||
|
|
||||||
|
<PRIVATE
|
||||||
|
! work on underlying, index is on the @
|
||||||
|
! @foo
|
||||||
|
: left-decorator? ( obj -- ? )
|
||||||
|
{
|
||||||
|
[ char-before-slice ?blank? ]
|
||||||
|
[ next-char-from-slice ?blank? not ]
|
||||||
|
} 1&& ;
|
||||||
|
|
||||||
|
! foo@
|
||||||
|
: right-decorator? ( slice -- ? )
|
||||||
|
{
|
||||||
|
[ prev-char-from-slice-end ?blank? not ]
|
||||||
|
[ next-char-from-slice ?blank? ]
|
||||||
|
} 1&& ;
|
||||||
|
|
||||||
|
PRIVATE>
|
||||||
|
|
||||||
|
: read-decorator ( n string slice -- n' string obj )
|
||||||
|
{
|
||||||
|
{ [ dup left-decorator? ] [ t make-decorator-sentinel ] }
|
||||||
|
{ [ dup right-decorator? ] [
|
||||||
|
dup length 1 > [
|
||||||
|
[ -1 + ] 2dip
|
||||||
|
-1 modify-to make-tag-literal
|
||||||
|
] [
|
||||||
|
f make-decorator-sentinel
|
||||||
|
] if ] }
|
||||||
|
[ make-tag-literal ]
|
||||||
|
} cond ;
|
||||||
|
|
||||||
|
SYMBOL: lexing-delimiters
|
||||||
|
|
||||||
|
: add-lexing-delimiter ( rule -- )
|
||||||
|
[ ] [ delimiter>> ] bi lexing-delimiters get set-once-at ;
|
||||||
|
|
||||||
|
<<
|
||||||
|
: lexer-rules>hashtable ( seq -- obj )
|
||||||
|
H{ } clone lexing-delimiters [
|
||||||
|
[ add-lexing-delimiter ] each
|
||||||
|
lexing-delimiters get
|
||||||
|
] with-variable ;
|
||||||
|
|
||||||
|
: lexer-rules>delimiters ( seq -- string )
|
||||||
|
[ delimiter>> ] "" map-as ;
|
||||||
|
|
||||||
|
: lexer-rules>assoc ( seq -- seq' )
|
||||||
|
[ [ delimiter>> ] [ generator>> 1quotation ] bi ] { } map>assoc ;
|
||||||
|
>>
|
||||||
|
|
||||||
|
MACRO: rules>call-lexer ( seq -- quot: ( n/f string -- n'/f string literal ) )
|
||||||
|
[ lexer-rules>delimiters ]
|
||||||
|
[
|
||||||
|
lexer-rules>assoc
|
||||||
|
{ f [ f like dup [ make-tag-literal ] when ] } suffix
|
||||||
|
] bi
|
||||||
|
'[ _ slice-til-either _ case ] ;
|
||||||
|
|
||||||
|
CONSTANT: factor-lexing-rules {
|
||||||
|
T{ line-comment-lexer { generator read-exclamation } { delimiter CHAR: ! } }
|
||||||
|
T{ backtick-lexer { generator read-backtick } { delimiter CHAR: ` } }
|
||||||
|
T{ backslash-lexer { generator read-backslash } { delimiter CHAR: \ } }
|
||||||
|
T{ dquote-lexer { generator read-string } { delimiter CHAR: " } { escape CHAR: \ } }
|
||||||
|
T{ decorator-lexer { generator read-decorator } { delimiter CHAR: @ } }
|
||||||
|
|
||||||
|
T{ colon-lexer { generator read-colon } { delimiter CHAR: : } }
|
||||||
|
T{ matched-lexer { generator read-bracket } { delimiter CHAR: [ } }
|
||||||
|
T{ matched-lexer { generator read-brace } { delimiter CHAR: { } }
|
||||||
|
T{ matched-lexer { generator read-paren } { delimiter CHAR: ( } }
|
||||||
|
|
||||||
|
T{ terminator-lexer { generator read-terminator } { delimiter CHAR: ; } }
|
||||||
|
T{ terminator-lexer { generator read-terminator } { delimiter CHAR: ] } }
|
||||||
|
T{ terminator-lexer { generator read-terminator } { delimiter CHAR: } } }
|
||||||
|
T{ terminator-lexer { generator read-terminator } { delimiter CHAR: ) } }
|
||||||
|
|
||||||
|
T{ whitespace-lexer { generator read-token-or-whitespace } { delimiter CHAR: \s } }
|
||||||
|
T{ whitespace-lexer { generator read-token-or-whitespace } { delimiter CHAR: \r } }
|
||||||
|
T{ whitespace-lexer { generator read-token-or-whitespace } { delimiter CHAR: \n } }
|
||||||
|
}
|
||||||
|
|
||||||
|
: lex-factor ( n/f string -- n'/f string literal )
|
||||||
|
factor-lexing-rules rules>call-lexer ;
|
||||||
|
|
||||||
|
: string>literals ( string -- sequence )
|
||||||
|
[ 0 ] dip [ lex-factor ] loop>array 2nip postprocess-lexed ;
|
||||||
|
|
||||||
|
: vocab>literals ( vocab -- sequence )
|
||||||
|
".private" ?tail drop
|
||||||
|
modern-source-path utf8 file-contents string>literals ;
|
||||||
|
|
||||||
|
: path>literals ( path -- sequence )
|
||||||
|
utf8 file-contents string>literals ;
|
||||||
|
|
||||||
|
: lex-core ( -- assoc )
|
||||||
|
core-bootstrap-vocabs [ [ vocab>literals ] [ nip ] recover ] map-zip ;
|
||||||
|
|
||||||
|
: filter-lex-errors ( assoc -- assoc' )
|
||||||
|
[ nip array? not ] assoc-filter ;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
! What a lexer body looks like, produced by make-lexer
|
||||||
|
: lex ( n/f string -- n'/f string literal )
|
||||||
|
"!`\\\"[{(\s\r\n" slice-til-either {
|
||||||
|
{ CHAR: ! [ read-exclamation ] }
|
||||||
|
{ CHAR: ` [ read-backtick ] }
|
||||||
|
{ CHAR: \ [ read-backslash ] }
|
||||||
|
{ CHAR: " [ read-string ] }
|
||||||
|
{ CHAR: [ [ read-bracket ] }
|
||||||
|
{ CHAR: { [ read-brace ] }
|
||||||
|
{ CHAR: ( [ read-paren ] }
|
||||||
|
{ CHAR: \s [ read-token-or-whitespace ] }
|
||||||
|
{ CHAR: \r [ read-token-or-whitespace ] }
|
||||||
|
{ CHAR: \n [ read-token-or-whitespace ] }
|
||||||
|
{ f [ f like dup [ make-tag-literal ] when ] }
|
||||||
|
} case ; inline
|
||||||
|
*/
|
|
@ -0,0 +1 @@
|
||||||
|
Doug Coleman
|
|
@ -0,0 +1,56 @@
|
||||||
|
! Copyright (C) 2016 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors combinators.short-circuit kernel modern
|
||||||
|
modern.out sequences tools.test multiline ;
|
||||||
|
IN: modern.out.tests
|
||||||
|
|
||||||
|
: rewrite-same-string ( string -- ? )
|
||||||
|
[ [ ] rewrite-string ] keep sequence= ;
|
||||||
|
|
||||||
|
: rename-backtick-delimiter ( string -- string' )
|
||||||
|
[
|
||||||
|
dup backtick-literal? [ [ drop "^" ] change-delimiter ] when
|
||||||
|
] rewrite-string ;
|
||||||
|
|
||||||
|
: rename-backslash-delimiter ( string -- string' )
|
||||||
|
[
|
||||||
|
dup backslash-literal? [ [ drop "^" ] change-delimiter ] when
|
||||||
|
] rewrite-string ;
|
||||||
|
|
||||||
|
{ t } [ "fixnum`33 ch`@" rewrite-same-string ] unit-test
|
||||||
|
{ t } [ "! omg" rewrite-same-string ] unit-test
|
||||||
|
{ t } [ "todo! omg" rewrite-same-string ] unit-test
|
||||||
|
{ t } [ "foo[ bar{ baz( ) } ]" rewrite-same-string ] unit-test
|
||||||
|
|
||||||
|
{ t } [ " ARRAY: ;" rewrite-same-string ] unit-test
|
||||||
|
{ t } [ " ARRAY: 1 ;{ inline }" rewrite-same-string ] unit-test
|
||||||
|
{ t } [ " ARRAY: 1 ;[ 0 ]" rewrite-same-string ] unit-test
|
||||||
|
|
||||||
|
{ t } [ " abc{ 1 2 3 abc}" rewrite-same-string ] unit-test
|
||||||
|
{ t } [ " ABC: abc{ 1 2 3 abc} ABC;" rewrite-same-string ] unit-test
|
||||||
|
{ t } [ " a{ a{ a{ a} } a}" rewrite-same-string ] unit-test
|
||||||
|
|
||||||
|
! Funky spaced decorator test
|
||||||
|
{ t } [
|
||||||
|
" lol@ { 1 }@ { 2 }@ hi @{ 3 } @{ 4 } @inline" rewrite-same-string
|
||||||
|
] unit-test
|
||||||
|
! Disable these for now.
|
||||||
|
! { t } [ " array: 1" rewrite-same-string ] unit-test
|
||||||
|
! { t } [ " { array: 1 array: 2 }" rewrite-same-string ] unit-test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{ "fixnum^33 ch^@" } [ "fixnum`33 ch`@" rename-backtick-delimiter ] unit-test
|
||||||
|
|
||||||
|
{ "^ foo ^ bar" } [ "\\ foo \\ bar" rename-backslash-delimiter ] unit-test
|
||||||
|
|
||||||
|
/*
|
||||||
|
{ ": asdf < '< > > ;" } [
|
||||||
|
": asdf [ '[ ] ] ;" [
|
||||||
|
dup { [ single-matched-literal? ] [ delimiter>> "[" = ] } 1&&
|
||||||
|
[ [ drop "<" ] change-delimiter ] when
|
||||||
|
] rewrite-string
|
||||||
|
] unit-test
|
||||||
|
*/
|
||||||
|
|
||||||
|
! lexable-paths [ transform-single-line-comment>hash-comment ] rewrite-paths
|
|
@ -0,0 +1,311 @@
|
||||||
|
! Copyright (C) 2016 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors combinators combinators.short-circuit
|
||||||
|
combinators.smart continuations fry io io.encodings.utf8
|
||||||
|
io.files io.streams.string kernel modern modern.paths
|
||||||
|
modern.slices multiline namespaces prettyprint sequences sets
|
||||||
|
splitting strings arrays ;
|
||||||
|
IN: modern.out
|
||||||
|
|
||||||
|
SYMBOL: last-slice
|
||||||
|
|
||||||
|
: write-whitespace ( obj -- )
|
||||||
|
[ last-slice get [ swap slice-between ] [ slice-before ] if* io:write ]
|
||||||
|
[ last-slice namespaces:set ] bi ;
|
||||||
|
|
||||||
|
DEFER: write-literal
|
||||||
|
GENERIC: write-literal ( obj -- )
|
||||||
|
! M: object write-literal lexed-underlying write ;
|
||||||
|
M: string write-literal write ;
|
||||||
|
M: slice write-literal [ write-whitespace ] [ write ] bi ;
|
||||||
|
|
||||||
|
M: array write-literal [ write-literal ] each ;
|
||||||
|
|
||||||
|
M: tag-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: single-matched-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> write ]
|
||||||
|
[ payload>> [ write-literal ] each ] ! don't need write-whitespace here, the recursion does it
|
||||||
|
[ seq>> 3 swap nth lexed-underlying write-whitespace ]
|
||||||
|
[ closing-tag>> write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: double-matched-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> io:write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
[ seq>> 2 swap nth write-whitespace ]
|
||||||
|
[ payload>> io:write ]
|
||||||
|
[ seq>> 3 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> matching-delimiter-string io:write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: dquote-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> io:write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
[ seq>> 2 swap nth write-whitespace ]
|
||||||
|
[ payload>> io:write ]
|
||||||
|
[ seq>> 3 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> matching-delimiter-string io:write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: backtick-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> io:write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
[ seq>> 2 swap nth write-whitespace ]
|
||||||
|
[ payload>> io:write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: backslash-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> io:write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
[ seq>> 2 swap nth write-whitespace ]
|
||||||
|
[ payload>> io:write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: line-comment-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> io:write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
[ seq>> 2 swap nth write-whitespace ]
|
||||||
|
[ payload>> io:write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: uppercase-colon-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> write ]
|
||||||
|
[ payload>> [ write-literal ] each ] ! don't need write-whitespace here, the recursion does it
|
||||||
|
[ seq>> 3 swap nth lexed-underlying write-whitespace ]
|
||||||
|
[ closing-tag>> write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: lowercase-colon-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ tag>> io:write ]
|
||||||
|
[ seq>> 1 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
[ payload>> write-literal ] ! don't need write-whitespace here, the recursion does it
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: left-decorator-literal write-literal
|
||||||
|
{
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
[ payload>> write-literal ] ! don't need write-whitespace here, the recursion does it
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: right-decorator-literal write-literal
|
||||||
|
{
|
||||||
|
[ payload>> write-literal ] ! don't need write-whitespace here, the recursion does it
|
||||||
|
[ seq>> 0 swap nth write-whitespace ]
|
||||||
|
[ delimiter>> io:write ]
|
||||||
|
} cleave ;
|
||||||
|
|
||||||
|
M: compound-literal write-literal
|
||||||
|
sequence>> [ write-literal ] each ;
|
||||||
|
|
||||||
|
M: compound-sequence-literal write-literal
|
||||||
|
sequence>> [ write-literal ] each ;
|
||||||
|
|
||||||
|
! Swap in write-literal for renaming
|
||||||
|
|
||||||
|
: write-modern-loop ( quot -- )
|
||||||
|
[ write-literal ] each ; inline
|
||||||
|
|
||||||
|
: write-modern-string ( seq -- string )
|
||||||
|
[ write-modern-loop ] with-string-writer ; inline
|
||||||
|
|
||||||
|
: write-modern-path ( seq path -- )
|
||||||
|
utf8 [ write-modern-loop nl ] with-file-writer ; inline
|
||||||
|
|
||||||
|
: map-literals ( obj quot: ( obj -- obj' ) -- seq )
|
||||||
|
over single-matched-literal? [
|
||||||
|
[ call drop ] [
|
||||||
|
'[
|
||||||
|
dup compound-sequence-literal? [ sequence>> ] when
|
||||||
|
[ _ map-literals ] map
|
||||||
|
] change-payload
|
||||||
|
] 2bi
|
||||||
|
] [
|
||||||
|
call
|
||||||
|
] if ; inline recursive
|
||||||
|
|
||||||
|
: rewrite-path ( path quot -- )
|
||||||
|
! dup print
|
||||||
|
'[ [ path>literals [ _ map-literals ] map ] [ ] bi write-modern-path ]
|
||||||
|
[ drop . ] recover ; inline
|
||||||
|
|
||||||
|
: rewrite-string ( string quot -- )
|
||||||
|
! dup print
|
||||||
|
[ string>literals ] dip '[ _ map-literals ] map write-modern-string ; inline
|
||||||
|
|
||||||
|
: rewrite-paths ( seq quot -- ) '[ _ rewrite-path ] each ; inline
|
||||||
|
: lexable-core-paths ( -- seq ) core-source-paths ;
|
||||||
|
: lexable-basis-paths ( -- seq )
|
||||||
|
basis-source-paths {
|
||||||
|
"resource:basis/bit-arrays/bit-arrays.factor"
|
||||||
|
"resource:basis/bit-vectors/bit-vectors.factor"
|
||||||
|
"resource:basis/csv/csv.factor"
|
||||||
|
"resource:basis/dlists/dlists.factor"
|
||||||
|
"resource:basis/eval/eval.factor"
|
||||||
|
"resource:basis/farkup/farkup.factor"
|
||||||
|
"resource:basis/fry/fry.factor"
|
||||||
|
"resource:basis/linked-assocs/linked-assocs.factor"
|
||||||
|
"resource:basis/literals/literals.factor"
|
||||||
|
"resource:basis/nibble-arrays/nibble-arrays.factor"
|
||||||
|
"resource:basis/shuffle/shuffle.factor"
|
||||||
|
"resource:basis/simple-tokenizer/simple-tokenizer.factor"
|
||||||
|
"resource:basis/specialized-arrays/specialized-arrays.factor"
|
||||||
|
"resource:basis/specialized-vectors/specialized-vectors.factor"
|
||||||
|
"resource:basis/suffix-arrays/suffix-arrays.factor"
|
||||||
|
"resource:basis/urls/urls.factor"
|
||||||
|
"resource:basis/vlists/vlists.factor"
|
||||||
|
"resource:basis/alien/data/data.factor"
|
||||||
|
"resource:basis/alien/syntax/syntax.factor"
|
||||||
|
"resource:basis/byte-arrays/hex/hex.factor"
|
||||||
|
"resource:basis/classes/struct/struct.factor"
|
||||||
|
"resource:basis/cocoa/messages/messages.factor"
|
||||||
|
"resource:basis/db/postgresql/errors/errors.factor"
|
||||||
|
"resource:basis/hash-sets/identity/identity.factor"
|
||||||
|
"resource:basis/hash-sets/sequences/sequences.factor"
|
||||||
|
"resource:basis/hashtables/identity/identity.factor"
|
||||||
|
"resource:basis/hashtables/sequences/sequences.factor"
|
||||||
|
"resource:basis/help/handbook/handbook.factor"
|
||||||
|
"resource:basis/help/html/html.factor"
|
||||||
|
"resource:basis/html/templates/fhtml/fhtml.factor"
|
||||||
|
"resource:basis/http/parsers/parsers.factor"
|
||||||
|
"resource:basis/io/encodings/iso2022/iso2022.factor"
|
||||||
|
"resource:basis/json/reader/reader.factor"
|
||||||
|
"resource:basis/json/writer/writer.factor"
|
||||||
|
"resource:basis/math/complex/complex.factor"
|
||||||
|
"resource:basis/math/vectors/simd/simd.factor"
|
||||||
|
"resource:basis/math/vectors/simd/cords/cords.factor"
|
||||||
|
"resource:basis/memoize/syntax/syntax.factor"
|
||||||
|
"resource:basis/peg/ebnf/ebnf.factor"
|
||||||
|
"resource:basis/peg/parsers/parsers.factor"
|
||||||
|
"resource:basis/persistent/hashtables/hashtables.factor"
|
||||||
|
"resource:basis/persistent/vectors/vectors.factor"
|
||||||
|
"resource:basis/regexp/parser/parser.factor"
|
||||||
|
"resource:basis/xml/autoencoding/autoencoding.factor"
|
||||||
|
"resource:basis/xml/dtd/dtd.factor"
|
||||||
|
"resource:basis/xml/elements/elements.factor"
|
||||||
|
"resource:basis/xml/entities/entities.factor"
|
||||||
|
} diff ;
|
||||||
|
|
||||||
|
: lexable-extra-paths ( -- seq )
|
||||||
|
extra-source-paths {
|
||||||
|
"resource:extra/brainfuck/brainfuck.factor" ! EBNF: [[ ]] ;
|
||||||
|
"resource:extra/cuesheet/cuesheet.factor" ! CHAR: "
|
||||||
|
"resource:extra/fjsc/fjsc.factor" ! EBNF:
|
||||||
|
"resource:extra/emojify/emojify.factor" ! R/
|
||||||
|
"resource:extra/gml/gml.factor"
|
||||||
|
"resource:extra/metar/metar.factor" ! R/
|
||||||
|
"resource:extra/morse/morse.factor"
|
||||||
|
"resource:extra/rosetta-code/balanced-brackets/balanced-brackets.factor"
|
||||||
|
"resource:extra/flip-text/flip-text.factor"
|
||||||
|
"resource:extra/ini-file/ini-file.factor"
|
||||||
|
"resource:extra/poker/poker.factor"
|
||||||
|
"resource:extra/qw/qw.factor"
|
||||||
|
"resource:extra/svg/svg.factor"
|
||||||
|
"resource:extra/text-to-pdf/text-to-pdf.factor"
|
||||||
|
"resource:extra/tnetstrings/tnetstrings.factor"
|
||||||
|
"resource:extra/trees/trees.factor"
|
||||||
|
"resource:extra/alien/data/map/map.factor"
|
||||||
|
"resource:extra/arrays/shaped/shaped.factor"
|
||||||
|
"resource:extra/bunny/outlined/outlined.factor"
|
||||||
|
"resource:extra/c/lexer/lexer.factor"
|
||||||
|
"resource:extra/c/preprocessor/preprocessor.factor"
|
||||||
|
"resource:extra/gml/parser/parser.factor"
|
||||||
|
"resource:extra/gml/runtime/runtime.factor"
|
||||||
|
"resource:extra/gpu/effects/blur/blur.factor"
|
||||||
|
"resource:extra/hash-sets/numbers/numbers.factor"
|
||||||
|
"resource:extra/hashtables/numbers/numbers.factor"
|
||||||
|
"resource:extra/html/parser/parser.factor"
|
||||||
|
"resource:extra/infix/parser/parser.factor"
|
||||||
|
"resource:extra/infix/tokenizer/tokenizer.factor"
|
||||||
|
"resource:extra/parser-combinators/simple/simple.factor"
|
||||||
|
"resource:extra/pdf/values/values.factor"
|
||||||
|
"resource:extra/peg/pl0/pl0.factor"
|
||||||
|
"resource:extra/peg/javascript/parser/parser.factor"
|
||||||
|
"resource:extra/peg/javascript/tokenizer/tokenizer.factor"
|
||||||
|
"resource:extra/project-euler/011/011.factor"
|
||||||
|
"resource:extra/rosetta-code/balanced-brackets/balanced-bracke..."
|
||||||
|
"resource:extra/slots/syntax/syntax.factor"
|
||||||
|
"resource:extra/smalltalk/parser/parser.factor"
|
||||||
|
"resource:extra/talks/galois-talk/galois-talk.factor"
|
||||||
|
"resource:extra/talks/google-tech-talk/google-tech-talk.factor"
|
||||||
|
"resource:extra/talks/otug-talk/otug-talk.factor"
|
||||||
|
"resource:extra/talks/vpri-talk/vpri-talk.factor"
|
||||||
|
"resource:extra/trees/avl/avl.factor"
|
||||||
|
"resource:extra/trees/splay/splay.factor"
|
||||||
|
"resource:extra/yaml/conversion/conversion.factor"
|
||||||
|
} diff ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
! These work except they use pegs/ebnf, grep for [[ ]]
|
||||||
|
modified: basis/db/sqlite/errors/errors.factor
|
||||||
|
modified: basis/formatting/formatting.factor
|
||||||
|
modified: basis/globs/globs.factor
|
||||||
|
modified: extra/alien/fortran/fortran.factor
|
||||||
|
modified: extra/cpu/8080/emulator/emulator.factor
|
||||||
|
modified: extra/peg/expr/expr.factor
|
||||||
|
modified: extra/rosetta-code/arithmetic-evaluation/arithmetic-evaluation.factor
|
||||||
|
modified: extra/shell/parser/parser.factor
|
||||||
|
*/
|
||||||
|
|
||||||
|
: lexable-paths ( -- seq )
|
||||||
|
[
|
||||||
|
lexable-core-paths
|
||||||
|
lexable-basis-paths
|
||||||
|
lexable-extra-paths
|
||||||
|
] append-outputs ;
|
||||||
|
|
||||||
|
: paren-word>tick-word ( string -- string' )
|
||||||
|
dup [ "(" ?head drop ")" ?tail drop "'" append ] [ ] if ;
|
||||||
|
|
||||||
|
: paren-word-name? ( string -- ? )
|
||||||
|
{ [ "(" head? ] [ ")" tail? ] } 1&& ;
|
||||||
|
|
||||||
|
: transform-paren-word>tick-word ( token -- token' )
|
||||||
|
dup { [ tag-literal? ] [ tag>> paren-word-name? ] } 1&& [
|
||||||
|
[ paren-word>tick-word ] change-tag
|
||||||
|
] when ;
|
||||||
|
|
||||||
|
: single-line-comment? ( token -- ? )
|
||||||
|
{ [ line-comment-literal? ] [ delimiter>> "!" sequence= ] } 1&& ;
|
||||||
|
|
||||||
|
: transform-single-line-comment>hash-comment ( token -- token' )
|
||||||
|
dup single-line-comment? [
|
||||||
|
[ drop "#" ] change-delimiter
|
||||||
|
] when ;
|
||||||
|
|
||||||
|
: transform-source ( quot -- )
|
||||||
|
lexable-paths swap rewrite-paths ; inline
|
||||||
|
|
||||||
|
: transform-core ( quot -- )
|
||||||
|
lexable-core-paths swap rewrite-paths ; inline
|
|
@ -0,0 +1 @@
|
||||||
|
Doug Coleman
|
|
@ -0,0 +1,134 @@
|
||||||
|
! Copyright (C) 2015 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors combinators.smart io.files kernel sequences
|
||||||
|
splitting vocabs.files vocabs.hierarchy vocabs.loader
|
||||||
|
vocabs.metadata sets ;
|
||||||
|
IN: modern.paths
|
||||||
|
|
||||||
|
: modern-if-available ( path -- path' )
|
||||||
|
dup ".factor" ?tail [
|
||||||
|
".modern" append
|
||||||
|
dup exists? [ nip ] [ drop ] if
|
||||||
|
] [
|
||||||
|
drop
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
ERROR: not-a-source-path path ;
|
||||||
|
: force-modern-path ( path -- path' )
|
||||||
|
".factor" ?tail [ ".modern" append ] [ not-a-source-path ] if ;
|
||||||
|
: modern-docs-path ( path -- path' )
|
||||||
|
vocab-docs-path modern-if-available ;
|
||||||
|
: modern-tests-path ( path -- path' )
|
||||||
|
vocab-tests-path modern-if-available ;
|
||||||
|
: modern-source-path ( path -- path' )
|
||||||
|
vocab-source-path modern-if-available ;
|
||||||
|
: modern-syntax-path ( path -- path' )
|
||||||
|
vocab-source-path ".factor" ?tail drop "-syntax.modern" append ;
|
||||||
|
|
||||||
|
: force-modern-docs-path ( path -- path' )
|
||||||
|
vocab-docs-path force-modern-path ;
|
||||||
|
: force-modern-tests-path ( path -- path' )
|
||||||
|
vocab-tests-path force-modern-path ;
|
||||||
|
: force-modern-source-path ( path -- path' )
|
||||||
|
vocab-source-path force-modern-path ;
|
||||||
|
|
||||||
|
: vocabs-from ( root -- vocabs )
|
||||||
|
"" disk-vocabs-in-root/prefix
|
||||||
|
no-prefixes [ name>> ] map ;
|
||||||
|
|
||||||
|
: core-vocabs ( -- seq ) "resource:core" vocabs-from ;
|
||||||
|
: less-core-test-vocabs ( seq -- seq' )
|
||||||
|
{
|
||||||
|
"vocabs.loader.test.a"
|
||||||
|
"vocabs.loader.test.b"
|
||||||
|
"vocabs.loader.test.c"
|
||||||
|
"vocabs.loader.test.d"
|
||||||
|
"vocabs.loader.test.e"
|
||||||
|
"vocabs.loader.test.f"
|
||||||
|
"vocabs.loader.test.g"
|
||||||
|
"vocabs.loader.test.h"
|
||||||
|
"vocabs.loader.test.i"
|
||||||
|
"vocabs.loader.test.j"
|
||||||
|
"vocabs.loader.test.k"
|
||||||
|
"vocabs.loader.test.l"
|
||||||
|
"vocabs.loader.test.m"
|
||||||
|
"vocabs.loader.test.n"
|
||||||
|
"vocabs.loader.test.o"
|
||||||
|
"vocabs.loader.test.p"
|
||||||
|
} diff ;
|
||||||
|
|
||||||
|
: core-bootstrap-vocabs ( -- seq )
|
||||||
|
core-vocabs less-core-test-vocabs ;
|
||||||
|
|
||||||
|
: basis-vocabs ( -- seq ) "resource:basis" vocabs-from ;
|
||||||
|
: extra-vocabs ( -- seq ) "resource:extra" vocabs-from ;
|
||||||
|
: all-vocabs ( -- seq )
|
||||||
|
[
|
||||||
|
core-vocabs
|
||||||
|
basis-vocabs
|
||||||
|
extra-vocabs
|
||||||
|
] { } append-outputs-as ;
|
||||||
|
|
||||||
|
: filter-exists ( seq -- seq' ) [ exists? ] filter ;
|
||||||
|
|
||||||
|
! These paths have syntax errors on purpose...
|
||||||
|
: reject-some-paths ( seq -- seq' )
|
||||||
|
{
|
||||||
|
"resource:core/vocabs/loader/test/a/a.factor"
|
||||||
|
"resource:core/vocabs/loader/test/b/b.factor"
|
||||||
|
"resource:core/vocabs/loader/test/c/c.factor"
|
||||||
|
! Here down have parse errors
|
||||||
|
"resource:core/vocabs/loader/test/d/d.factor"
|
||||||
|
"resource:core/vocabs/loader/test/e/e.factor"
|
||||||
|
"resource:core/vocabs/loader/test/f/f.factor"
|
||||||
|
"resource:core/vocabs/loader/test/g/g.factor"
|
||||||
|
"resource:core/vocabs/loader/test/h/h.factor"
|
||||||
|
"resource:core/vocabs/loader/test/i/i.factor"
|
||||||
|
"resource:core/vocabs/loader/test/j/j.factor"
|
||||||
|
"resource:core/vocabs/loader/test/k/k.factor"
|
||||||
|
"resource:core/vocabs/loader/test/l/l.factor"
|
||||||
|
"resource:core/vocabs/loader/test/m/m.factor"
|
||||||
|
"resource:core/vocabs/loader/test/n/n.factor"
|
||||||
|
"resource:core/vocabs/loader/test/o/o.factor"
|
||||||
|
"resource:core/vocabs/loader/test/p/p.factor"
|
||||||
|
"resource:extra/math/blas/vectors/vectors.factor" ! need .modern file
|
||||||
|
"resource:extra/math/blas/matrices/matrices.factor" ! need .modern file
|
||||||
|
} diff
|
||||||
|
! Don't parse .modern files yet
|
||||||
|
[ ".modern" tail? ] reject ;
|
||||||
|
|
||||||
|
: modern-source-paths ( names -- paths )
|
||||||
|
[ modern-source-path ] map filter-exists reject-some-paths ;
|
||||||
|
: modern-docs-paths ( names -- paths )
|
||||||
|
[ modern-docs-path ] map filter-exists reject-some-paths ;
|
||||||
|
: modern-tests-paths ( names -- paths )
|
||||||
|
[ vocab-tests ] map concat
|
||||||
|
[ modern-if-available ] map filter-exists reject-some-paths ;
|
||||||
|
|
||||||
|
: all-source-paths ( -- seq )
|
||||||
|
all-vocabs modern-source-paths ;
|
||||||
|
|
||||||
|
: all-docs-paths ( -- seq )
|
||||||
|
all-vocabs modern-docs-paths ;
|
||||||
|
|
||||||
|
: all-tests-paths ( -- seq )
|
||||||
|
all-vocabs modern-tests-paths ;
|
||||||
|
|
||||||
|
: all-syntax-paths ( -- seq )
|
||||||
|
all-vocabs [ modern-syntax-path ] map filter-exists reject-some-paths ;
|
||||||
|
|
||||||
|
: all-factor-paths ( -- seq )
|
||||||
|
[
|
||||||
|
all-syntax-paths all-source-paths all-docs-paths all-tests-paths
|
||||||
|
] { } append-outputs-as ;
|
||||||
|
|
||||||
|
: vocab-names>syntax ( strings -- seq )
|
||||||
|
[ modern-syntax-path ] map [ exists? ] filter ;
|
||||||
|
|
||||||
|
: core-syntax-paths ( -- seq ) core-vocabs vocab-names>syntax reject-some-paths ;
|
||||||
|
: basis-syntax-paths ( -- seq ) basis-vocabs vocab-names>syntax reject-some-paths ;
|
||||||
|
: extra-syntax-paths ( -- seq ) extra-vocabs vocab-names>syntax reject-some-paths ;
|
||||||
|
|
||||||
|
: core-source-paths ( -- seq ) core-vocabs modern-source-paths reject-some-paths ;
|
||||||
|
: basis-source-paths ( -- seq ) basis-vocabs modern-source-paths reject-some-paths ;
|
||||||
|
: extra-source-paths ( -- seq ) extra-vocabs modern-source-paths reject-some-paths ;
|
|
@ -0,0 +1 @@
|
||||||
|
Doug Coleman
|
|
@ -0,0 +1,199 @@
|
||||||
|
! Copyright (C) 2016 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: accessors assocs fry kernel locals math math.private
|
||||||
|
sequences sequences.extras sequences.private unicode ;
|
||||||
|
IN: modern.slices
|
||||||
|
|
||||||
|
: matching-delimiter ( ch -- ch' )
|
||||||
|
H{
|
||||||
|
{ CHAR: ( CHAR: ) }
|
||||||
|
{ CHAR: [ CHAR: ] }
|
||||||
|
{ CHAR: { CHAR: } }
|
||||||
|
{ CHAR: < CHAR: > }
|
||||||
|
{ CHAR: : CHAR: ; }
|
||||||
|
} ?at drop ;
|
||||||
|
|
||||||
|
: matching-delimiter-string ( string -- string' )
|
||||||
|
[ matching-delimiter ] map ;
|
||||||
|
|
||||||
|
ERROR: unexpected-end n string ;
|
||||||
|
: nth-check-eof ( n string -- nth )
|
||||||
|
2dup ?nth [ 2nip ] [ unexpected-end ] if* ;
|
||||||
|
|
||||||
|
: peek-from ( n/f string -- ch )
|
||||||
|
over [ ?nth ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
! Allow eof
|
||||||
|
: next-char-from ( n/f string -- n'/f string ch/f )
|
||||||
|
over [
|
||||||
|
2dup ?nth [ [ 1 + ] 2dip ] [ f ] if*
|
||||||
|
] [
|
||||||
|
[ 2drop f ] [ nip ] 2bi f
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: prev-char-from-slice-end ( slice -- ch/f )
|
||||||
|
[ to>> 2 - ] [ seq>> ] bi ?nth ;
|
||||||
|
|
||||||
|
: prev-char-from-slice ( slice -- ch/f )
|
||||||
|
[ from>> 1 - ] [ seq>> ] bi ?nth ;
|
||||||
|
|
||||||
|
: next-char-from-slice ( slice -- ch/f )
|
||||||
|
[ to>> ] [ seq>> ] bi ?nth ;
|
||||||
|
|
||||||
|
: char-before-slice ( slice -- ch/f )
|
||||||
|
[ from>> 1 - ] [ seq>> ] bi ?nth ;
|
||||||
|
|
||||||
|
: char-after-slice ( slice -- ch/f )
|
||||||
|
[ to>> ] [ seq>> ] bi ?nth ;
|
||||||
|
|
||||||
|
: next-char-from* ( n/f string -- ch/f )
|
||||||
|
next-char-from 2nip ;
|
||||||
|
|
||||||
|
: find-from* ( ... n seq quot: ( ... elt -- ... ? ) -- ... i elt ? )
|
||||||
|
[ find-from ] keep
|
||||||
|
pick [ drop t ] [ length -rot nip f ] if ; inline
|
||||||
|
|
||||||
|
: skip-blank-from ( n string -- n' string )
|
||||||
|
[ [ blank? not ] find-from* 2drop ] keep ; inline
|
||||||
|
|
||||||
|
: skip-til-eol-from ( n string -- n' string )
|
||||||
|
[ [ "\r\n" member? ] find-from* 2drop ] keep ; inline
|
||||||
|
|
||||||
|
! Don't include the whitespace in the slice
|
||||||
|
:: slice-til-whitespace ( n string -- n' string slice/f ch/f )
|
||||||
|
n string [ "\s\r\n" member? ] find-from :> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch ; inline
|
||||||
|
|
||||||
|
:: slice-until' ( n string quot -- n' string slice/f ch/f )
|
||||||
|
n string quot find-from :> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch ; inline
|
||||||
|
|
||||||
|
: slice-until ( n string quot -- n' string slice/f )
|
||||||
|
slice-until' drop ; inline
|
||||||
|
|
||||||
|
:: slice-til-not-whitespace ( n string -- n' string slice/f ch/f )
|
||||||
|
n string [ "\s\r\n" member? not ] find-from :> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch ; inline
|
||||||
|
|
||||||
|
: skip-whitespace ( n string -- n' string )
|
||||||
|
slice-til-not-whitespace 2drop ;
|
||||||
|
|
||||||
|
: empty-slice-end ( seq -- slice )
|
||||||
|
[ length dup ] [ ] bi <slice> ; inline
|
||||||
|
|
||||||
|
: empty-slice-from ( n seq -- slice )
|
||||||
|
dupd <slice> ; inline
|
||||||
|
|
||||||
|
:: slice-til-eol ( n string -- n' string slice/f ch/f )
|
||||||
|
n [
|
||||||
|
n string '[ "\r\n" member? ] find-from :> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch
|
||||||
|
] [
|
||||||
|
n string string empty-slice-end f
|
||||||
|
] if ; inline
|
||||||
|
|
||||||
|
:: merge-slice-til-eol-slash'' ( n string -- n' string slice/f ch/f )
|
||||||
|
n [
|
||||||
|
n string '[ "\r\n\\" member? ] find-from :> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch
|
||||||
|
] [
|
||||||
|
n string string empty-slice-end f
|
||||||
|
] if ; inline
|
||||||
|
|
||||||
|
: merge-slice-til-whitespace ( n string slice -- n' string slice' )
|
||||||
|
[ slice-til-whitespace drop ] dip merge-slices ;
|
||||||
|
|
||||||
|
: merge-slice-til-eol ( n string slice -- n' string slice' )
|
||||||
|
[ slice-til-eol drop ] dip merge-slices ;
|
||||||
|
|
||||||
|
: slice-between ( slice1 slice2 -- slice )
|
||||||
|
! ensure-same-underlying
|
||||||
|
slice-order-by-from
|
||||||
|
[ to>> ]
|
||||||
|
[ [ from>> 2dup < [ swap ] unless ] [ seq>> ] bi ] bi* <slice> ;
|
||||||
|
|
||||||
|
: slice-before ( slice -- slice' )
|
||||||
|
[ drop 0 ] [ from>> ] [ seq>> ] tri <slice> ;
|
||||||
|
|
||||||
|
: ?nth' ( n/f string/f -- obj/f )
|
||||||
|
over [ ?nth ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
:: merge-slice-til-eol-slash' ( n string slice -- n' string slice/f ch/f )
|
||||||
|
n string merge-slice-til-eol-slash'' :> ( n' string' slice' ch' )
|
||||||
|
ch' CHAR: \ = [
|
||||||
|
n' 1 + string' ?nth' "\r\n" member? [
|
||||||
|
n' 2 + string' slice slice' span-slices merge-slice-til-eol-slash'
|
||||||
|
] [
|
||||||
|
"omg" throw
|
||||||
|
] if
|
||||||
|
] [
|
||||||
|
n' string' slice slice' span-slices ch'
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
! Supports \ at eol (with no space after it)
|
||||||
|
: slice-til-eol-slash ( n string -- n' string slice/f ch/f )
|
||||||
|
2dup empty-slice-from merge-slice-til-eol-slash' ;
|
||||||
|
|
||||||
|
:: slice-til-separator-inclusive ( n string tokens -- n' string slice/f ch/f )
|
||||||
|
n string '[ tokens member? ] find-from [ dup [ 1 + ] when ] dip :> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch ; inline
|
||||||
|
|
||||||
|
: slice-til-separator-exclusive ( n string tokens -- n' string slice/f ch/f )
|
||||||
|
slice-til-separator-inclusive dup [
|
||||||
|
[ [ 1 - ] change-to ] dip
|
||||||
|
] when ;
|
||||||
|
|
||||||
|
:: slice-til-either ( n string tokens -- n'/f string slice/f ch )
|
||||||
|
n [
|
||||||
|
n string '[ tokens member? ] find-from
|
||||||
|
dup "\s\r\n" member? [
|
||||||
|
:> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch
|
||||||
|
] [
|
||||||
|
[ dup [ 1 + ] when ] dip :> ( n' ch )
|
||||||
|
n' string
|
||||||
|
n n' string ?<slice>
|
||||||
|
ch
|
||||||
|
] if
|
||||||
|
] [
|
||||||
|
f string f f
|
||||||
|
] if ; inline
|
||||||
|
|
||||||
|
ERROR: subseq-expected-but-got-eof n string expected ;
|
||||||
|
|
||||||
|
:: slice-til-string ( n string search -- n' string payload end-string )
|
||||||
|
search string n start* :> n'
|
||||||
|
n' [ n string search subseq-expected-but-got-eof ] unless
|
||||||
|
n' search length + string
|
||||||
|
n n' string ?<slice>
|
||||||
|
n' dup search length + string ?<slice> ;
|
||||||
|
|
||||||
|
: modify-from ( slice n -- slice' )
|
||||||
|
'[ from>> _ + ] [ to>> ] [ seq>> ] tri <slice> ;
|
||||||
|
|
||||||
|
: modify-to ( slice n -- slice' )
|
||||||
|
[ [ from>> ] [ to>> ] [ seq>> ] tri ] dip
|
||||||
|
swap [ + ] dip <slice> ;
|
||||||
|
|
||||||
|
! { CHAR: ] [ read-closing ] }
|
||||||
|
! { CHAR: } [ read-closing ] }
|
||||||
|
! { CHAR: ) [ read-closing ] }
|
||||||
|
: read-closing ( n string tok -- n string tok )
|
||||||
|
dup length 1 = [
|
||||||
|
-1 modify-to [ 1 - ] 2dip
|
||||||
|
] unless ;
|
||||||
|
|
Loading…
Reference in New Issue