// // 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 Dos ; $use Arithm ; $use Class ; $use Access ; $use Compare ; $use Convert ; $use Table ; $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 = e.source ; $func? Interface-Name? e.source = e.iname ; $func Push-Source e.source 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 ; 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.p) (WORD e.s)) = { , ;; }, { :: e.include, , e.nts ; , e.nts; } :: e.nts, (e.nts) (e.line) T; ((e) (SEMICOLON)) = (e.nts) (e.line) F; }; } :: (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?; '$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), (WORD 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 = 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 = { e.name : &RFP-Dir-Separator e = (); e.name : '.' e = (>); (>); } :: e.path, e.path : e (e.dir) e, e.dir : { e &RFP-Dir-Separator = e.dir; v = e.dir &RFP-Dir-Separator; e = /*empty*/; } :: e.dir, // { // e.name $iter { e.name : e1 '.' e2 = e1 &RFP-Dir-Separator e2; } :: e.name, // # \{ e.name : e1 '.' e2; }, e.name; // } :: e.name, { = ; e.name; } :: e.name, e.dir e.name '.rfi' :: e.full-name, { , ;; }, :: e.source, { , ;; }, e.source; Interface-Name? FILE s (e.name) (e) = e.name : \{ e.base '.rf' = e.base '.rfi'; };