Author Topic: Stripped fluffos 2.27 lpc grammar  (Read 240 times)

Offline silenus

  • BFF
  • ***
  • Posts: 181
    • View Profile
Stripped fluffos 2.27 lpc grammar
« on: September 06, 2017, 08:02:43 AM »
I believe Kalinash did something like this before but here is a stripped copy of the grammar.pre.y taken from fluffos 2.27. The semantic actions have been taken out.

Code: [Select]
/* This is to make emacs edit this in C mode: -*-C-*- */

%{
extern char *outp;
#include "std.h"
#include "compiler.h"
#include "lex.h"
#include "scratchpad.h"

#include "lpc_incl.h"
#include "simul_efun.h"
#include "generate.h"
#include "master.h"

/* gross. Necessary? - Beek */
#ifdef WIN32
#define MSDOS
#endif
#define YYSTACK_USE_ALLOCA 0
%line
/*
 * This is the grammar definition of LPC, and its parse tree generator.
 */

/* down to one global :)
   bits:
      SWITCH_CONTEXT     - we're inside a switch
      LOOP_CONTEXT       - we're inside a loop
      SWITCH_STRINGS     - a string case has been found
      SWITCH_NUMBERS     - a non-zero numeric case has been found
      SWITCH_RANGES      - a range has been found
      SWITCH_DEFAULT     - a default has been found
 */
int context;
int num_refs;
int func_present;
/*
 * bison & yacc don't prototype this in y.tab.h
 */
int yyparse (void);

%}
/*
 * Token definitions.
 *
 * Appearing in the precedence declarations are:
 *      '+'  '-'  '/'  '*'  '%'
 *      '&'  '|'  '<'  '>'  '^'
 *      '~'  '?'
 *
 * Other single character tokens recognized in this grammar:
 *      '{'  '}'  ','  ';'  ':'
 *      '('  ')'  '['  ']'  '$'
 */

%token L_STRING L_NUMBER L_REAL
%token L_BASIC_TYPE L_TYPE_MODIFIER
%token L_DEFINED_NAME L_IDENTIFIER
%token L_EFUN

%token L_INC L_DEC
%token L_ASSIGN
%token L_LAND L_LOR
%token L_LSH L_RSH
%token L_ORDER
%token L_NOT

%token L_IF L_ELSE
%token L_SWITCH L_CASE L_DEFAULT L_RANGE L_DOT_DOT_DOT
%token L_WHILE L_DO L_FOR L_FOREACH L_IN
%token L_BREAK L_CONTINUE
%token L_RETURN
%token L_ARROW L_INHERIT L_COLON_COLON
%token L_ARRAY_OPEN L_MAPPING_OPEN L_FUNCTION_OPEN L_NEW_FUNCTION_OPEN

%token L_SSCANF L_CATCH
%ifdef DEBUG
%token L_TREE
%endif
%ifdef ARRAY_RESERVED_WORD
%token L_ARRAY
%endif
%ifdef REF_RESERVED_WORD
%token L_REF
%endif
%token L_PARSE_COMMAND L_TIME_EXPRESSION
%token L_CLASS L_NEW
%token L_PARAMETER

%ifdef COMPAT_32
%token L_LAMBDA
%endif

/*
 * 'Dangling else' shift/reduce conflict is well known...
 *  define these precedences to shut yacc up.
 */

%nonassoc LOWER_THAN_ELSE
%nonassoc L_ELSE

/*
 * Operator precedence and associativity...
 * greatly simplify the grammar.
 */

%right L_ASSIGN
%right '?'
%left L_LOR
%left L_LAND
%left '|'
%left '^'
%left '&'
%left L_EQ L_NE
%left L_ORDER '<'
%left L_LSH L_RSH
%left '+' '-'
%left '*' '%' '/'
%right L_NOT '~'
%nonassoc L_INC L_DEC

/*
 * YYTYPE
 *
 * Anything with size > 4 is commented.  Sizes assume typical 32 bit
 * architecture.  This size of the largest element of this union should
 * be kept as small as possible to optimize copying of compiler stack
 * elements.
 */
%union
{
    POINTER_INT pointer_int;
    LPC_INT number; /* 4 or 8 */
    LPC_FLOAT real; /* 8 */
    char *string;
    struct { short num_arg; char flags; } argument;
    ident_hash_elem_t *ihe;
    parse_node_t *node;
    function_context_t *contextp;
    struct {
parse_node_t *node;
        char num;
    } decl; /* 5 */
    struct {
char num_local;
char max_num_locals;
short context;
short save_current_type;
short save_exact_types;
    } func_block; /* 8 */
}


/*
 * Type declarations.
 */

/* These hold opcodes */
%type <number> efun_override L_ASSIGN L_ORDER

/* Holds a variable index */
%type <number> L_PARAMETER single_new_local_def

/* These hold arbitrary numbers */
%type <number> L_NUMBER

/* These hold numbers that are going to be stuffed into pointers :)
 * Don't ask :)
 */
%type <pointer_int> constant

/* These hold a real number */
%type <real>   L_REAL

/* holds a string constant */
%type <string> L_STRING string_con1 string_con2

/* Holds the number of elements in a list and whether it must be a prototype */
%type <argument> argument_list argument

/* These hold a list of possible interpretations of an identifier */
%type <ihe> L_DEFINED_NAME

/* These hold a type */
%type <number> type optional_star type_modifier_list
%type <number> opt_basic_type L_TYPE_MODIFIER L_BASIC_TYPE basic_type atomic_type
%type <number> cast arg_type
%ifdef ARRAY_RESERVED_WORD
%type <number> opt_atomic_type
%endif

/* This holds compressed and less flexible def_name information */
%type <number> L_NEW_FUNCTION_OPEN l_new_function_open
%ifdef COMPAT_32
%type <number> simple_function_pointer
%endif

/* holds an identifier or some sort */
%type <string> L_IDENTIFIER L_EFUN function_name identifier
%type <string> new_local_name

/* The following return a parse node */
%type <node> number real string expr0 comma_expr for_expr sscanf catch
%type <node> parse_command time_expression expr_list expr_list2 expr_list3
%type <node> expr_list4 assoc_pair expr4 lvalue function_call lvalue_list
%type <node> new_local_def statement while cond do switch case
%type <node> return optional_else_part block_or_semi
%type <node> case_label statements switch_block
%type <node> expr_list_node expr_or_block
%type <node> single_new_local_def_with_init
%type <node> class_init opt_class_init all def
%type <node> program modifier_change inheritance type_decl
%ifdef DEBUG
%type <node> tree
%endif

/* The following hold information about blocks and local vars */
%type <decl> local_declarations local_name_list block decl_block
%type <decl> foreach_var foreach_vars first_for_expr foreach for

/* This holds a flag */
%type <number> new_arg

%%
%pragma auto_note_compiler_case_start

all:
program
    ;

program:
program def possible_semi_colon
    |   /* empty */
    ;

possible_semi_colon:
/* empty */
    |   ';'
    ;


inheritance:
type_modifier_list L_INHERIT string_con1 ';'
;

real:
    L_REAL
    ;

number:
L_NUMBER
    ;

optional_star:
/* empty */
    |   '*'
    ;

block_or_semi:
block
    |   ';'
    | error
    ;

identifier:
        L_DEFINED_NAME
     |  L_IDENTIFIER
     ;

def:
        type optional_star identifier '(' argument ')' block_or_semi
    |   type name_list ';'
    |   inheritance
    |   type_decl
    |   modifier_change
    ;

modifier_change: type_modifier_list ':'
;

member_name:
        optional_star identifier
     ;

member_name_list:
        member_name
    |   member_name ',' member_name_list
    ;

member_list:
            /* empty */
    | member_list basic_type
    member_name_list ';'
    ;

type_decl:
      type_modifier_list L_CLASS identifier '{'
    member_list '}'
    ;

new_local_name:
        L_IDENTIFIER
      | L_DEFINED_NAME
      ;

atomic_type:
        L_BASIC_TYPE
      | L_CLASS L_DEFINED_NAME
      | L_CLASS L_IDENTIFIER
       ;

%ifdef ARRAY_RESERVED_WORD
opt_atomic_type:
        atomic_type
    |   /* empty */
    ;
%endif

basic_type:
         atomic_type
%ifdef ARRAY_RESERVED_WORD
       | opt_atomic_type L_ARRAY   
%endif
       ;

arg_type:
         basic_type
%ifdef REF_RESERVED_WORD
       | basic_type ref
%endif
       ;

new_arg:
        arg_type optional_star
      | arg_type optional_star new_local_name
      | new_local_name
      ;

argument:
/* empty */
    |   argument_list
    |   argument_list L_DOT_DOT_DOT
    ;

argument_list:
new_arg
    |   argument_list ',' new_arg
    ;

type_modifier_list:
/* empty */
    |   L_TYPE_MODIFIER type_modifier_list
    ;

type:
type_modifier_list opt_basic_type
    ;

cast:
'(' basic_type optional_star ')'
    ;

opt_basic_type:
        basic_type
    |   /* empty */
    ;

name_list:
new_name
    |   new_name ',' name_list
    ;

new_name:
optional_star identifier
    |   optional_star identifier L_ASSIGN expr0
    ;

block:
'{' local_declarations statements '}'
    ;

decl_block: block | for | foreach ;

local_declarations:
        /* empty */
    |   local_declarations basic_type
        local_name_list ';'
    ;

new_local_def:
optional_star new_local_name
    |   optional_star new_local_name L_ASSIGN expr0
    ;

single_new_local_def:
        arg_type optional_star new_local_name
    ;

single_new_local_def_with_init:
        single_new_local_def L_ASSIGN expr0
    ;

local_name_list:
        new_local_def
    |   new_local_def ',' local_name_list
    ;

statements:
/* empty */
    |   statement statements
    |   error ';'
    ;

statement:
comma_expr ';'
    |   cond
    |   while
    |   do
    |   switch
    |   return
    |   decl_block
    |   /* empty */ ';'
    |   L_BREAK ';'
    |   L_CONTINUE ';'
    ;

while:
       L_WHILE '(' comma_expr ')'
statement
    ;

do:
        L_DO
        statement L_WHILE '(' comma_expr ')' ';'
    ;

for:
L_FOR '(' first_for_expr ';' for_expr ';' for_expr ')'
    ;

foreach_var: L_DEFINED_NAME
          | single_new_local_def
          | L_IDENTIFIER
     ;

foreach_vars:
        foreach_var
     |  foreach_var ',' foreach_var
     ;

foreach:
        L_FOREACH '(' foreach_vars L_IN expr0 ')'
        statement
         ;

for_expr:
/* EMPTY */
    |   comma_expr
    ;

first_for_expr:
        for_expr
    |   single_new_local_def_with_init
    ;

 switch:
        L_SWITCH '(' comma_expr ')'
       '{' local_declarations case switch_block '}'
    ;

 switch_block:
        case switch_block
    |   statement switch_block
    |   /* empty */
    ;

 case:
        L_CASE case_label ':'
    |   L_CASE case_label L_RANGE case_label ':'
    |   L_CASE case_label L_RANGE ':'
    |   L_CASE L_RANGE case_label ':'
    |  L_DEFAULT ':'
    ;

 case_label:
        constant
    |   string_con1
    ;

 constant:
        constant '|' constant
    |   constant '^' constant
    |   constant '&' constant
    |   constant L_EQ constant
    |   constant L_NE constant
    |   constant L_ORDER constant
    |   constant '<' constant
    |   constant L_LSH constant
    |   constant L_RSH constant
    |   constant '+' constant
    |   constant '-' constant
    |   constant '*' constant
    |   constant '%' constant
    |   constant '/' constant
    |   '(' constant ')'
    |   L_NUMBER
    |   '-' L_NUMBER
    |   L_NOT L_NUMBER
    |   '~' L_NUMBER
    ;

comma_expr:
expr0
    |   comma_expr ',' expr0
    ;

%ifdef REF_RESERVED_WORD
ref:
      L_REF
%ifdef COMPAT_32
    | '&'
%endif
    ;
%endif

expr0:
%ifdef REF_RESERVED_WORD
        ref lvalue
    |
%endif
lvalue L_ASSIGN expr0
    |   error L_ASSIGN expr0
    |   expr0 '?' expr0 ':' expr0 %prec '?'
    |   expr0 L_LOR expr0
    |   expr0 L_LAND expr0
    |   expr0 '|' expr0
    |   expr0 '^' expr0
    |   expr0 '&' expr0
    |   expr0 L_EQ expr0
    |   expr0 L_NE expr0
    |   expr0 L_ORDER expr0
    |   expr0 '<' expr0
    |   expr0 L_LSH expr0
    |   expr0 L_RSH expr0
    |   expr0 '+' expr0
    |   expr0 '-' expr0
    |   expr0 '*' expr0
    |   expr0 '%' expr0
    |   expr0 '/' expr0
    |   cast expr0  %prec L_NOT
    |   L_INC lvalue  %prec L_NOT  /* note lower precedence here */
    |   L_DEC lvalue  %prec L_NOT  /* note lower precedence here */
    |   L_NOT expr0
    |   '~' expr0
    |   '-' expr0  %prec L_NOT
    |   lvalue L_INC   /* normal precedence here */
    |   lvalue L_DEC
    |   expr4
    |   sscanf
    |   parse_command
    |   time_expression
    |   number
    |   real
    ;

return:
L_RETURN ';'
    |   L_RETURN comma_expr ';'
    ;

expr_list:
/* empty */
    |   expr_list2
    |   expr_list2 ','
    ;

expr_list_node:
        expr0
    |   expr0 L_DOT_DOT_DOT
    ;

expr_list2:
        expr_list_node
    |   expr_list2 ',' expr_list_node
    ;

expr_list3:
/* empty */
    |   expr_list4
    |   expr_list4 ','
    ;

expr_list4:
assoc_pair
    |   expr_list4 ',' assoc_pair
    ;

assoc_pair:
expr0 ':' expr0
    ;

lvalue:
        expr4
        ;

l_new_function_open: L_NEW_FUNCTION_OPEN
    | L_FUNCTION_OPEN efun_override
    ;

%ifdef COMPAT_32
simple_function_pointer: l_new_function_open ':' ')'
    |   L_LAMBDA L_DEFINED_NAME
    ;
%endif

expr4:
function_call
    |   L_DEFINED_NAME
    |   L_IDENTIFIER
    |   L_PARAMETER
    |   '$' '('
    |   expr4 L_ARROW identifier
    |   expr4 '[' comma_expr L_RANGE comma_expr ']'
    |   expr4 '[' '<' comma_expr L_RANGE comma_expr ']'
    |   expr4 '[' '<' comma_expr L_RANGE '<' comma_expr ']'
    |   expr4 '[' comma_expr L_RANGE '<' comma_expr ']'
    |   expr4 '[' comma_expr L_RANGE ']'
    |   expr4 '[' '<' comma_expr L_RANGE ']'
    |   expr4 '[' '<' comma_expr ']'
    |   expr4 '[' comma_expr ']'
    |   string
    |   '(' comma_expr ')'
    |   catch
%ifdef DEBUG
    |   tree
%endif
    |   L_BASIC_TYPE
%ifdef COMPAT_32
    |   simple_function_pointer
%else
    |   l_new_function_open ':' ')'
%endif
    |   l_new_function_open ',' expr_list2 ':' ')'
    |   L_FUNCTION_OPEN comma_expr ':' ')'
    |   L_MAPPING_OPEN expr_list3 ']' ')'
    |   L_ARRAY_OPEN expr_list '}' ')'
    ;

expr_or_block:
        block
    |   '(' comma_expr ')'
    ;

catch:
L_CATCH
        expr_or_block
    ;

%ifdef DEBUG
tree:
L_TREE block
    |
        L_TREE '(' comma_expr ')'
    ;
%endif

sscanf:
L_SSCANF '(' expr0 ',' expr0 lvalue_list ')'
    ;

parse_command:
L_PARSE_COMMAND '(' expr0 ',' expr0 ',' expr0 lvalue_list ')'
    ;

time_expression:
L_TIME_EXPRESSION
expr_or_block
    ;

lvalue_list:
/* empty */
    |   ',' lvalue lvalue_list
    ;

string:
string_con2
    ;

string_con1:
string_con2
    |   '(' string_con1 ')'
    |   string_con1 '+' string_con1
    ;

string_con2:
L_STRING
    |   string_con2 L_STRING
    ;

class_init: identifier ':' expr0
    ;

opt_class_init:
/* empty */
    | opt_class_init ',' class_init
    ;


function_call:
efun_override '('
        | L_NEW '('
        | L_NEW '(' L_CLASS L_DEFINED_NAME opt_class_init ')'
| L_NEW '(' L_CLASS L_IDENTIFIER opt_class_init ')'
| L_DEFINED_NAME '(' expr_list ')'
| function_name '(' expr_list ')'
    |   expr4 L_ARROW identifier '(' expr_list ')'
    |   '(' '*' comma_expr ')' '(' expr_list ')'
    ;

efun_override: L_EFUN L_COLON_COLON identifier
    | L_EFUN L_COLON_COLON L_NEW
    ;
   
function_name:
L_IDENTIFIER
    |   L_COLON_COLON identifier
    |   L_BASIC_TYPE L_COLON_COLON identifier
    |   identifier L_COLON_COLON identifier
    ;

cond:
        L_IF '(' comma_expr ')' statement optional_else_part
    ;

optional_else_part:
/* empty */    %prec LOWER_THAN_ELSE
    |   L_ELSE statement
    ;
%%

%line