mirror of
git://git.psyced.org/git/psyclpc
synced 2024-08-15 03:20:16 +00:00
305 lines
10 KiB
C
305 lines
10 KiB
C
#ifndef LEX_H__
|
|
#define LEX_H__ 1
|
|
|
|
#include "driver.h"
|
|
#include "typedefs.h"
|
|
#ifndef USE_NEW_INLINES
|
|
#include "strfuns.h"
|
|
#endif
|
|
|
|
/* --- Types --- */
|
|
|
|
typedef struct source_file_s source_file_t; /* forward */
|
|
|
|
/* --- struct source_loc_s: location within a source file ---
|
|
*
|
|
* This structure is used to identify the location of lexical elements
|
|
* in the input source. The pointers contained become invalid after
|
|
* a compilation has finished.
|
|
*/
|
|
|
|
typedef struct source_loc_s
|
|
{
|
|
source_file_t * file; /* The source file, if any, or NULL */
|
|
int line; /* The source line */
|
|
} source_loc_t;
|
|
|
|
|
|
/* --- struct source_file_s: a source file ---
|
|
*
|
|
* This structure is used to describe a source file used in the compilation.
|
|
* The embedded source_loc_t structure references the file this particular
|
|
* source file was included from.
|
|
*
|
|
* Together the structures form a tree, describing the include structure
|
|
* of the compiled program. With the end of the compilation, all contained
|
|
* pointers become invalid.
|
|
*
|
|
* The structures are additionally linked together into a singly linked list
|
|
* in order of allocation; the list is used by the lexer to deallocate the
|
|
* tree.
|
|
*/
|
|
|
|
struct source_file_s
|
|
{
|
|
source_file_t * next; /* next source_file structure, or NULL */
|
|
char * name; /* Allocated: the name of the file */
|
|
source_loc_t parent; /* the file/line this source was included from;
|
|
* or NULL if none.
|
|
*/
|
|
};
|
|
|
|
|
|
/* --- struct lpc_predef_s: predefined preprocessor macros ---
|
|
*
|
|
* The structures are used in a list to store macro definitions
|
|
* given to the driver on the commandline. The list is evaluated
|
|
* when the lexer is first initialised.
|
|
*/
|
|
|
|
struct lpc_predef_s
|
|
{
|
|
char * flag;
|
|
/* The raw text of the definition in the form 'NAME' or 'NAME=<value>'
|
|
* in its own allocated memory.
|
|
*/
|
|
struct lpc_predef_s *next;
|
|
/* Next predefinition in the list, or NULL.
|
|
*/
|
|
};
|
|
|
|
|
|
/* --- typedef defn_fun: dynamic macro expansion ---
|
|
*
|
|
* Functions of this type are used to provide dynamic macro expansions.
|
|
* When used in a macro definition instead of a static replacement text,
|
|
* they are called at every point of macro use.
|
|
*
|
|
* If the implemented macro takes no argument, NULL is passed
|
|
* in the call and the function has to return a fresh allocation of
|
|
* the replacement text.
|
|
*
|
|
* If the macro takes arguments, they are passed as char** with as
|
|
* many arguments as the definition requires. The macro has to add
|
|
* the replacement text via add_input() and return NULL.
|
|
*
|
|
* TODO: Also, the different handling of the replacement text is ugly.
|
|
*/
|
|
|
|
typedef char * (*defn_fun)(char **);
|
|
|
|
|
|
/* --- struct defn: definition of a macro ---
|
|
*
|
|
* Macros are stored in the ident_table[] as I_TYPE_DEFINEs. Their replacement
|
|
* can be given as literal text, or as the result of a function called every
|
|
* time the macro is used.
|
|
*
|
|
* The function is passed an char*[] with the current macro argument values,
|
|
* terminated with a NULL, and has to return an allocated c-string with
|
|
* the replacement text.
|
|
*
|
|
* The replacement text must not contain comments.
|
|
*
|
|
* Function macros (.nargs >= 0) expect the replacement text to contain
|
|
* special MARKS sequences ('@' followed by another character) to mark
|
|
* the places where the function arguments are to be inserted. The code
|
|
* of the second character minus ('@'+1) gives the number of the argument
|
|
* to insert. The sequence '@@' stands for the literal '@' character.
|
|
*
|
|
* Plain macros (.nargs < 0) take the replacement text as it is.
|
|
*/
|
|
|
|
struct defn
|
|
{
|
|
union { /* The replacement text: */
|
|
char *str; /* given as tabled literal (.special is false) */
|
|
defn_fun fun; /* return by fun() (.special is true) */
|
|
} exps;
|
|
short nargs; /* Number of arguments, 0 for non-function macros
|
|
*/
|
|
SBool permanent; /* true: permanent define */
|
|
SBool special; /* true: <fun> returns the replacement text */
|
|
source_loc_t loc; /* location of the definition,
|
|
* NULL for predefined macros.
|
|
*/
|
|
};
|
|
|
|
|
|
/* --- struct ident_s: known identifiers ---
|
|
*
|
|
* The structure is used to keep the information about all identifiers
|
|
* encountered so far (including reserved words, efuns, etc).
|
|
*
|
|
* There can several entries for the same identifier name but with
|
|
* different types in the table. These entries are put into a list formed
|
|
* by their .inferior pointers, sorted by falling type values. The entry
|
|
* with the highest type is the one linked into the hash chain.
|
|
*
|
|
* The identifiers are stored in a table of chains, hashed over their names.
|
|
* The most recently identifier always brought to the head of its hash-chain.
|
|
*
|
|
* Additionally, all efuns and defines are stored in their
|
|
* own 'all_...' lists, linked by the '.next_all' field.
|
|
*/
|
|
|
|
struct ident_s
|
|
{
|
|
string_t *name; /* Name of the identifier (tabled string)
|
|
* The inferiour structures (if any) and this
|
|
* structure all share the same reference to
|
|
* the string. */
|
|
short type; /* Type of this entry */
|
|
short hash; /* Hashvalue of this identifier */
|
|
ident_t *next; /* Next in hash chain */
|
|
ident_t *inferior; /* Ident of same name, but lower type */
|
|
union { /* Type-depend data: */
|
|
struct defn define; /* Macro definition */
|
|
int code; /* Reserved word: lexem code */
|
|
struct { /* Global identifier: */
|
|
short function;
|
|
/* >= 0: lfun: Index number of the lfun in den function table,
|
|
* < 0: Undefined
|
|
*/
|
|
short variable;
|
|
/* >= 0: variable: Index number in the variable table.
|
|
* During compilation, virtual variables are offset
|
|
* by VIRTUAL_VAR_TAG.
|
|
* < 0: -2: efun/sefun, -1: lfun/inherited hidden var
|
|
*/
|
|
short efun;
|
|
/* efun: Index in instrs[], negative else
|
|
* < 0: -1: gvar/sefun
|
|
*/
|
|
short sim_efun;
|
|
/* simul-efun: Index in simul_efun[], negative else
|
|
* < 0: -1: efun/gvar
|
|
*/
|
|
#ifdef USE_STRUCTS
|
|
short struct_id;
|
|
/* struct index ('id') in the current program's struct table.
|
|
* < 0: undefined
|
|
*/
|
|
#endif
|
|
} global;
|
|
struct { /* Local identifier: */
|
|
int num; /* Number, also the index on the stack */
|
|
int context; /* -1 for normal locals, or the index
|
|
* in the context frame. In that case,
|
|
* .num is either -1 or the index
|
|
* of the related local of the defining
|
|
* function.
|
|
*/
|
|
int depth; /* Definition depth */
|
|
} local;
|
|
} u;
|
|
ident_t *next_all; /* 'all_...' list link */
|
|
};
|
|
|
|
/* ident_t.type values: */
|
|
|
|
#define I_TYPE_UNKNOWN 0
|
|
#define I_TYPE_GLOBAL 2 /* function, variable or efuns/simul_efuns */
|
|
#define I_TYPE_LOCAL 3
|
|
#define I_TYPE_RESWORD 4 /* reserved word */
|
|
#define I_TYPE_DEFINE 5
|
|
|
|
/* ident_t.global magic values */
|
|
|
|
#define I_GLOBAL_FUNCTION_OTHER (-1)
|
|
#define I_GLOBAL_VARIABLE_OTHER (-1)
|
|
#define I_GLOBAL_VARIABLE_FUN (-2)
|
|
#define I_GLOBAL_EFUN_OTHER (-1)
|
|
#define I_GLOBAL_SEFUN_OTHER (-1)
|
|
#ifdef USE_STRUCTS
|
|
#define I_GLOBAL_STRUCT_NONE (-1)
|
|
#endif
|
|
|
|
|
|
#define lookup_predef(p) (p->type == I_TYPE_GLOBAL ? p->u.global.efun : -1)
|
|
|
|
|
|
#ifndef USE_NEW_INLINES
|
|
/* --- struct inline_fun: linked list element of saved function texts ---
|
|
*
|
|
* The functions inlined by (: ... :) have their code (plus the function
|
|
* header and trailer) saved for later parsing in a list of these
|
|
* structures.
|
|
*/
|
|
|
|
struct inline_fun
|
|
{
|
|
strbuf_t buf; /* the complete function text */
|
|
struct inline_fun * next; /* next list element */
|
|
};
|
|
#endif /* USE_NEW_INLINES */
|
|
|
|
|
|
/* --- Variables --- */
|
|
|
|
extern struct lpc_predef_s * lpc_predefs;
|
|
extern int total_lines;
|
|
extern source_loc_t current_loc;
|
|
extern int pragma_strict_types;
|
|
extern Bool pragma_use_local_scopes;
|
|
extern Bool pragma_save_types;
|
|
extern Bool pragma_combine_strings;
|
|
extern Bool pragma_verbose_errors;
|
|
extern Bool pragma_no_clone;
|
|
extern Bool pragma_no_inherit;
|
|
extern Bool pragma_no_shadow;
|
|
extern Bool pragma_pedantic;
|
|
extern Bool pragma_range_check;
|
|
extern Bool pragma_warn_missing_return;
|
|
extern Bool pragma_warn_deprecated;
|
|
extern Bool pragma_warn_empty_casts;
|
|
extern Bool pragma_check_overloads;
|
|
extern Bool pragma_share_variables;
|
|
extern string_t *last_lex_string;
|
|
extern ident_t *all_efuns;
|
|
#ifndef USE_NEW_INLINES
|
|
extern struct inline_fun * first_inline_fun;
|
|
extern Bool insert_inline_fun_now;
|
|
extern unsigned int next_inline_fun;
|
|
#endif /* USE_NEW_INLINES */
|
|
|
|
/* Values of pragma_strict_types */
|
|
|
|
#define PRAGMA_WEAK_TYPES 0
|
|
#define PRAGMA_STRONG_TYPES 1
|
|
#define PRAGMA_STRICT_TYPES 2
|
|
|
|
|
|
/* --- Prototypes --- */
|
|
|
|
extern void init_lexer(void);
|
|
extern int symbol_operator(const char *symbol, const char **endp);
|
|
extern void symbol_efun_str(const char *str, size_t len, svalue_t *sp, Bool is_efun);
|
|
extern void symbol_efun(string_t *name, svalue_t *sp);
|
|
extern void init_global_identifier (ident_t * ident, Bool bVariable);
|
|
extern ident_t *lookfor_shared_identifier(char *, int, int, Bool);
|
|
#define make_shared_identifier(s,n,d) lookfor_shared_identifier(s,n,d, MY_TRUE)
|
|
#define find_shared_identifier(s,n,d) lookfor_shared_identifier(s,n,d, MY_FALSE)
|
|
extern ident_t *make_global_identifier(char *, int);
|
|
extern void free_shared_identifier(ident_t*);
|
|
extern int yylex(void);
|
|
extern void end_new_file(void);
|
|
extern void lex_close(char *msg);
|
|
extern void start_new_file(int fd, const char * fname);
|
|
extern char *get_f_name(int n);
|
|
extern void free_defines(void);
|
|
extern size_t show_lexer_status (strbuf_t * sbuf, Bool verbose);
|
|
extern void set_inc_list(vector_t *v);
|
|
extern void remove_unknown_identifier(void);
|
|
extern char *lex_error_context(void);
|
|
extern svalue_t *f_expand_define(svalue_t *sp);
|
|
extern char * lex_parse_number (char * cp, unsigned long * p_num, Bool * p_overflow);
|
|
#ifdef USE_NEW_INLINES
|
|
extern void * get_include_handle (void);
|
|
#endif /* USE_NEW_INLINES */
|
|
|
|
#ifdef GC_SUPPORT
|
|
extern void count_lex_refs(void);
|
|
#endif /* GC_SUPPORT */
|
|
|
|
#endif /* LEX_H__ */
|