// // Copyright (C) 1999, 2000 Refal+ Development Group // // Refal+ 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. // // Refal+ 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 Refal+; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // $Source$ // $Revision$ // $Date$ // Author: Andrey Slepuhin // rfp_lex.rfi $use "rfpc" ; // rfpc.rfi $use "rfp_helper" ; // rfp_helper.rfi $use "rfp_src" ; // rfp_src.rfi $use "rfp_err" ; // rfp_err.rfi $use StdIO; $use Box ; $use Dir ; $use Dos ; $use Arithm ; $use Class ; $use Access ; $use Compare ; $use Convert ; $use Table ; $use Apply ; $use List ; $use File ; $box Source ; $box Position ; $box Source-Index ; $box Saved-Sources ; $box Src-Counter ; $func? Get-Source-Line = e.line ; $func Scan-Token e.line = (e.tokens) (e.new-line) ; $func Scan-Tokens e.line = e.tokens ; $func? Blank? s.char = ; $func? Skip-Blank e.line = e.new-line ; $func Next-Column = ; $func Next-Row = ; $func? Uppercase-Letter? s.letter = ; $func Source-File-Name = e.name ; $func Print-File-Name = ; $func Token-Position = e.position; $func? Scan-Number? e.line = (e.num) (e.new-line) ; $func Scan-Number-Rest (e.start) (e.line) = (e.num) (e.new-line) ; $func? Scan-Keyword? e.line = (e.token) (e.new-line) ; $func Scan-Keyword-Rest (e.start) (e.line) = (e.keyword) (e.new-line) ; $func? Scan-Variable? e.line = (e.token) (e.new-line) ; $func? Scan-Identifier? e.line = (e.token) (e.new-line) ; $func Scan-Identifier-Rest s.obj (e.start) (e.line) = (e.word) (e.new-line) ; $func? Scan-Word? e.line = (e.token) (e.new-line) ; $func? Scan-String? e.line = (e.token) (e.new-line) ; $func Scan-String-Rest (e.start) (e.line) s.term = (e.string) (e.new-line) ; $func? Skip-Comment e.line = e.new-line ; $func? Find-Include? e.name s.case-insensitive? = e.source ; $func? Try-Open e.filename = e.source ; $func? Interface-Name? e.source = e.iname ; $func Push-Source e.source s.type s.row s.column = ; $func? Pop-Source? = ; RFP-Lexer e.filename = , , , , , , { e.filename : v, { ; , ; }; ; } :: e.source, { e.source : e (e '.rfi') (e) = ; ; }, { > :: e.source, , ;; } :: e.ts, e.ts ; Find-Includes e.filename = , , , , , { ; , ; } :: e.source, , (/*e.includes*/) (/*e.line*/) /*e.stop?*/ $iter : { ((e (EOF))) e = (e.includes) () STOP; ((e (USE))) (e.ln) = () (e.ln) /*e.st?*/ $iter : { ((e (SEMICOLON))) (e.l) = (e.incs) (e.l) STOP; (((e.p) (s.WORD-or-QWORD e.s))) (e.l), s.WORD-or-QWORD : \{ WORD; QWORD; } = (e.incs (e.s)) (e.l); (((e.p) (EOF))) = , , () (); (((e.p) (e.tag))) = , , () (); } :: (e.incs) (e.ln) e.st?, e.st? : STOP = (e.includes e.incs) (e.ln); e (e.ln) = (e.includes) (e.ln); } :: (e.includes) (e.line) e.stop?, e.stop? : STOP = e.includes; Push-Source e.source s.type s.row s.col = : s.n, <"+" s.n 1> :: s.n, , ( ) >, , )>, , ; Pop-Source? = >, : e1, e1 : $r e.saved (e.source s.n s.type s.row s.col), , , , ; Scan-Tokens e.line = :: (e.t) (e.line), e.t : { ((e) (EOF)) = { ; e.t; }; ((e) (USE)), # = { () (e.line) T $iter { :: (e.t) (e.line), e.t : { ((e) (SEMICOLON)) = (e.nts) (e.line) F; ((e.p) (s.WORD-or-QWORD e.s)), s.WORD-or-QWORD : \{ WORD = CI; QWORD = NOT-CI; } :: s.ci? = { ; e.s; } :: e.s, { , ;; }, { :: e.include, , e.nts ; , e.nts; } :: e.nts, (e.nts) (e.line) T; ((e.p) (EOF)) = , (e.nts) (e.line) F; ((e.p) (e.tag)) = , (e.nts) (e.line) T; }; } :: (e.nts) (e.line) s1, s1 : F, e.nts ; }; e = e.t ; }; Scan-Token e.line = e.line : { = { :: e.line, ; ((() (EOF))) (); }; s.char e.rest = :: e.saved-position, { = , ; s.char : \{ '(' = LPAREN; ')' = RPAREN; '<' = LBRACKET; '>' = RBRACKET; '{' = LBRACE; '}' = RBRACE; '#' = NOT; '&' = REF; ',' = COMMA; ';' = SEMICOLON; '=' = EQUAL; } :: s.tk = , (((e.saved-position) (s.tk))) (e.rest); s.char : \{ ':' = , { e.rest : ':' e.rest2 = , (((e.saved-position) (DCOLON))) (e.rest2); (((e.saved-position) (COLON))) (e.rest); }; '\\' = , { e.rest : s.char2 e.rest2 = { s.char2 : \{ '?' = STAKE; '!' = CUT; '{' = TLBRACE; } :: s.tk = , (((e.saved-position) (s.tk))) (e.rest2); ) ("Invalid character \'" s.char2 "\'")>, , ; }; ) ("Unexpected end of line")>, ; }; '/' = , e.rest : \{ '/' e.rest2 = ; '*' e.rest2 = , >; s.err e.rest2 = ) ("Invalid character \'" s.err "\'")>, , ; = ) ("Unexpected end of line")>, ; }; '*' = ; }; \{ ; ; ; ; ; ; } :: (e.tk) (e.new-line), (((e.saved-position) (e.tk))) (e.new-line); ) ("Invalid character \'" s.char "\'")>, , ; }; }; Get-Source-Line = > :: e.line, , e.line; Blank? s.char = ' \n\t' : e s.char e; Skip-Blank e.line = e.line : { = >; s.char e.rest = { = , ; e.line; }; }; Scan-Keyword? '$' e.rest = , :: (e.ident) (e.line), { = ; e.ident; } : \{ '$box' = BOX; '$channel' = CHANNEL; '$const' = CONST; '$error' = ERROR; '$fail' = FAIL; '$func' = FUNC; '$func?' = FUNC?; '$tfunc' = { = TFUNC; ) ("Incorrect using of t-function \n")>, TFUNC; }; '$extern' = EXTERN; '$iter' = ITER; '$l' = L; '$r' = R; '$string' = STRING; '$table' = TABLE; '$trace' = TRACE; '$traceall' = TRACEALL; '$trap' = TRAP; '$use' = USE; '$vector' = VECTOR; '$with' = WITH; } :: s.key, (s.key) (e.line); Scan-Keyword-Rest (e.start) (e.line) = (e.start) (e.line) T $iter { e.l : s.first e.rest, \{ ; s.first : \{ '?'; '!'; }; }, , (e.w s.first) (e.rest) T; (e.w) (e.l) F; } :: (e.w) (e.l) s.cond, s.cond : F, (e.w) (e.l) ; Scan-Variable? e.line = e.line : s.first e.rest, s.first : \{ 's', SVAR; 'e', EVAR; 'v', VVAR; 't', TVAR; } :: s.type, , { e.rest : '.' e.rest2 = , ; ; } :: (e.name) (e.new-line), { e.name : = : s.r s.c, (s.type '!!tmp-' '-' s.r '-' s.c>) (e.new-line); (s.type e.name) (e.new-line); }; Scan-Number? e.line = e.line : s.first e.rest, \{ \{ ; s.first : \{ '+'; '-'; }; }, , :: (e.num) (e.rest), (NUMBER )(e.rest); }; Scan-Number-Rest (e.start) (e.line) = { e.line : '\\' = )>; (e.start) (e.line) T $iter { e.l : s.first e.rest, , , (e.w s.first) (e.rest) T; (e.w) (e.l) F; } :: (e.w) (e.l) s.cond, s.cond : F, (e.w) (e.l) ; }; Scan-Identifier? e.line = e.line : s.first e.rest, \{ \{ ; s.first : \{ '?'; '!'; }; }, , :: (e.word) (e.rest), (WORD e.word) (e.rest); }; Scan-Identifier-Rest s.obj (e.start) (e.line) = s.obj : { Var = '?!-' ; Fun = '?!-.'; } :: e.extra, (e.start) (e.line) T $iter { e.l : s.first e.rest, \{ ; ; e.extra : e s.first e; }, , (e.w s.first) (e.rest) T; (e.w) (e.l) F; } :: (e.w) (e.l) s.cond, s.cond : F = { // = () (e.l); (e.w) (e.l); }; Scan-Word? e.line = e.line : '\"' e.rest, \{ , :: (e.word) (e.rest), (QWORD e.word) (e.rest); }; Scan-String? e.line = e.line : '\'' e.rest, \{ , :: (e.str) (e.rest), (SYMBOLS e.str) (e.rest); }; Scan-String-Rest (e.start) (e.line) s.term = (e.start) (e.line) T $iter { e.l : s.first e.rest, , s.first : { s.term = (e.s) (e.rest) F; '\\' = { e.rest : s.first2 e.rest2, , s.first2 : \{ 't' = (e.s '\t') (e.rest2) T; 'n' = (e.s '\n') (e.rest2) T; 'r' = (e.s '\r') (e.rest2) T; '\\' = (e.s '\\') (e.rest2) T; '\'' = (e.s '\'') (e.rest2) T; '\"' = (e.s '\"') (e.rest2) T; s = ) ("Unknown control sequence \'\\" s.first2 "\'")>, (e.s s.first2) (e.rest2) T; }; (e.s) () T; ) (Error "Unterminated string detected")>, (e.s) () F; }; s = (e.s s.first) (e.rest) T; }; (e.s '\n') () T; ) ("Unterminated string detected")>, (e.s) () F; } :: (e.s) (e.l) s.cond, s.cond : F, (e.s) (e.l) ; Skip-Comment e.line = { e.line : e1 '*/' e.rest = &Next-Column>)> : e, e.rest; >; ) ("Unexpected end of file")>; }; Next-Column = >>; Next-Row = >>; Uppercase-Letter? s.letter = , <"=" () (s.letter)>; Source-File-Name = : s.srctype s.getline-func (e.name) (e.src), e.name; Print-File-Name = >; Token-Position = ; Find-Include? e.name s.ci? = : s.dir-separator, :: e.NAME, { e.name : s.dir-separator e = (); e.name : '.' e = (>); (>) ; } :: e.path, e.path : e (e.dirname) e \? e.dirname : { e s.dir-separator = e.dirname; v = e.dirname s.dir-separator; e = '.' s.dir-separator; } :: e.dirn, // { // e.name $iter { e.name : e1 '.' e2 = e1 s.dir-separator e2; } :: e.name, // # \{ e.name : e1 '.' e2; }, e.name; // } :: e.name, \{ \! { $trap $with { e = $fail; }; } : s.dir, $iter \{ :: e.filename, { e.filename : e.basename '.rfi', \{ e.basename : e.name; s.ci? : CI, : e.NAME; } = ();; }; } :: e.res, e.res : (e.source) = e.source; ; } :: e.source, e.source; Try-Open e.filename = { , ;; }, :: e.source, { , ;; }, e.source; Interface-Name? FILE s (e.name) (e) = e.name : \{ e.base '.rf' = e.base '.rfi'; };