// // 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_parse.rfi $use "rfpc" ; // rfpc.rfi $use "rfp_helper" ; // rfp_helper.rfi $use "rfp_src" ; // rfp_src.rfi $use "rfp_err" ; // rfp_err.rfi $use Box ; $use Convert ; $use Compare ; $use Table ; $use StdIO ; $use Arithm ; $use Access ; $func Parse-Body = e.items ; $func Parse-Const-Decls = e.items ; // $func Parse-Const-Decl e.name = e.items ; $func Parse-Const-Expr = e.expr ; $func Parse-Const-Term (e.pos) (s.type e.value) = e.term ; $func Module-Name = e.name ; $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 Full-Name s.idx (e.name) = e.fullname ; $func? Lookup-Name (e.pos) (e.name) = e.fullname ; $func Lookup-Check (e.pos) (e.name) (e.fullname) (e.rest) = ; $func Bind-Name (e.name) ((e.pos) e.info) = ; $func? Get-Token = (e.pos) (s.type e.value) ; $func Unget-Token e.token = ; $func? Expect-Token e.types = (e.pos) (s.type e.value) ; $func Token-Descr s.type = e.string ; $func Parse-Format = e.format ; $func Parse-Format-Terms = e.terms ; $func Parse-Result = e.format ; $func Parse-Result-Term = e.terms ; $func Parse-Hard-Expr = e.format ; $func Parse-Hard-Expr-Terms = e.terms ; $func Parse-Sentence e.colon-pos = e.items ; $func Parse-Pattern e.colon-pos = e.items ; $func Parse-Pattern-Expr = e.items ; $func Parse-Pattern-Term = e.items ; $func Parse-Ref = e.items ; $func? Tail? = ; $func Parse-Path = e.items ; $func Parse-Source = e.items ; $func Parse-Tail = e.items ; $func Parse-Alt e.colon-pos = e.items ; $func Make-Name2 e.sname = e.name ; $func Parse-Imports = e.imports ; $func? Interface? = ; $func Canonical-Name s.type e.name = e.name; $func Canonical-Word e.value = s.word; $func Pragma e.pos = (PRAGMA e.PragmaBody); $box Module-Name-Box ; $box Saved-Position ; $box Unget-Stack ; $table Constants ; $table Names ; $box Traceall? ; // 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 = "'='"; 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"; USE = "$use"; TRACE = "$trace"; TRACEALL = "$traceall"; s.type = "token " s.type; }; // This function returns a next token Get-Token // [] = (e.pos) (s.type e.value) = { // First check if there are any tokens in unget stack : (e.tokens) ((e.pos) (s.type e.value)) = , (e.pos) (s.type e.value); // If unget stack is empty, get a token in a usual way : (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.token = ) (e.token)>; // 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.message : T; s.type : EOF; }, )>, $fail; F ; } :: s.message (e.pos) (s.type e.value), e.types : \{ e s.type e = //, (e.pos) (s.type e.value); e EMPTY e = //, , (e.pos) (EMPTY); }; RFP-Parser = , , , >>, // $trap { , (INTERFACE > ); (MODULE > ); } // $with { // e = :: e.pos, // , // FAIL; // }; ; // This is a shortcut function to get a module name Module-Name = ; Interface? = : e '.rfi'; // 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 : USE = ; // If token type is CONST then parse constant declaration s.type : CONST = ; s.type : TRACE = ; s.type : TRACEALL = , : e; s.type : EXTERN = ; s.type : \{ FUNC; FUNC?; TFUNC; } = ; s.type : \{ WORD; QWORD; } = ; # \{ s.type : EOF; } ; } :: e.items = e.items ; // If there are no tokens and we aren't processing an interface file then // check for undefined functions. = ; (/*e.undefs*/) $iter { e.domain : e (e.name) e.rest, : (e.decl-pos) (e.decl-name) s.tag s.linkage t.in t.out, s.linkage : \{ LOCAL; EXPORT; } = , e.rest (e.undefs (UNDEF s.tag t.in t.out)); /*empty*/ (e.undefs); } :: e.domain (e.undefs), e.domain : /*empty*/ = e.undefs; }; Parse-Imports // [] = e.imports = :: (e.pos) (s.type e.value), { s.type : SEMICOLON; (USE ) ; }; Parse-Object-Decls s.type = { : { (e) (SEMICOLON) = ; (e.pos) (s.WORD-or-QWORD e.name) = e.pos : { s S s s = LOCAL (); s.idx e = { > :: e.module, <"/=" (e.module) ()>, IMPORT (e.module); EXPORT (); }; } :: s.linkage (e.module), e.module '.' e.name :: e.name, ) ((e.pos) (e.name) s.type)>, (s.linkage s.type ) ; }; }; Parse-Const-Expr = :: (e.pos) (s.type e.value), { s.type : EMPTY = ; ; }; Parse-Const-Term (e.pos) (s.type e.value) = s.type : { REF = ; SYMBOLS = e.value; NUMBER = e.value; WORD = ; QWORD = ; LPAREN = :: e.expr, : e, (PAREN e.expr); }; Parse-Const-Decls = :: (e.pos) (s.type e.value), s.type : { SEMICOLON = ; COMMA = ; s.WORD-or-QWORD = : e, :: e.expr, e.pos : { s S s s = LOCAL (); s.idx e = { > :: e.module, <"/=" (e.module) ()>, IMPORT (e.module); EXPORT (); }; } :: s.linkage (e.module), e.module '.' e.value :: e.name, ) ((e.pos) (e.name) CONST)>, (s.linkage CONST e.expr) ; // >; }; /* Parse-Const-Decl e.name = : e, :: e.expr, , (CONST e.expr) ; Full-Name s.idx (e.name) = > '.' e.name; */ Lookup-Name (e.pos) (e.name) = : \{ e (e.name) e.rest = (e.name) (e.rest); e (e.module '.' e.name) e.rest = (e.module '.' e.name) (e.rest); } :: (e.fullname) (e.rest), , e.fullname; Lookup-Check (e.pos) (e.name) (e.fullname) (e.names) = { e.names : \{ e (e.name) e.rest = (e.name) (e.rest); e (e.module '.' e.name) e.rest = (e.module '.' e.name) (e.rest); } :: (e.other) (e.rest), , ;; }; Bind-Name (e.name) ((e.pos) e.info) = { : (e.prev-pos) e = , ;; }, ; Parse-Extern-Names = : { e (SEMICOLON) = ; (e.pos) (s.type e.value) = ) ((e.pos) (e.value) FUNC? EXTERN ((EVAR)) ((EVAR)))>, (EXTERN ) ; }; Parse-Func-Decl // s.type = e.items s.type = :: (e.pos) (s.WORD-or-QWORD e.name), e.pos : { s S s s = LOCAL (); s.idx e = { > :: e.module, <"/=" (e.module) ()>, IMPORT (e.module); EXPORT (); }; } :: s.linkage (e.module), e.module '.' e.name :: e.name, :: e.in, : e, :: e.out, : e, ) ((e.pos) (e.name) s.type s.linkage (e.in) (e.out))>, { \{ s.linkage : IMPORT; ; } = (s.linkage s.type (e.in) (e.out)); ; }; Parse-Format // [] = e.format = :: e.terms, :: (e.pos) (s.type e.value), { s.type : EMPTY = ; (s.type); } :: e.var, e.terms e.var ; Parse-Format-Terms // [] = e.terms = :: (e.pos) (s.type e.value), { s.type : EMPTY = ; s.type : { LPAREN = (PAREN ) :: e.hexpr, : e, e.hexpr; SYMBOLS = e.value; NUMBER = e.value; WORD = ; QWORD = ; REF = ; s = (s.type); } :: e.term, e.term ; }; Parse-Hard-Expr // [] = e.format = //, :: e.terms, :: (e.pos) (s.type e.value), { s.type : EMPTY = ; (s.type ); } :: e.var, e.terms e.var ; Parse-Hard-Expr-Terms // [] = e.terms = //, :: (e.pos) (s.type e.value), { s.type : EMPTY = ; s.type : { LPAREN = (PAREN ) :: e.hexpr, : e, e.hexpr; SYMBOLS = e.value; NUMBER = e.value; WORD = ; QWORD = ; REF = ; s = (s.type ); } :: e.term, e.term ; }; Parse-Trace-Names = : { e (SEMICOLON) = ; (e.pos) (s.type e.value) = :: e.uniname, { :: e.name = : { (e.pragma-pos) (e.origname) FUNC e = e.origname; (e.pragma-pos) (e.origname) FUNC? e = e.origname; (e.pragma-pos) (e.origname) TFUNC e = e.origname; (e.pragma-pos) (e.origname) s.decl e = , ; }; \{ e.value : 'Main'; , : 'MAIN'; } = '.' e.value ; ; } :: e.name, { e.name : v = (TRACE ) ; ; }; }; Parse-Func-Def // (e.pos) (s.type e.value) = e.items (e.pos) (s.type e.value) = //, :: e.items, : e, :: e.uniname, //, { :: e.name = //>, :: e.nameinfo = //, { : (Def e.def-pos) = , ;; }, e.nameinfo : { (e.pragma-pos) (e.origname) FUNC s.linkage t.in t.out e = , e.origname FUNC s.linkage t.in t.out ; (e.pragma-pos) (e.origname) FUNC? s.linkage t.in t.out e = , e.origname FUNC? s.linkage t.in t.out ; (e.pragma-pos) (e.origname) TFUNC s.linkage t.in t.out e = , e.origname TFUNC s.linkage t.in t.out ; (e.pragma-pos) (e.origname) s.decl e = , , , e.origname FUNC LOCAL () () ; }; \{ e.value : 'Main'; , : 'MAIN'; } = '.' e.uniname) ((e.pos) (e.value) FUNC EXPORT () ((EVAR)) (Def e.pos))>, '.' e.value FUNC EXPORT () ((EVAR)) ; , , e.value FUNC LOCAL () () ; } :: e.name s.tag s.linkage t.in t.out t.pragma, { : v = (TRACE );; } :: e.trace, { s.linkage : EXTERN = EXPORT; s.linkage; } :: s.linkage, (s.linkage s.tag t.pragma t.in t.out (BRANCH e.items) ) e.trace; Parse-Alt e.colon-pos // = e.items = :: (e.pos) (s.type e.value), { s.type : EMPTY = ; (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), { e.items : = (LEFT ); { s.type : LBRACE = (BLOCK e.items); (BLOCK? e.items); }; }; }; Parse-Sentence e.colon-pos // = e.items = //, :: e.pattern, :: e.tail, e.pattern e.tail; Tail? // [] = [] = :: (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 ); } :: e.items, e.items $iter { :: (e.p) (s.t e.v), , s.t : \{ LBRACE; TLBRACE; } = e.items ; , e.items (e.pos) (EMPTY); } :: e.items (e.pos) (s.type e.value), s.type : EMPTY = e.items; Parse-Result // [] = e.items = //, { : v.term = v.term ; ; }; Parse-Result-Term // [] = e.items = //, :: (e.pos) (s.type e.value), { s.type : EMPTY = ; s.type : SYMBOLS = e.value; s.type : NUMBER = e.value; s.type : REF = ; s.type : LPAREN = :: e.items, : e, (PAREN e.items); s.type : \{ EVAR; VVAR; TVAR; SVAR; } = (s.type ); s.type : WORD = ; s.type : QWORD = ; s.type : LBRACKET = :: (e.pos) (s.type e.value), :: e.uniname, { :: e.name = : (e.decl-pos) (e.origname) s.decl-type e.nameinfo = { s.decl-type : \{ FUNC e; FUNC? e; TFUNC e; } = e.origname; , , e.origname; }; , e.value; } :: e.name, (CALL ) :: e.items, : e, e.items; 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); }; }; Parse-Pattern e.colon-pos // = e.items = : (e.pos) (s.type e), (e.colon-pos) (e.pos) : e (v.p) e, { s.type : R = (RIGHT ); (LEFT ); }; Parse-Pattern-Expr // [] = e.items = //, { : v.term = v.term ; ; }; Parse-Pattern-Term // [] = e.items = //, :: (e.pos) (s.type e.value), { s.type : EMPTY = ; s.type : SYMBOLS = e.value; s.type : NUMBER = e.value; s.type : WORD = ; s.type : QWORD = ; s.type : REF = ; s.type : LPAREN = :: e.items, : e, (PAREN e.items); s.type : \{ EVAR; VVAR; TVAR; SVAR; } = (s.type ); }; Parse-Ref // [] = e.items = :: (e.pos) (s.type e.value), :: e.uniname, { :: e.name = : (e.decl-pos) (e.origname) s.decl-type e.nameinfo, (REF ); , (REF ); }; Make-Name // e.sname = t.name e.sname = (>); Make-Name2// e.sname = e.name { e.item '.' e.rest = ; e.item = ; }; Canonical-Name s.type e.name, { s.type : WORD, = ; e.name; }; Canonical-Word e.value, { = >; ; }; Pragma s.idx s s.line s.col = (PRAGMA (FILE ) (LINE s.line s.col));