spinau / uuscan

header-only lexical scanning for recursive descent parsing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

uuscan.h provides single-header low-overhead tokenless helper functions for
scanning lexical elements in recursive descent parsing (with backtracking).

It could be useful for small command-languages, DSL's, or other ad-hoc
parsing jobs where integrating lex and yacc or other tools is too expensive
and using straight strcmp's too tedious.

The two main functions provided are the self-documenting accept() and expect().
Errors are typically handled by a non-local goto for instant unwinding of deeply
nested parsing.

Any number of application-defined terminals can be used without lookup penalty.
Each terminal is processed in its own scanning function.

Functions for literal matching of strings and characters are provided in uuscan.h; 
terminal scanning functions must be provided by the application.

An example application is in example.c
Read the notes in uuscan.h for more information

Here's a brief overview showing a terminal T being defined and used:

// define all terminal names required by app:
#define UUTERMINALS X(T) ...

// if terminal scan functions return a converted value such values can be
// assigned to application-defined identifiers in the uu struct. define UUVAL like:
#define UUVAL { int i; char *s; }

#include "uuscan.h"
...

// scanning function for T; this defines a function header bool __scan_T(char *lp)
UUDEFINE(T)
{
    // lp is ptr to the next non-space char of the input line to scan.

    // IF the text beginning at lp matches the rules for T and there are no errors
    // on conversion then 'return success(lp)' will update the global uu.lp pointer
    // to the first char after the current scan.

    // ELSE on any scan or conversion error 'return fail(lp)' will update
    // uu.lpfail where the scan failed; app parsing code will determine if
    // this is an error or a backtrack condition. 

    // for error handling normally a call to uuerror(..) is made to format an
    // error message. uuerror() will then jump to the on_uuerror() {...} code
    // block where the error message can be output and a decision made to continue
    // or to exit(1).

    // assign converted or saved values to uu.i, uu.s, etc. as declared with UUVAL above
    // or use a second ptr-to-variable argument in accept() and expect()
}

...

    // declare uuerror() target:

    on_uuerror {
        // report error message
        // either exit with error or fall through to read next line
    }

    // read loop:

    while (uu.line = read_next_line()) {
        uu.lp = uu.line;
        ...

        if (accept(T)) {
            ...
        }

        expect(T);
    }
}

About

header-only lexical scanning for recursive descent parsing

License:MIT License


Languages

Language:C 100.0%