// $Id$ //X/$functor Lexer (Stream : IndexedStream); //X/$module Err = Stream-Error (Stream); //X/$use Err; $use "Stream.IndexedStream"; $use "Stream.Stream"; $use "Stream.StreamErr"; $use Arithm Box Class Compare Convert; $box Collect_Errors_Box; /* * A number. Initially should be 0. */ //** $func Start-Collect-Errors = ; //** $func Stop-Collect-Errors = ; //** $func? Collecting-Errors? = ; Start_Collect_Errors = : s.num, >; Stop_Collect_Errors = : { 0; s.num = >; }; IsCollecting_Errors = # \{ : 0; }; $func? IsBlank term = ; IsBlank \{ ' '; '\t'; '\n'; '\r'; }; IsSkip_Blank stream = : v; IsSkip_Comment stream = { # = ;; }, : { '*' = : e; '/' = :: t.pos, { : { '/' = : e; '*' = $iter { : v, { : { '/' = Stop; t; }; , Stop; }; , Stop; } :: e.Isstop, e.Isstop : Stop; t1 = , $fail; }; = $fail; }; t1 = , $fail; }; $func? IsVar_Sym term = ; IsVar_Sym sym = \{ ; ; '-?!' : e sym e; }; IsScan_Keyword stream = : { '$'; t1 = , $fail; }, :: e.ident, { : 1 = ; e.ident; } : { 'box' = BOX; 'channel' = CHANNEL; 'const' = CONST; 'error' = ERROR; 'fail' = FAIL; 'func' = FUNC; 'func?' = "FUNC?"; 'iter' = ITER; 'l' = L; 'r' = R; 'string' = STRING; 'table' = TABLE; 'trace' = TRACE; 'traceall' = TRACEALL; 'trap' = TRAP; 'use' = USE; 'vector' = VECTOR; 'with' = WITH; e1 = , $fail; }; IsScan_Number stream = : s.first, { ; s.first : \{ '+'; '-'; }; = $fail; }, NUMBER s.first ; IsScan_Variable stream = : { 's', SVAR; 'e', EVAR; 'v', VVAR; 't', TVAR; t1 = , $fail; } :: s.type, : { '.' = ; s1, = s1 ; t1 = , /*empty*/; } :: e.name, { // e.name : /*empty*/ = // s.type '!!tmp-' '-' '-' >; s.type e.name; }; $func? IsUppercase_Letter s.letter = ; $func? IsFun_Sym term = ; IsScan_Identifier stream = : s.first, { \{ ; '?!' : e s.first e; } = WORD s.first ; = $fail; }; IsUppercase_Letter s.letter = , ) (s.letter)>; IsFun_Sym sym = \{ ; ; '-.!?' : e sym e; }; $func Scan_String_Rest t.pos s.max s.term stream = e.characters; IsScan_Quoted_Word stream = { # = ;; }, :: t.pos, : { '\"' = QWORD ; t1 = , $fail; }; IsScan_String stream = { # = ;; }, :: t.pos, : { '\'' = SYMBOLS ; t1 = , $fail; }; IsScan_Char stream = { # = ;; }, :: t.pos, : { '\'' = : { v.str = , SYMBOLS v.str; empty = SYMBOLS /*empty*/; }; t1 = , $fail; }; Scan_String_Rest t.pos s.max s.term stream = (/*e.s*/) s.max $iter { : { s.term = (e.s) 0; '\\' = { : { 'n' = (e.s '\n') ; 't' = (e.s '\t') ; 'v' = (e.s '\v') ; 'b' = (e.s '\b') ; 'r' = (e.s '\r') ; 'f' = (e.s '\f') ; '\\' = (e.s '\\') ; '\'' = (e.s '\'') ; '\"' = (e.s '\"') ; '\n' = (e.s) s.max; s1 = , (e.s s1) ; t1 = , (e.s) s.max; }; , (e.s) 0; }; '\n' = (e.s '\n') ; //FIXME: should be option-controlled! s1 = (e.s s1) ; t1 = , (e.s) s.max; }; , (e.s) 0; } :: (e.s) s.max, s.max : 0 = e.s; $box Parenth_Level; $func? Read_Term_Aux stream = term; IsRead_Term stream = , , { :: term = , term; = $fail; }; Read_Term_Aux stream = $iter { ; ; Stop; } :: e.Isstop, e.Isstop : Stop = \{ :: t.pos, : \{ '(' = : s.level, >, /*e.terms*/ (/*e.last*/) $iter { e.terms e.last (); = $fail; } :: e.terms (e.last), : s.level = (e.terms); ')' = : s.level, { = >, ("Time-To-Close-Parentheses"); = $fail; }; t1, , $fail; }; \{ ; ; ; ; } : s.type e.value, s.type : { WORD = { : 1 = >; ; }; QWORD = ; SYMBOLS = \{ e.value : symbol, symbol; ; }; NUMBER = ; }; : t1 = , ; };