// // 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-Func-Decl s.type = e.items ; $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 Pragma e.pos = (PRAGMA e.PragmaBody); $box Module-Name-Box ; $box Saved-Position ; $box Unget-Stack ; $table Constants ; $table Names ; // 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 = "'&'"; 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?"; CHANNEL = "$channel"; USE = "$use"; 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; } = ; // If token type is CONST then parse constant declaration s.type : USE = ; s.type : CONST = ; s.type : \{ FUNC; FUNC?; } = ; s.type : WORD = //, // (FUNCDEF '.' e.value> ) ; ; # \{ 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 (e.name) e, : (e.decl-pos) s.tag s.linkage t.in t.out, s.linkage : \{ LOCAL; EXPORT; }, , $fail; // ...and return. ; }; Parse-Imports // [] = e.imports = :: (e.pos) (s.type e.value), { s.type : WORD = (USE ) ;; }; Parse-Object-Decls s.type = { : { (e) (SEMICOLON) = ; (e.pos) (WORD 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, , (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 = ; LPAREN = :: e.expr, : e, (PAREN e.expr); }; Parse-Const-Decls = :: (e.pos) (s.type e.value), s.type : { WORD = : 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, , (s.linkage CONST e.expr) ; // >; SEMICOLON = ; COMMA = ; }; /* 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-Func-Decl // s.type = e.items s.type = :: (e.pos) (s 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, , { \{ 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 = ; 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 = ; REF = ; s = (s.type ); } :: e.term, e.term ; }; Parse-Func-Def // (e.pos) (s.type e.value) = e.items (e.pos) (s.type e.value) = //, :: e.items, : e, //, { :: e.name = //>, :: e.nameinfo = //, { : (Def e.def-pos) = , ;; }, e.nameinfo : { (e.pragma-pos) FUNC s.linkage t.in t.out e = , e.name FUNC s.linkage t.in t.out ; (e.pragma-pos) FUNC? s.linkage t.in t.out e = , e.name FUNC? s.linkage t.in t.out ; (e.pragma-pos) s.decl e = , , , e.name FUNC LOCAL () () ; }; e.value : \{ 'Main'; 'MAIN', ; } = '.' e.value) ((e.pos) 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, (s.linkage s.tag t.pragma t.in t.out (BRANCH e.items) ); 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, :: (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); }; (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 : WORD = ; s.type : REF = ; s.type : LPAREN = :: e.items, : e, (PAREN e.items); s.type : \{ EVAR; VVAR; TVAR; SVAR; } = (s.type ); s.type : LBRACKET = :: (e.pos) (s.type e.value), { :: e.name = : (e.decl-pos) s.decl-type e.nameinfo = { s.decl-type : \{ FUNC e; FUNC? e; } = e.name; , , e.name; }; , e.value; } :: e.name, (CALL ) :: e.items, : e, 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 : 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.name = // :: e.nameinfo = // { // e.nameinfo : CONST e.expr = e.expr; (REF ); // }; , (REF ); }; Make-Name // e.sname = t.name e.sname = (>); Make-Name2// e.sname = e.name { e.item '.' e.rest = ; e.item = ; }; Pragma s.idx s s.line s.col = (PRAGMA (FILE ) (LINE s.line s.col));