view examples/mpp/jrc.syn @ 7:57b2cc9b87f7

Use memcpy instead of strncpy when we know the length anyway. Modern gcc seems to think it knows how to detect misuse of strncpy, but it's wrong (in fact: very, very wrong) and the path of least resistance is to not try to fight with it.
author David A. Holland
date Mon, 30 May 2022 23:47:52 -0400
parents 13d2b8934445
children
line wrap: on
line source

{/*

    Copyright (C) 1989,1990 James A. Roskind, All rights reserved.

    This grammar was developed  and  written  by  James  A.  Roskind.
    Copying  of  this  grammar  description, as a whole, is permitted
    providing this notice is intact and applicable  in  all  complete
    copies.   Translations as a whole to other parser generator input
    languages  (or  grammar  description  languages)   is   permitted
    provided  that  this  notice is intact and applicable in all such
    copies,  along  with  a  disclaimer  that  the  contents  are   a
    translation.   The reproduction of derived text, such as modified
    versions of this grammar, or the output of parser generators,  is
    permitted,  provided  the  resulting  work includes the copyright
    notice "Portions Copyright (c)  1989,  1990  James  A.  Roskind".
    Derived products, such as compilers, translators, browsers, etc.,
    that  use  this  grammar,  must also provide the notice "Portions
    Copyright  (c)  1989,  1990  James  A.  Roskind"  in   a   manner
    appropriate  to  the  utility,  and in keeping with copyright law
    (e.g.: EITHER displayed when first invoked/executed; OR displayed
    continuously on display terminal; OR via placement in the  object
    code  in  form  readable in a printout, with or near the title of
    the work, or at the end of the file).  No royalties, licenses  or
    commissions  of  any  kind are required to copy this grammar, its
    translations, or derivative products, when the copies are made in
    compliance with this notice. Persons or corporations that do make
    copies in compliance with this notice may charge  whatever  price
    is  agreeable  to  a  buyer, for such copies or derivative works.
    THIS GRAMMAR IS PROVIDED ``AS IS'' AND  WITHOUT  ANY  EXPRESS  OR
    IMPLIED  WARRANTIES,  INCLUDING,  WITHOUT LIMITATION, THE IMPLIED
    WARRANTIES  OF  MERCHANTABILITY  AND  FITNESS  FOR  A  PARTICULAR
    PURPOSE.

    James A. Roskind
    Independent Consultant
    516 Latania Palm Drive
    Indialantic FL, 32903
    (407)729-4348
    jar@ileaf.com
    or ...!uunet!leafusa!jar


 ******************************************************************************

 Translation to AnaGram and Interfacing
 Copyright 1993 Parsifal Software. All rights reserved.

 This software is provided 'as-is', without any express or implied
 warranty.  In no event will the authors be held liable for any damages
 arising from the use of this software.

 Permission is granted to anyone to use this software for any purpose,
 including commercial applications, and to alter it and redistribute it
 freely, subject to the following restrictions:

 1. The origin of this software must not be misrepresented; you must not
    claim that you wrote the original software. If you use this software
    in a product, an acknowledgment in the product documentation would be
    appreciated but is not required.
 2. Altered source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.
 3. This notice may not be removed or altered from any source distribution.

 ******************************************************************************

*/

#include "mpp.h"

}

[
  grammar token = prog start
 ~nest comments
  sticky { statement}                    //Resolves if-then-else conflict
  event driven
  far tables                             // Comment out for 32 bit compilers
 ~allow macros
  input values
  line numbers
  //escape backslashes                   // uncomment if using MSVC++
  error trace
  parser name = cc
  default input type = token
  header file name = "jrc.h"
  parser file name = "jrc.cpp"
 ~test range
  enum {
    eof               =0,
    SPACE             =' ',
    ANDAND            ='A', // "&&"
    ANDassign,              // "&="
    ARROW,                  // "->"
    CONCAT,                 // "##"
    DECR,                   // "--"
    DIVassign,              // "/="
    ELLIPSIS,               // "..."
    EQ,                     // "=="
    ERassign,               // "^="
    GE,                     // ">="
    ICR,                    // "++"
    LE,                     // "<="
    LS,                     // "<<"
    LSassign,               // "<<="
    MODassign,              // "%="
    MINUSassign,            // "-="
    MULTassign,             // "*="
    NE,                     // "!="
    ORassign,               // "|="
    OROR,                   // "||"
    PLUSassign,             // "+="
    RS,                     // ">>"
    RSassign,               // ">>="
    CHARACTERconstant,      // character constant
    STRINGliteral,          // character string
    HEXconstant       =129,
    OCTconstant,
    DECconstant,
    FLOATconstant,          // real
    NAME,
    AUTO,                   // "auto"
    BREAK,                  // "break"
    CASE,                   // "case"
    CHAR,                   // "char"
    CONSTANT,               // "const"
    CONTINUE,               // "continue"
    DEFAULT,                // "default"
    DO,                     // "do"
    DOUBLE,                 // "double"
    ELSE,                   // "else"
    ENUM,                   // "enum"
    EXTERN,                 // "extern"
    FLOAT,                  // "float"
    FOR,                    // "for"
    GOTO,                   // "goto"
    IF,                     // "if"
    INT,                    // "int"
    LONG,                   // "long"
    REGISTER,               // "register"
    RETURN,                 // "return"
    SHORT,                  // "short"
    SIGNED,                 // "signed"
    SIZEOF,                 // "sizeof"
    STATIC,                 // "static"
    STRUCT,                 // "struct"
    SWITCH,                 // "switch"
    TYPEDEF,                // "typedef"
    UNION,                  // "union"
    UNSIGNED,               // "unsigned"
    VOIDkey,                // "void"
    VOLATILE,               // "volatile"
    WHILE,                  // "while"
    UNRECOGNIZED,
  }
]

OCTALconstant    = OCTconstant
INTEGERconstant  = DECconstant
FLOATINGconstant = FLOATconstant
CONST            = CONSTANT
VOID             = VOIDkey

prog start
 -> translation unit?, eof

/* CONSTANTS */

constant
 -> FLOATINGconstant
 -> INTEGERconstant
 -> OCTALconstant
 -> HEXconstant
 -> CHARACTERconstant

/* STRING LITERALS */

string literal list
 -> STRINGliteral
 -> string literal list, STRINGliteral

/* EXPRESSIONS */

(void) primary expression
 -> IDENTIFIER
 -> constant
 -> string literal list
 -> '(', expression, ')'

postfix expression
 -> primary expression
 -> postfix expression, '[', expression, ']'
 -> postfix expression, '(', ')'
 -> postfix expression, '(', argument expression list, ')'
 -> postfix expression, '.', identifier or typedef name
 -> postfix expression, ARROW, identifier or typedef name
 -> postfix expression, ICR
 -> postfix expression, DECR

argument expression list
 -> assignment expression
 -> argument expression list, ',', assignment expression

unary expression
 -> postfix expression
 -> ICR, unary expression
 -> DECR, unary expression
 -> unary operator, cast expression
 -> SIZEOF, unary expression
 -> SIZEOF, '(', type name, ')'

unary operator
 -> '&'
 -> '*'
 -> '+'
 -> '-'
 -> '~'
 -> '!'

cast expression
 -> unary expression
 -> '(', type name, ')', cast expression

multiplicative expression
 -> cast expression
 -> multiplicative expression, '*', cast expression
 -> multiplicative expression, '/', cast expression
 -> multiplicative expression, '%', cast expression

additive expression
 -> multiplicative expression
 -> additive expression, '+', multiplicative expression
 -> additive expression, '-', multiplicative expression

shift expression
 -> additive expression
 -> shift expression, LS, additive expression
 -> shift expression, RS, additive expression

relational expression
 -> shift expression
 -> relational expression, '<', shift expression
 -> relational expression, '>', shift expression
 -> relational expression, LE, shift expression
 -> relational expression, GE, shift expression

equality expression
 -> relational expression
 -> equality expression, EQ, relational expression
 -> equality expression, NE, relational expression

AND expression
 -> equality expression
 -> AND expression, '&', equality expression

exclusive OR expression
 -> AND expression
 -> exclusive OR expression, '^', AND expression

inclusive OR expression
 -> exclusive OR expression
 -> inclusive OR expression, '|', exclusive OR expression

logical AND expression
 -> inclusive OR expression
 -> logical AND expression, ANDAND, inclusive OR expression

logical OR expression
 -> logical AND expression
 -> logical OR expression, OROR, logical AND expression

conditional expression
 -> logical OR expression
 -> logical OR expression, '?', expression, ':', conditional expression

assignment expression
 -> conditional expression
 -> unary expression, assignment operator, assignment expression

assignment operator
 -> '='
 -> MULTassign
 -> DIVassign
 -> MODassign
 -> PLUSassign
 -> MINUSassign
 -> LSassign
 -> RSassign
 -> ANDassign
 -> ERassign
 -> ORassign

expression
 -> assignment expression
 -> expression, ',', assignment expression

constant expression
 -> conditional expression

/* The following was used for clarity */

expression opt
 ->
 -> expression

/* DECLARATIONS */

declaration
 -> sue declaration specifier, ';'
 -> sue type specifier, ';'
 -> declaring list, ';'
 -> default declaring list, ';'

default declaring list
 -> declaration qualifier list, identifier declarator, initializer opt
 -> type qualifier list, identifier declarator, initializer opt
 -> default declaring list, ',', identifier declarator, initializer opt

declaring list
 -> declaration specifier, declarator, initializer opt
 -> type specifier, declarator, initializer opt
 -> declaring list, ',', declarator, initializer opt

declaration specifier
 -> basic declaration specifier
 -> sue declaration specifier
 -> typedef declaration specifier

type specifier
 -> basic type specifier
 -> sue type specifier
 -> typedef type specifier

declaration qualifier list
 -> storage class
 -> type qualifier list, storage class
 -> declaration qualifier list, declaration qualifier

type qualifier list
 -> type qualifier
 -> type qualifier list, type qualifier

declaration qualifier
 -> type qualifier
 -> storage class

type qualifier
 -> CONST
 -> VOLATILE

basic declaration specifier
 -> basic type specifier, storage class
 -> declaration qualifier list, basic type name
 -> basic declaration specifier, declaration qualifier
 -> basic declaration specifier, basic type name

basic type specifier
 -> basic type name
 -> type qualifier list, basic type name
 -> basic type specifier, type qualifier
 -> basic type specifier, basic type name

sue declaration specifier
 -> sue type specifier, storage class
 -> declaration qualifier list, elaborated type name
 -> sue declaration specifier, declaration qualifier

sue type specifier
 -> elaborated type name
 -> type qualifier list, elaborated type name
 -> sue type specifier, type qualifier

(void) typedef declaration specifier
 -> typedef type specifier, storage class
 -> declaration qualifier list, TYPEDEFname
 -> typedef declaration specifier, declaration qualifier

(void) typedef type specifier
 -> TYPEDEFname
 -> type qualifier list, TYPEDEFname
 -> typedef type specifier, type qualifier

storage class
 -> TYPEDEF           =typedef_flag = 1;
 -> EXTERN
 -> STATIC
 -> AUTO
 -> REGISTER

basic type name
 -> VOID
 -> CHAR
 -> SHORT
 -> INT
 -> LONG
 -> FLOAT
 -> DOUBLE
 -> SIGNED
 -> UNSIGNED

elaborated type name
 -> save flag:f, struct or union specifier      =typedef_flag = f;
 -> enum specifier

(int) save flag
 ->     ={int f = typedef_flag; typedef_flag = 0; return f;}

struct or union specifier
 -> struct or union, '{', struct declaration list, '}'
 -> struct or union, identifier or typedef name, '{', struct declaration list, '}'
 -> struct or union, identifier or typedef name

struct or union
 -> STRUCT
 -> UNION

struct declaration list
 -> struct declaration
 -> struct declaration list, struct declaration

struct declaration
 -> struct declaring list, ';'
 -> struct default declaring list, ';'

struct default declaring list
 -> type qualifier list, struct identifier declarator
 -> struct default declaring list, ',', struct identifier declarator

struct declaring list
 -> type specifier, struct declarator
 -> struct declaring list, ',', struct declarator

struct declarator
 -> declarator, bit field size opt
 -> bit field size

struct identifier declarator
 -> identifier declarator, bit field size opt
 -> bit field size

bit field size opt
 ->
 -> bit field size

bit field size
 -> ':', constant expression

enum specifier
 -> ENUM, '{', enumerator list, '}'
 -> ENUM, identifier or typedef name, '{', enumerator list, '}'
 -> ENUM, identifier or typedef name

enumerator list
 -> identifier or typedef name, enumerator value opt
 -> enumerator list, ',', identifier or typedef name, enumerator value opt

enumerator value opt
 ->
 -> '=', constant expression

parameter type list
 -> parameter list
 -> parameter list, ',', ELLIPSIS

parameter list
 -> parameter declaration
 -> parameter list, ',', parameter declaration

parameter declaration
 -> declaration specifier
 -> declaration specifier, abstract declarator
 -> declaration specifier, identifier declarator
 -> declaration specifier, parameter typedef declarator
 -> declaration qualifier list
 -> declaration qualifier list, abstract declarator
 -> declaration qualifier list, identifier declarator
 -> type specifier
 -> type specifier, abstract declarator
 -> type specifier, identifier declarator
 -> type specifier, parameter typedef declarator
 -> type qualifier list
 -> type qualifier list, abstract declarator
 -> type qualifier list, identifier declarator

(void) identifier list
 -> IDENTIFIER
 -> identifier list, ',', IDENTIFIER

(void) identifier or typedef name
 -> IDENTIFIER
 -> TYPEDEFname

type name
 -> type specifier
 -> type specifier, abstract declarator
 -> type qualifier list
 -> type qualifier list, abstract declarator

initializer opt
 ->
 -> '=', initializer

initializer
 -> '{', initializer list, '}'
 -> '{', initializer list, ',', '}'
 -> assignment expression

initializer list
 -> initializer
 -> initializer list, ',', initializer

/* STATEMENTS */

statement
 -> labeled statement
 -> compound statement
 -> expression statement
 -> selection statement
 -> iteration statement
 -> jump statement

labeled statement
 -> identifier or typedef name, ':', statement
 -> CASE, constant expression, ':', statement
 -> DEFAULT, ':', statement

compound statement
 -> '{', '}'
 -> '{', declaration list, '}'
 -> '{', statement list, '}'
 -> '{', declaration list, statement list, '}'

declaration list
 -> declaration
 -> declaration list, declaration

statement list
 -> statement
 -> statement list, statement

expression statement
 -> expression opt, ';'

selection statement
 -> IF, '(', expression, ')', statement
 -> IF, '(', expression, ')', statement, ELSE, statement
 -> SWITCH, '(', expression, ')', statement

iteration statement
 -> WHILE, '(', expression, ')', statement
 -> DO, statement, WHILE, '(', expression, ')', ';'
 -> FOR, '(', expression opt, ';', expression opt, ';', expression opt, ')', statement

jump statement
 -> GOTO, identifier or typedef name, ';'
 -> CONTINUE, ';'
 -> BREAK, ';'
 -> RETURN, expression opt, ';'

/* EXTERNAL DEFINITIONS */

translation unit
 -> external definition
 -> translation unit, external definition

external definition
 -> function definition
 -> declaration
 -> identifier declarator, ';'    /* Added by JTH! */

function definition
 -> identifier declarator, compound statement
 -> declaration specifier, identifier declarator, compound statement
 -> type specifier, identifier declarator, compound statement
 -> declaration qualifier list, identifier declarator, compound statement
 -> type qualifier list, identifier declarator, compound statement
 -> old function declarator, compound statement
 -> declaration specifier, old function declarator, compound statement
 -> type specifier, old function declarator, compound statement
 -> declaration qualifier list, old function declarator, compound statement
 -> type qualifier list, old function declarator, compound statement
 -> old function declarator, declaration list, compound statement
 -> declaration specifier, old function declarator, declaration list, compound statement
 -> type specifier, old function declarator, declaration list, compound statement
 -> declaration qualifier list, old function declarator, declaration list, compound statement
 -> type qualifier list, old function declarator, declaration list, compound statement

declarator
 -> typedef declarator
 -> identifier declarator

typedef declarator
 -> paren typedef declarator
 -> parameter typedef declarator

parameter typedef declarator
 -> TYPEDEFname
 -> TYPEDEFname, postfixing abstract declarator
 -> clean typedef declarator

clean typedef declarator
 -> clean postfix typedef declarator
 -> '*', parameter typedef declarator
 -> '*', type qualifier list, parameter typedef declarator

clean postfix typedef declarator
 -> '(', clean typedef declarator, ')'
 -> '(', clean typedef declarator, ')', postfixing abstract declarator

paren typedef declarator
 -> paren postfix typedef declarator
 -> '*', '(', simple paren typedef declarator, ')'
 -> '*', type qualifier list, '(', simple paren typedef declarator, ')'
 -> '*', paren typedef declarator
 -> '*', type qualifier list, paren typedef declarator

paren postfix typedef declarator
 -> '(', paren typedef declarator, ')'
 -> '(', simple paren typedef declarator, postfixing abstract declarator, ')'
 -> '(', paren typedef declarator, ')', postfixing abstract declarator

simple paren typedef declarator
 -> TYPEDEFname
 -> '(', simple paren typedef declarator, ')'

identifier declarator
 -> unary identifier declarator
 -> paren identifier declarator

unary identifier declarator
 -> postfix identifier declarator
 -> '*', identifier declarator
 -> '*', type qualifier list, identifier declarator

postfix identifier declarator
 -> paren identifier declarator, postfixing abstract declarator
 -> '(', unary identifier declarator, ')'
 -> '(', unary identifier declarator, ')', postfixing abstract declarator

paren identifier declarator
 -> IDENTIFIER:s                            =do_typedef(s);
 -> '(', paren identifier declarator, ')'

old function declarator
 -> postfix old function declarator
 -> '*', old function declarator
 -> '*', type qualifier list, old function declarator

postfix old function declarator
 -> paren identifier declarator, '(', identifier list, ')'
 -> '(', old function declarator, ')'
 -> '(', old function declarator, ')', postfixing abstract declarator

abstract declarator
 -> unary abstract declarator
 -> postfix abstract declarator
 -> postfixing abstract declarator

postfixing abstract declarator
 -> array abstract declarator
 -> '(', ')'
 -> '(', parameter type list, ')'

array abstract declarator
 -> '[', ']'
 -> '[', constant expression, ']'
 -> array abstract declarator, '[', constant expression, ']'

unary abstract declarator
 -> '*'
 -> '*', type qualifier list
 -> '*', abstract declarator
 -> '*', type qualifier list, abstract declarator

postfix abstract declarator
 -> '(', unary abstract declarator, ')'
 -> '(', postfix abstract declarator, ')'
 -> '(', postfixing abstract declarator, ')'
 -> '(', unary abstract declarator, ')', postfixing abstract declarator

(token) IDENTIFIER, TYPEDEFname
 -> NAME:t                                  =check_typedef(t);


{                                           // Embedded C

#define SYNTAX_ERROR syntax_error(PCB.error_message)
#define INPUT_CODE(T) (T).id

static int typedef_flag = 0;
static int use_count = 0;

symbol_type_enum symbol_table[N_SYMBOLS];


static void do_typedef(token t) {
  if (typedef_flag == 0) return;
  typedef_flag = 0;
  symbol_table[t.handle] = typedef_name;
}

static token check_typedef(token t) {
  if (symbol_table[t.handle] == typedef_name)
    CHANGE_REDUCTION(TYPEDEFname);
  return t;
}

// Member Functions for Class c_parser

// Constructor

/*
  This parser has no provisions for multiple simultaneous parses or for
  recursion. The purpose of use_count is to make sure that there is only one
  copy of the parser active at any time.
*/


c_parser::c_parser() {
  assert(use_count == 0);
  use_count++;
  typedef_flag = 0;
  memset(symbol_table, 0, sizeof(symbol_table));
  init_cc();                                // init parse
}


// Destructor

c_parser::~c_parser() {
  use_count--;                              // Makes parser available
}


// Reset Parser

c_parser &reset(c_parser &c) {
  typedef_flag = 0;
  memset(symbol_table, 0, sizeof(symbol_table));
  init_cc();                                // init parse
  return c;
}


// Transmit token to c_parser

/*
  The overloaded operator "<<" is used to transmit data to a parser.
  Newline tokens are filtered out, since they are passed along by the
  token scanner only in case text output of the preprocessor is
  required.

  If the parser has encountered an error, there is no point in giving
  it any further input.

  Otherwise, the input_code and input_value fields of the pcb are set
  up and cc() is called to deal with the token.
*/

token_sink &c_parser::operator << (token c) {
  if (PCB.exit_flag != AG_RUNNING_CODE || (int) c.id == '\n') return *this;
  PCB.input_code = c.id;
  PCB.input_value = c;
  cc();
  return *this;
}

token_sink &c_parser::operator << (token *s) {
  while (s->id != END_OF_FILE && PCB.exit_flag == AG_RUNNING_CODE) {
    if ((int) s->id == 10) continue;
    PCB.input_code = s->id;
    PCB.input_value = *s++;
    cc();
  }
  return *this;
}

}                                           // End Embedded C