// // 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 $use "rfp_helper" "rfp_src" "rfp_lex" ; $use Access Arithm Box Convert Compare List Table StdIO ; $func Token_Descr s.type = e.string ; $func? Get_Token = (e.pos) (s.type e.value) ; $func Unget_Token (e.pos) (s.type e.value) = ; $func Put_Tokens e.token = ; $func? Expect_Token e.types = (e.pos) (s.type e.value) ; $func? Get_Expected_Token e.types = (e.pos) (s.type e.value) ; $func Parse_Body = e.items ; $func Parse_Const_Decls = e.items ; $func Parse_Object_Decls s.type = e.items ; $func Parse_Extern_Names = e.extern_decls; $func Parse_Func_Decl s.type = e.items ; $func Parse_Trace_Names = e.trace_directives ; $func Parse_Func_Def (e.pos) (s.type e.value) = e.items ; $func? IsTail = ; $func Parse_Path = e.items ; $func Parse_Source = e.items ; $func Parse_Tail = e.items ; $func Parse_Module_Name = ; $func Parse_Imports s.type = e.imports ; $func Parse_Pattern e.colon_pos = e.items ; $func? Parse_PatternAlt e.colon_pos = e.items; $func Parse_Sentence e.colon_pos = e.items; $func Parse_PatternSource = e.items; $func Parse_Const_Expr = e.expr ; $func? Parse_Const_Term = e.term ; $func Parse_Format = e.format ; $func Parse_Format_Terms = e.terms ; $func Parse_Hard_Expr = e.expr ; $func Parse_Hard_Expr_Terms = e.terms ; $func Parse_Result = e.result ; $func? Parse_Result_Term = e.term ; $func Parse_Pattern_Expr = e.expr ; $func? Parse_Pattern_Term = e.term ; $func? Parse_Ground_Term = e.term ; $func Bind_Name (e.qname) ((e.pos) e.info) = ; $func Lookup_Name (e.pos) (s.WORDorQWORD e.origName) = e.qname ; $func? Make_Decl_Name s.WORDorQWORD e.origName = s.linkage e.qname; $func Canonical_Word e.value = s.word; $func Pragma e.pos = (PRAGMA e.PragmaBody); $func Add_Error (e.pos) (e.msg) = ; $func Add_Warning (e.pos) (e.msg) = ; $func Add_Errors (e.moduleName) e.errors = ; $box Module_Name ; $box Current_Module ; $box Token_Stack ; $table Names ; $table Upper_Names ; $table ImplemNames ; $box IsTraceall ; $box Errors ; RFP_Parser_Errors = ; Add_Error (e.pos) (e.msg) = ) (e.pos)) (e.msg))>; Add_Warning (e.pos) (e.msg) = ) (e.pos)) (e.msg))>; Add_Errors (e.moduleName) e.errors, { e.errors : e (s.type (e.pos) (e.msg)) e, , $fail;; }; // This function returns a token description according // to its type Token_Descr // s.type = e.string { COMMA = "\',\'"; COLON = "\':\'"; DCOLON = "\'::\'"; SEMICOLON = "\';\'"; LBRACE = "'{'"; RBRACE = "'}'"; LBRACKET = "'<'"; RBRACKET = "'>'"; LPAREN = "'('"; RPAREN = "')'"; REF = "'&'"; NOT = "'#'"; EQUAL = "'='"; COMMENT = "comment"; EOF = "end of file"; EVAR = "e-variable"; VVAR = "v-variable"; TVAR = "t-variable"; SVAR = "s-variable"; BOX = "$box"; TABLE = "$table"; VECTOR = "$vector"; STRING = "$string"; FUNC = "$func"; "FUNC?" = "$func?"; TFUNC = "$tfunc"; EXTERN = "$extern"; CHANNEL = "$channel"; MODULE = "$module"; USE = "$use"; IMPORT = "$import"; TRACE = "$trace"; TRACEALL = "$traceall"; R = "$r"; L = "$l"; s.type = "token " s.type; }; // This function returns a next token Get_Token // [] = (e.pos) (s.type e.value) = : (e.token) e.rest, , e.token : (e.pos) (s.type e.value), (e.pos) (s.type e.value); // This function puts a token to unget stack for future use Unget_Token // e.token = [] (e.pos) (s.type e.value) = >; Put_Tokens // e.token = [] e.tokens = >; // TODO : Remove this function and add correct error processing // This function scans for a token of one of specified types Expect_Token // e.types = (e.pos) (s.type e.value) e.types = T $iter \{ s.type : COMMENT = s.message ; \{ s.message : T; s.type : EOF; }, )>, $fail; F ; } :: s.message (e.pos) (s.type e.value), # \{ s.type : COMMENT; }, e.types : \{ e s.type e = //, (e.pos) (s.type e.value); e EMPTY e = //, , (e.pos) (EMPTY); }; // This function scans for a token of one of specified types (no EMPTY) Get_Expected_Token e.types = // (e.pos) (s.type e.value) :: (e.pos) (s.type e.value), { e.types : e s.type e = (e.pos) (s.type e.value); s.type : COMMENT = ; = e.types : e EMPTY e, (e.pos) (EMPTY); }; RFP_Parser t.fileId = , , , { ; = , $fail; } :: e.reader (e.qname), , { :: e.reader, ; () (); } :: (e.interf_tokens) (e.errors), , :: (e.implem_tokens) (e.errors), , , { : e (ERROR e) e = $fail; , // $trap :: e.items, { : e (ERROR e) e = $fail; (MODULE () e.items); } ; // $with { // e "Unexpected fail" = $fail; // e.err = $error e.err; // }; }; RFP_Parse_Tokens (e.qname) e.tokens = , , ; // The main parsing routine Parse_Body = { :: (e.pos) (s.type e.value), // , \{ // If token type is BOX, TABLE, VECTOR, STRING or CHANNEL // then parse object declaration s.type : \{ BOX; TABLE; VECTOR; STRING; CHANNEL; } = ; s.type : MODULE = ; s.type : \{ USE; IMPORT; } = ; s.type : CONST = ; s.type : TRACE = ; s.type : TRACEALL = , : e; s.type : EXTERN = ; s.type : \{ FUNC; "FUNC?"; TFUNC; } = ; s.type : \{ WORD; QWORD; } = ; s.type : BOF = { e.value : RF e = >, ; , ; }; s.type : EOF = { : e ((e.k) (e.v)) e, , $fail;; }; # \{ s.type : EOFS; } ; } :: e.items = e.items ; // If there are no tokens and we aren't processing an interface file then // check for undefined functions. : RFI e = ; (/*e.undefs*/) $iter { e.domain : e (e.name) e.rest, : (e.decl_pos) (e.origname) s.tag s.linkage t.in t.out, s.linkage : \{ LOCAL; EXPORT; } = , e.rest (e.undefs (UNDEF s.tag (e.name) t.in t.out)); /*empty*/ (e.undefs); } :: e.domain (e.undefs), e.domain : /*empty*/ = e.undefs; }; Parse_Module_Name = :: (e.pos) (s.type e.origname), :: e.modulename, { () () : (RFI e1) (e1) = , ; : RFI e.modulename; : RFI e.modname, )>; }, : e; Parse_Imports s.itype // s.itype = e.imports = Continue $iter { :: (e.pos) (s.type e.origname), { s.type : SEMICOLON = Stop e.tokens; s.itype : \{ USE = >; IMPORT = >; } :: e.reader (e.qname), :: (e.toks) (e.errors), , , Continue e.tokens (() (BOF RFI e.qname)) e.toks; , Continue e.tokens; }; } :: s.Isstop e.tokens, s.Isstop : Stop = ))>; Parse_Object_Decls s.type = : { (e) (SEMICOLON) = ; (e.pos) (s.WORD_or_QWORD e.origname) = :: s.linkage e.qname, , (s.linkage s.type (e.qname)) ; }; Parse_Const_Decls = : { (e) (SEMICOLON) = ; (e) (COMMA) = ; (e.pos) (s.WORD_or_QWORD e.origname) = : e, :: e.expr, :: s.linkage e.qname, , (s.linkage CONST (e.qname) e.expr) ; }; Parse_Extern_Names = : { e (SEMICOLON) = ; (e.pos) (s.WORD_or_QWORD e.origname) = : t.name, , (EXTERN (t.name)) ; }; Parse_Func_Decl // s.type = e.items s.type = :: (e.pos) (s.WORD_or_QWORD e.origname), :: s.linkage e.qname, , :: e.in, : e, :: e.out, : e, , { \{ s.linkage : IMPORT; // : RFI e; } = (s.linkage s.type (e.qname) (e.in) (e.out)); ; }; Parse_Trace_Names = : { e (SEMICOLON) = ; (e.pos) (s.WORD_or_QWORD e.origtracename) = :: s e.qname, { : (e.declPos) (e.origDeclName) s.declType e, { # s.declType : \{ FUNC; "FUNC?"; TFUNC; }, , ;; }; e.qname : s1 e s1; ; }, (TRACE (e.qname)) ; }; Parse_Func_Def // (e.pos) (s.type e.value) = e.items (e.pos) (s.WORD_or_QWORD e.funcorigname) = //, :: e.items, : e, :: s e.qname, { :: e.nameinfo = { e.nameinfo : (e) (e.origname) e (Def e.def_pos) = , ;; }, e.nameinfo : (e.pragma_pos) (e.origname) s.declType s.linkage t.in t.out e = { s.declType : \{ FUNC; "FUNC?"; TFUNC; }, , e.qname s.declType s.linkage t.in t.out ; , , e.qname FUNC LOCAL () () ; }; e.qname : s1 e s1, , e.qname FUNC EXPORT () ((EVAR)) ; , , e.qname FUNC LOCAL ((EVAR)) ((EVAR)) ; } :: e.qname s.tag s.linkage t.in t.out t.pragma, { : v = (TRACE (e.qname));; } :: e.trace, { s.linkage : EXTERN = EXPORT; s.linkage; } :: s.linkage, (s.linkage s.tag t.pragma (e.qname) t.in t.out (BRANCH e.items) ) e.trace; IsTail // [] = [] = :: (e.pos) (s.type e.value), \{ s.type : EMPTY = $fail; ; }; Parse_Tail // [] = e.items = //, :: (e.pos) (s.type e.value), s.type : { COMMA = ; NOT = (NOT (BRANCH )) ; STAKE = (STAKE ) ; CUT = (CUT ) ; FAIL = (FAIL ); EQUAL = (CUTALL ) ; ERROR = (ERROR ) ; TRAP = :: e.try, : e, (TRY (BRANCH e.try) ); EMPTY = (RESULT ); }; Parse_Path // [] = e.item = //, { , ; :: e.source, { , ; :: (e.pos) (s.type e), s.type : { DCOLON = (FORMAT ) ; ITER = :: e.body, { = (ITER (BRANCH e.body) (FORMAT ) (BRANCH ) ); :: (e.dcolon_pos) t, (ITER (BRANCH e.body) (FORMAT ) (BRANCH ) ); }; COLON = ; EMPTY = ; }; } :: e.items, e.source e.items; }; Parse_Source // [] = e.item = // :: (e.pos) (s.type e), // { // s.type : // \{ // LBRACE; // TLBRACE; // } = // (e.pos) /*empty*/ $iter // { // e.items (BRANCH ) :: e.items, // :: (e.snt-end-pos) t, // (e.snt-end-pos) e.items; // } :: (e.snt-end-pos) e.items, // : (e) (RBRACE e), // { // s.type : LBRACE = (BLOCK e.items); // (BLOCK? e.items); // }; :: (e.pos) e, (RESULT ) ; // }; Parse_Sentence e.colon_pos = { :: e.source = { , ; :: (e.pos) (s.type e), s.type : { DCOLON = (FORMAT ) ; ITER = :: e.body, { = (ITER (BRANCH e.body) (FORMAT ) (BRANCH ) ); :: (e.dcolon_pos) t, (ITER (BRANCH e.body) (FORMAT ) (BRANCH ) ); }; COLON = ; EMPTY = ; }; } :: e.items, e.source e.items; ; }; Parse_PatternSource = { :: (e.p) (s.t e.v), { ; ; };; }; Parse_PatternAlt e.colon_pos // = e.items = :: (e.pos) (s.type e.value), { (e.pos) /*empty*/ $iter { e.items (BRANCH ) :: e.items, :: (e.snt_end_pos) t, (e.snt_end_pos) e.items; } :: (e.snt_end_pos) e.items, : e, { s.type : LBRACE = (BLOCK e.items); ("BLOCK?" e.items); }; }; Parse_Pattern e.colon_pos = // e.pattern :: (e.pos) (s.type e), (e.colon_pos) (e.pos) : e (v.p) e, { s.type : R = RIGHT; LEFT; } :: s.type, (s.type ); Parse_Const_Expr = // e.expr { ;; }; Parse_Const_Term = // e.term \{ ; :: (e.pos) (s.type e.value), :: e.expr, : e, (PAREN e.expr); }; Parse_Format = // e.format :: e.terms1, { :: (e.pos) (s.type e.value), (s.type) ;; } :: e.terms2, e.terms1 e.terms2; Parse_Format_Terms = // e.terms { \{ ; :: (e.pos) (s.type e.value), { s.type : LPAREN = :: e.format, : e, (PAREN e.format); (s.type); }; } :: e.term, e.term ;; }; Parse_Hard_Expr = // e.expr :: e.terms1, { :: (e.pos) (s.type e.value), (s.type (e.value)) ;; } :: e.terms2, e.terms1 e.terms2; Parse_Hard_Expr_Terms = // e.terms { \{ ; :: (e.pos) (s.type e.value), { s.type : LPAREN = :: e.expr, : e, (PAREN e.expr); (s.type (e.value)); }; } :: e.term, e.term ;; }; Parse_Result = // e.result { ;; }; Parse_Result_Term = // e.term \{ ; :: (e.pos) (s.type e.value), { s.type : \{ EVAR; SVAR; TVAR; VVAR; } = (s.type (e.value)); s.type : LPAREN = :: e.result, : e, (PAREN e.result); s.type : LBRACKET = { :: (e.pos) (s.WORDorQWORD e.origCallName), :: e.qname, { : (e.declPos) (e.origDeclName) s.declType e, # s.declType : \{ FUNC; "FUNC?"; TFUNC; }, , ;; }, e.qname; " should be followed by an identifier")>; } :: e.qname, (CALL (e.qname) ) :: e.term, : e, e.term; s.type : \{ LBRACE; TLBRACE; } = (e.pos) /*empty*/ $iter { e.items (BRANCH ) :: e.items, :: (e.sntEndPos) t, (e.sntEndPos) e.items; } :: (e.sntEndPos) e.items, : e, // TODO: is it good for error correction? { s.type : LBRACE = (BLOCK e.items); ("BLOCK?" e.items); }; }; }; Parse_Pattern_Expr = // e.expr { ;; }; Parse_Pattern_Term = // e.term \{ ; :: (e.pos) (s.type e.value), { s.type : \{ EVAR; SVAR; TVAR; VVAR; } = (s.type (e.value)); s.type : LPAREN = :: e.expr, : e, (PAREN e.expr); }; }; Parse_Ground_Term = // e.term :: (e.pos) (s.type e.value), s.type : { NUMBER = e.value; SYMBOLS = e.value; WORD = ; QWORD = ; REF = { (REF (>)); " should be followed by an identifier")>; }; }; Bind_Name (e.qname) ((e.pos) e.info) = { : (e.prevPos) e = e.info : (e.origName) e, , ;; }, ; Lookup_Name (e.pos) (s.WORDorQWORD e.origName) = :: e.name, { \{ s.WORDorQWORD : WORD, = e.name : e.m s.n, e.m >> :: e.name, : e (e.module e.name) e.rest = () (e.name) e.rest; : e (e.module e.name) e.rest = (e.module e.name) (e.name) e.rest; } :: (e.qname) (e.name) e.rest = { e.rest : e (e.module2 e.name) e, "\' and \'" "\' do exist")>, $fail;; }, e.qname; , e.name; }; Make_Decl_Name s.WORDorQWORD e.origName = :: e.name, { e.name : t = : { RF e.moduleName = LOCAL e.moduleName; RFI e.moduleName = { : e.moduleName = EXPORT e.moduleName; IMPORT e.moduleName; }; } :: s.linkage e.moduleName, { s.WORDorQWORD : WORD, = >>) (e.moduleName e.name)>;; }, s.linkage e.moduleName e.name; = $fail; }; Canonical_Word e.value, { = >; ; }; Pragma (e.pos) e = (PRAGMA (FILE ) (LINE e.pos));