CONTENTS Syntax parser example code. COPYIGHT ©1999 Dietmar Eilert. All Rights Reserved. Dietmar Eilert Mies-v-d-Rohe-Str.31, 52074 Aachen, Germany Phone: +49-(0)179-5987061 German/English E-Mail: Dietmar.Eilert@post.rwth-aachen.de E-Mail: dietmar_eilert@yahoo.de (alternative address) WWW: http://members.tripod.com/golded Mirror: http://members.xoom.com/golded ABOUT The source drawer containes three fully compilable shared libraries implemented for DICE demonstrating how one can write a syntax parser library (library code & description based on Matt Dillon's example library): Some knowledge in shared libraries is required to understand the code. The basic thing to remember is (1) that a shared library is NOT a normal C program, and (2) the interface calls MUST be reentrant, i.e. multiple tasks can make a library call simultaniously. BASICS Syntax parsers are libraries, loaded by the editor at run time. They parse the lines of a text and return syntax descriptions to the editor. Syntax parsers do not contain rendering code: The editor is responsible for rendering to the display (and for briefing the syntax scanner if the user modifies the text). Syntax scanners have to implement a fixed set of library functions used by the editor. These functions are described in "autodoc/scanlib.doc". The most important function is ParseLine(): it is called by the editor to obtain syntax desciptions while refreshing the display: The editor will pass a text line to the parser, the parser returns a syntax description. This basic mechanism is supplemented by additional library calls to support high performance syntax parsing (simple scanners may choose to ignore most of them). Two classes of syntax scanners are supported: Context scanner Context scanners understand complex syntax elements consisting of multiple lines (e.g. a C parser recognizing comments). Context scanners are the most complex scanners because they have to process every action performed by the editor: deleting the first line of a file might influence highlighting of the last line. The editor will keep the scanner up-to-date by "sending" notifies (ie. calling a scanner function). A context scanners should use a syntax chache in order to speed up parsing: results of prior parser passes should be cached for each line. Context scanners tend to be slow. A context scanner example is available as example_context. Non-context scanner Non-context scanners examine single lines only. They are unable to recognize syntax elements consisting of multiple lines. Non-context scanners are considerably less complex than context scanners. Some of them will use a syntax cache (consuming memory), some of them are fast enough to provide real-time parsing. Two examples found in the source drawer are non-context scanners highlighting C++ comments (C++ comments are introduced by a "//" and terminated by the end of the line): the first example "example_cached" uses a cache, the second example "example_simple" doesn't use a cache. FILES source/example: DEFS.H scanner independant header stuff (do not change) LIB.C scanner independant basic code (do not change) INIT.C scanner independant initialization (do not change) TAG.A scanner dependant code FUNCS.C scanner dependant code DEFS.H, LIB.C and INIT.C are scanner independant modules. Do not change these files. FUNCS.C is the parser code decribed by scanlib.doc. TAG.A is the startup code with only one modifications required if used for other projects: the name of the library. "TAG.A contains a subset of the standard startup code LIB/AMIGA/C.A and assumes non-resident compilation (i.e. you cannot use the -r option). This isn't a problem since the -r option doesn't gain you anything as far as shared libraries go. The individual library interface routines are declared with the LibCall macro, defined in DEFS.H, which ensures the small-data pointer is set up for all interface calls allowing use of the small-data model" (Matt Dillon).