Subversion Repositories tendra.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

%prefixes%

terminal = lex_ ;


%maps%


/*
    ENTRY POINT

    The main entry point for the grammar is given by unit.
*/

unit -> read_errors ;


/*
    TYPE MAPPINGS

    These mappings give the correspondences between syntax types and
    C types.
*/

ID -> string ;
STRING -> string ;
ENTRY -> ENTRY ;
KEY -> KEY ;
MAP -> MAP ;
MSG -> MESSAGE ;
NAME -> NAME ;
PARAM -> PARAM ;
PROP -> PROPERTY ;
TYPE -> TYPE ;
USAGE -> USAGE ;
LIST-ENTRY -> LIST_ENTRY ;
LIST-MAP -> LIST_MAP ;
LIST-MSG -> LIST_MESSAGE ;
LIST-NAME -> LIST_NAME ;
LIST-PARAM -> LIST_PARAM ;
LIST-PROP -> LIST_PROPERTY ;


%header% @{
/*
                 Crown Copyright (c) 1997

    This TenDRA(r) Computer Program is subject to Copyright
    owned by the United Kingdom Secretary of State for Defence
    acting through the Defence Evaluation and Research Agency
    (DERA).  It is made available to Recipients with a
    royalty-free licence for its use, reproduction, transfer
    to other parties and amendment for any purpose not excluding
    product development provided that any such use et cetera
    shall be deemed to be acceptance of the following conditions:-

        (1) Its Recipients shall ensure that this Notice is
        reproduced upon any copies or amended versions of it;

        (2) Any amended version of it shall be clearly marked to
        show both the nature of and the organisation responsible
        for the relevant amendment or amendments;

        (3) Its onward transfer from a recipient to another
        party shall be deemed to be that party's acceptance of
        these conditions;

        (4) DERA gives no warranty or assurance as to its
        quality or suitability for any purpose and DERA accepts
        no liability whatsoever in relation to any use to which
        it may be put.
*/


#include "config.h"
#include "errors.h"
#include "entry_ops.h"
#include "map_ops.h"
#include "msg_ops.h"
#include "name_ops.h"
#include "param_ops.h"
#include "error.h"
#include "lex.h"
#include "process.h"
#include "syntax.h"
#include "xalloc.h"


/*
    PARSER TYPES

    These types give the implementation of the types used in the syntax.
*/

typedef LIST ( ENTRY ) LIST_ENTRY ;
typedef LIST ( MAP ) LIST_MAP ;
typedef LIST ( MESSAGE ) LIST_MESSAGE ;
typedef LIST ( NAME ) LIST_NAME ;
typedef LIST ( PARAM ) LIST_PARAM ;
typedef LIST ( PROPERTY ) LIST_PROPERTY ;


/*
    COUNTER VARIABLE

    This variable is used to keep count of the position in a name or
    parameter list.
*/

static int counter = 0 ;


/*
    FIND A NAME

    This routine searches the name list p for an identifier matching id.
    The null name is returned if no matching name is found.
*/

static NAME find_name
    ( LIST ( NAME ) p, string id )
{
    while ( !IS_NULL_list ( p ) ) {
        NAME a = DEREF_name ( HEAD_list ( p ) ) ;
        string nm = DEREF_string ( name_id ( a ) ) ;
        if ( streq ( nm, id ) ) return ( a ) ;
        p = TAIL_list ( p ) ;
    }
    return ( NULL_name ) ;
}


/*
    FIND A PARAMETER

    This routine searches the parameter list p for an identifier matching
    id.  The null parameter is returned if no matching parameter is found.
*/

static PARAM find_param
    ( LIST ( PARAM ) p, string id )
{
    while ( !IS_NULL_list ( p ) ) {
        PARAM a = DEREF_param ( HEAD_list ( p ) ) ;
        string nm = DEREF_string ( param_name ( a ) ) ;
        if ( streq ( nm, id ) ) return ( a ) ;
        p = TAIL_list ( p ) ;
    }
    return ( NULL_param ) ;
}


/*
    COMPILATION MODE

    We allow unreached code and switch off the variable analysis in the
    automatically generated sections.
*/

#if FS_TENDRA
#pragma TenDRA begin
#pragma TenDRA variable analysis off
#ifndef OLD_PRODUCER
#pragma TenDRA unreachable code allow
#endif
#endif


@}, @{
/*
                 Crown Copyright (c) 1997

    This TenDRA(r) Computer Program is subject to Copyright
    owned by the United Kingdom Secretary of State for Defence
    acting through the Defence Evaluation and Research Agency
    (DERA).  It is made available to Recipients with a
    royalty-free licence for its use, reproduction, transfer
    to other parties and amendment for any purpose not excluding
    product development provided that any such use et cetera
    shall be deemed to be acceptance of the following conditions:-

        (1) Its Recipients shall ensure that this Notice is
        reproduced upon any copies or amended versions of it;

        (2) Any amended version of it shall be clearly marked to
        show both the nature of and the organisation responsible
        for the relevant amendment or amendments;

        (3) Its onward transfer from a recipient to another
        party shall be deemed to be that party's acceptance of
        these conditions;

        (4) DERA gives no warranty or assurance as to its
        quality or suitability for any purpose and DERA accepts
        no liability whatsoever in relation to any use to which
        it may be put.
*/


#ifndef SYNTAX_INCLUDED
#define SYNTAX_INCLUDED

@};


%terminals%


/*
    IDENTIFIER TERMINAL

    This action gives the terminal for identifiers.  The identifier text
    is built up in token_buff by the lexical routines.
*/

identifier : () -> ( i : ID ) = @{
    @i = xstrcpy ( token_buff ) ;
@} ;


/*
    STRING TERMINAL

    This action gives the terminal for strings.  The string text is built
    up in token_buff by the lexical routines.
*/

string : () -> ( s : STRING ) = @{
    @s = xstrcpy ( token_buff ) ;
@} ;


%actions%


/*
    NULL IDENTIFIER

    This action describes the null identifier.
*/

<null_identifier> : () -> ( id : ID ) = @{
    @id = NULL ;
@} ;


/*
    LIST CONSTRUCTION ACTIONS

    These actions give the empty lists and cons operations for the various
    list types used in the grammar.  They basically map directly onto the
    various calculus constructs, except that checks are made for duplicate
    entries in some cases.
*/

<empty_message_list> : () -> ( p : LIST-MSG ) = @{
    @p = NULL_list ( MESSAGE ) ;
@} ;

<cons_message_list> : ( a : MSG, q : LIST-MSG ) -> ( p : LIST-MSG ) = @{
    CONS_msg ( @a, @q, @p ) ;
@} ;

<empty_map_list> : () -> ( p : LIST-MAP ) = @{
    @p = NULL_list ( MAP ) ;
@} ;

<cons_map_list> : ( a : MAP, q : LIST-MAP ) -> ( p : LIST-MAP ) = @{
    CONS_map ( @a, @q, @p ) ;
@} ;

<empty_props_list> : () -> ( p : LIST-PROP ) = @{
    @p = NULL_list ( PROPERTY ) ;
@} ;

<cons_props_list> : ( a : PROP, q : LIST-PROP ) -> ( p : LIST-PROP ) = @{
    CONS_name ( @a, @q, @p ) ;
@} ;

<empty_param_list> : () -> ( p : LIST-PARAM ) = @{
    @p = NULL_list ( PARAM ) ;
@} ;

<cons_param_list> : ( a : PARAM, q : LIST-PARAM ) -> ( p : LIST-PARAM ) = @{
    string id = DEREF_string ( param_name ( @a ) ) ;
    PARAM b = find_param ( @q, id ) ;
    if ( !IS_NULL_param ( b ) ) {
        error ( ERROR_SERIOUS, "Parameter '%s' defined twice", id ) ;
    }
    CONS_param ( @a, @q, @p ) ;
@} ;

<empty_entry_list> : () -> ( p : LIST-ENTRY ) = @{
    @p = NULL_list ( ENTRY ) ;
@} ;

<cons_entry_list> : ( a : ENTRY, q : LIST-ENTRY ) -> ( p : LIST-ENTRY ) = @{
    CONS_entry ( @a, @q, @p ) ;
@} ;

<empty_name_list> : () -> ( p : LIST-NAME ) = @{
    @p = NULL_list ( NAME ) ;
@} ;

<cons_name_list> : ( a : NAME, q : LIST-NAME ) -> ( p : LIST-NAME ) = @{
    string id = DEREF_string ( name_id ( @a ) ) ;
    NAME b = find_name ( @q, id ) ;
    if ( !IS_NULL_name ( b ) ) {
        error ( ERROR_SERIOUS, "Name '%s' given twice in list", id ) ;
    }
    CONS_name ( @a, @q, @p ) ;
@} ;

<join_name_list> : ( a : NAME, q : LIST-NAME ) -> ( p : LIST-NAME ) = @{
    CONS_name ( @a, @q, @p ) ;
@} ;


/*
    NAME LOOK-UP ACTIONS

    These actions are used to look up an identifier in various circumstances.
    They map directly onto the routines find_name and find_param defined
    above.
*/

<find_key> : ( id : ID ) -> ( k : KEY ) = @{
    NAME n = find_name ( all_keys, @id ) ;
    if ( IS_NULL_name ( n ) ) {
        error ( ERROR_SERIOUS, "Key '%s' not defined", @id ) ;
    }
    @k = n ;
@} ;

<find_props> : ( id : ID ) -> ( p : PROP ) = @{
    NAME n = find_name ( all_props, @id ) ;
    if ( IS_NULL_name ( n ) ) {
        error ( ERROR_SERIOUS, "Property '%s' not defined", @id ) ;
        MAKE_name_basic ( @id, 0, n ) ;
    }
    @p = n ;
@} ;

<find_type> : ( id : ID ) -> ( t : TYPE ) = @{
    NAME n = find_name ( all_types, @id ) ;
    if ( IS_NULL_name ( n ) ) {
        error ( ERROR_SERIOUS, "Type '%s' not defined", @id ) ;
        MAKE_name_basic ( @id, 0, n ) ;
    }
    @t = n ;
@} ;

<find_usage> : ( id : ID ) -> ( u : USAGE ) = @{
    NAME n = find_name ( all_usages, @id ) ;
    if ( IS_NULL_name ( n ) ) {
        error ( ERROR_SERIOUS, "Usage '%s' not defined", @id ) ;
        MAKE_name_basic ( @id, 0, n ) ;
    }
    @u = n ;
@} ;

<find_param> : ( id : ID, s : LIST-PARAM ) -> ( p : PARAM ) = @{
    PARAM a = find_param ( @s, @id ) ;
    if ( IS_NULL_param ( a ) ) {
        error ( ERROR_SERIOUS, "Parameter '%s' not defined", @id ) ;
    }
    @p = a ;
@} ;


/*
    OBJECT CONSTRUCTION ACTIONS

    These actions are used to construct various objects from their
    components.  They map directly onto the calculus construction routines.
*/

<null_usage> : () -> ( u : USAGE ) = @{
    @u = NULL_name ;
@} ;

<make_name> : ( id : ID ) -> ( n : NAME ) = @{
    MAKE_name_basic ( @id, counter, @n ) ;
    counter++ ;
@} ;

<make_name_aux> : ( id : ID ) -> ( n : NAME ) = @{
    MAKE_name_basic ( @id, 0, @n ) ;
@} ;

<make_param> : ( t : TYPE, id : ID ) -> ( p : PARAM ) = @{
    MAKE_param_basic ( @t, @id, counter, @p ) ;
    counter++ ;
@} ;

<message_param> : ( p : PARAM ) -> ( m : MSG ) = @{
    if ( !IS_NULL_param ( @p ) ) {
        MAKE_msg_param ( @p, @m ) ;
    } else {
        MAKE_msg_text ( "<error>", @m ) ;
    }
@} ;

<message_string> : ( s : STRING ) -> ( m : MSG ) = @{
    MAKE_msg_text ( @s, @m ) ;
@} ;

<make_map> : ( k : KEY, p : LIST-MSG, q : LIST-MSG ) -> ( m : MAP ) = @{
    MAKE_map_basic  ( @k, @p, @q, @m ) ;
@} ;

<make_entry> : ( a : ID, b : ID, s : LIST-PARAM, u : USAGE, v : USAGE,
                 p : LIST-PROP, m : LIST-MAP ) -> ( e : ENTRY ) = @{
    MAKE_entry_basic ( @a, @b, @s, @u, @v, @p, @m, @e ) ;
    counter = 0 ;
@} ;


/*
    GLOBAL ASSIGNMENT ACTIONS

    These actions assign the lists and strings constructed by the parser
    to the various global variables designed to hold this information.
*/

<set_db> : ( r : ID, s : ID ) -> () = @{
    db_name = @r ;
    db_name_alt = @s ;
@} ;

<set_rig> : ( r : ID ) -> () = @{
    rig_name = @r ;
@} ;

<set_prefix> : ( a : ID, b : ID, c : ID ) -> () = @{
    if ( @a ) rig_comp_output = @a ;
    if ( @b ) rig_from_comp = @b ;
    if ( @c ) rig_from_db = @c ;
@} ;

<set_types> : ( p : LIST-NAME, q : LIST-NAME, r : LIST-NAME ) -> () = @{
    all_types = @p ;
    all_types_aux = @q ;
    all_types_alt = @r ;
    counter = 0 ;
@} ;

<set_props> : ( p : LIST-NAME, q : LIST-NAME, r : LIST-NAME ) -> () = @{
    all_props = @p ;
    all_props_aux = @q ;
    all_props_alt = @r ;
    counter = 0 ;
@} ;

<set_keys> : ( p : LIST-NAME, q : LIST-NAME, r : LIST-NAME ) -> () = @{
    all_keys = @p ;
    all_keys_aux = @q ;
    all_keys_alt = @r ;
    counter = 0 ;
@} ;

<set_usages> : ( p : LIST-NAME, q : LIST-NAME, r : LIST-NAME ) -> () = @{
    all_usages = @p ;
    all_usages_aux = @q ;
    all_usages_alt = @r ;
    counter = 0 ;
@} ;

<set_entries> : ( p : LIST-ENTRY ) -> () = @{
    all_entries = @p ;
    counter = 0 ;
@} ;


/*
    SYNTAX ERROR ACTION

    This action is used to signal a syntax error.
*/

<syntax_error> : () -> () = @{
    error ( ERROR_SERIOUS, "Syntax error" ) ;
@} ;


%trailer% @{
@}, @{
#endif
@} ;