factor/core/lexer/lexer.factor

121 lines
2.9 KiB
Factor
Raw Normal View History

! Copyright (C) 2008, 2009 Slava Pestov.
2008-06-25 04:25:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences accessors namespaces math words strings
2008-07-28 23:03:13 -04:00
io vectors arrays math.parser combinators continuations ;
2008-06-25 04:25:08 -04:00
IN: lexer
TUPLE: lexer text line line-text line-length column ;
: next-line ( lexer -- )
dup [ line>> ] [ text>> ] bi ?nth >>line-text
dup line-text>> length >>line-length
[ 1 + ] change-line
2008-06-25 04:25:08 -04:00
0 >>column
drop ;
: new-lexer ( text class -- lexer )
new
0 >>line
swap >>text
dup next-line ; inline
: <lexer> ( text -- lexer )
lexer new-lexer ;
2009-06-16 14:47:56 -04:00
ERROR: unexpected want got ;
PREDICATE: unexpected-tab < unexpected
got>> CHAR: \t = ;
: forbid-tab ( c -- c )
[ CHAR: \t eq? [ "[space]" "[tab]" unexpected ] when ] keep ;
2008-06-25 04:25:08 -04:00
: skip ( i seq ? -- n )
over length
2009-06-16 14:47:56 -04:00
[ [ swap forbid-tab CHAR: \s eq? xor ] curry find-from drop ] dip or ;
2008-06-25 04:25:08 -04:00
: change-lexer-column ( lexer quot -- )
[ [ column>> ] [ line-text>> ] bi ] prepose keep
2008-08-29 17:52:10 -04:00
(>>column) ; inline
2008-06-25 04:25:08 -04:00
GENERIC: skip-blank ( lexer -- )
M: lexer skip-blank ( lexer -- )
[ t skip ] change-lexer-column ;
GENERIC: skip-word ( lexer -- )
M: lexer skip-word ( lexer -- )
[
2dup nth CHAR: " eq? [ drop 1 + ] [ f skip ] if
2008-06-25 04:25:08 -04:00
] change-lexer-column ;
: still-parsing? ( lexer -- ? )
2008-08-29 17:16:43 -04:00
[ line>> ] [ text>> ] bi length <= ;
2008-06-25 04:25:08 -04:00
: still-parsing-line? ( lexer -- ? )
2008-08-29 17:16:43 -04:00
[ column>> ] [ line-length>> ] bi < ;
2008-06-25 04:25:08 -04:00
: (parse-token) ( lexer -- str )
2008-08-29 17:16:43 -04:00
{
[ column>> ]
[ skip-word ]
[ column>> ]
[ line-text>> ]
} cleave subseq ;
2008-06-25 04:25:08 -04:00
: parse-token ( lexer -- str/f )
dup still-parsing? [
dup skip-blank
dup still-parsing-line?
[ (parse-token) ] [ dup next-line parse-token ] if
] [ drop f ] if ;
: scan ( -- str/f ) lexer get parse-token ;
PREDICATE: unexpected-eof < unexpected
2008-08-29 17:16:43 -04:00
got>> not ;
2008-06-25 04:25:08 -04:00
: unexpected-eof ( word -- * ) f unexpected ;
: expect ( token -- )
scan
[ 2dup = [ 2drop ] [ unexpected ] if ]
[ unexpected-eof ]
if* ;
2008-06-25 04:25:08 -04:00
: (parse-tokens) ( accum end -- accum )
scan 2dup = [
2drop
] [
[ pick push (parse-tokens) ] [ unexpected-eof ] if*
] if ;
: parse-tokens ( end -- seq )
100 <vector> swap (parse-tokens) >array ;
TUPLE: lexer-error line column line-text error ;
: <lexer-error> ( msg -- error )
\ lexer-error new
lexer get
[ line>> >>line ]
[ column>> >>column ]
[ line-text>> >>line-text ]
tri
swap >>error ;
: lexer-dump ( error -- )
[ line>> number>string ": " append ]
[ line-text>> dup string? [ drop "" ] unless ]
[ column>> 0 or ] tri
pick length + CHAR: \s <string>
[ write ] [ print ] [ write "^" print ] tri* ;
: with-lexer ( lexer quot -- newquot )
[ lexer set ] dip [ <lexer-error> rethrow ] recover ; inline
SYMBOL: lexer-factory
[ <lexer> ] lexer-factory set-global