mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 22:31:05 +00:00
The first stages of Quake-Pascal.
At present, this parses a subset of the pascal language with a few type extensions. There is already work on the type system.
This commit is contained in:
parent
ae4ca52661
commit
fed82466cc
3 changed files with 521 additions and 4 deletions
|
@ -37,17 +37,19 @@ YFLAGS = -v -d
|
||||||
|
|
||||||
if BUILD_QFCC
|
if BUILD_QFCC
|
||||||
qfcc=qfcc
|
qfcc=qfcc
|
||||||
|
qfpc=qfpc
|
||||||
qfpreqcc=qfpreqcc
|
qfpreqcc=qfpreqcc
|
||||||
qfprogs=qfprogs
|
qfprogs=qfprogs
|
||||||
else
|
else
|
||||||
qfcc=
|
qfcc=
|
||||||
|
qfpc=
|
||||||
qfpreqcc=
|
qfpreqcc=
|
||||||
qfprogs=
|
qfprogs=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
bin_PROGRAMS= $(qfcc) $(qfprogs)
|
bin_PROGRAMS= $(qfcc) $(qfpc) $(qfprogs)
|
||||||
bin_SCRIPTS= $(qfpreqcc)
|
bin_SCRIPTS= $(qfpreqcc)
|
||||||
EXTRA_PROGRAMS= qfcc qfprogs
|
EXTRA_PROGRAMS= qfcc qfpc qfprogs
|
||||||
|
|
||||||
common_src=\
|
common_src=\
|
||||||
class.c constfold.c cpp.c debug.c def.c emit.c expr.c function.c grab.c \
|
class.c constfold.c cpp.c debug.c def.c emit.c expr.c function.c grab.c \
|
||||||
|
@ -59,11 +61,16 @@ qfcc_SOURCES= qc-lex.l qc-parse.y $(common_src)
|
||||||
qfcc_LDADD= $(QFCC_LIBS)
|
qfcc_LDADD= $(QFCC_LIBS)
|
||||||
qfcc_DEPENDENCIES= $(QFCC_DEPS)
|
qfcc_DEPENDENCIES= $(QFCC_DEPS)
|
||||||
|
|
||||||
|
qfpc_SOURCES= qp-lex.l qp-parse.y $(common_src)
|
||||||
|
qfpc_LDADD= $(QFCC_LIBS)
|
||||||
|
qfpc_DEPENDENCIES= $(QFCC_DEPS)
|
||||||
|
|
||||||
qfprogs_SOURCES= \
|
qfprogs_SOURCES= \
|
||||||
disassemble.c globals.c lines.c modules.c obj_file.c stub.c qfprogs.c strings.c
|
disassemble.c globals.c lines.c modules.c obj_file.c stub.c qfprogs.c strings.c
|
||||||
qfprogs_LDADD= $(QFCC_LIBS)
|
qfprogs_LDADD= $(QFCC_LIBS)
|
||||||
qfprogs_DEPENDENCIES= $(QFCC_DEPS)
|
qfprogs_DEPENDENCIES= $(QFCC_DEPS)
|
||||||
|
|
||||||
BUILT_SOURCES=qc-parse.c qc-parse.h qc-lex.c
|
BUILT_SOURCES=qc-parse.c qc-parse.h qc-lex.c qp-parse.c qp-parse.h qp-lex.c
|
||||||
|
|
||||||
EXTRA_DIST=qc-lex.c qc-parse.c qc-parse.h qfpreqcc
|
EXTRA_DIST=qc-lex.c qc-parse.c qc-parse.h qfpreqcc \
|
||||||
|
qp-parse.c qp-parse.h qp-lex.c
|
||||||
|
|
242
tools/qfcc/source/qp-lex.l
Normal file
242
tools/qfcc/source/qp-lex.l
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
%{
|
||||||
|
/*
|
||||||
|
qp-lex.l
|
||||||
|
|
||||||
|
lexer for QuakePascal
|
||||||
|
|
||||||
|
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||||
|
|
||||||
|
Author: Bill Currie <bill@taniwha.org>
|
||||||
|
Date: 2011/01/06
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static __attribute__ ((used)) const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
|
#include "QF/hash.h"
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
#include "expr.h"
|
||||||
|
#include "grab.h"
|
||||||
|
#include "qfcc.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
#include "qp-parse.h"
|
||||||
|
|
||||||
|
#ifndef YY_PROTO
|
||||||
|
# define YY_PROTO(x) x
|
||||||
|
#else
|
||||||
|
# define YY_FLEX_REALLOC_HACK
|
||||||
|
#endif
|
||||||
|
int yyget_lineno (void);
|
||||||
|
FILE *yyget_in (void);
|
||||||
|
FILE *yyget_out (void);
|
||||||
|
int yyget_leng (void);
|
||||||
|
char *yyget_text (void);
|
||||||
|
void yyset_lineno (int line_number);
|
||||||
|
void yyset_in (FILE * in_str);
|
||||||
|
void yyset_out (FILE * out_str);
|
||||||
|
int yyget_debug (void);
|
||||||
|
void yyset_debug (int bdebug);
|
||||||
|
int yylex_destroy (void);
|
||||||
|
|
||||||
|
#define YY_NO_UNPUT
|
||||||
|
#define YY_DECL int yylex YY_PROTO(( void ))
|
||||||
|
YY_DECL;
|
||||||
|
|
||||||
|
|
||||||
|
static int keyword_or_id (const char *token);
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
s [ \t]
|
||||||
|
m [\-+]
|
||||||
|
D [0-9]
|
||||||
|
X [0-9a-fA-F]
|
||||||
|
ID [a-zA-Z_][0-9a-zA-Z_]*
|
||||||
|
FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)?
|
||||||
|
INTEGER ({D}+|0[xX]{X}+)
|
||||||
|
RELOP (=|<>|[<>]=?)
|
||||||
|
ADDOP [\-+]
|
||||||
|
MULOP [*/]
|
||||||
|
ASSIGNOP :=
|
||||||
|
RANGE \.\.
|
||||||
|
|
||||||
|
%x GRAB_FRAME GRAB_OTHER COMMENT
|
||||||
|
|
||||||
|
%%
|
||||||
|
grab_frame = -GRAB_FRAME;
|
||||||
|
grab_other = -GRAB_OTHER;
|
||||||
|
|
||||||
|
"{" { BEGIN (COMMENT); }
|
||||||
|
<COMMENT>"{" { warning (0, "nested { in comment"); }
|
||||||
|
<COMMENT>"}" { BEGIN (INITIAL); }
|
||||||
|
<COMMENT>\r*\n { pr.source_line++; }
|
||||||
|
<COMMENT>. /* nothing to do, with people like you */
|
||||||
|
<COMMENT><<EOF>> { error (0, "EOF in comment"); return 0; }
|
||||||
|
|
||||||
|
^#{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); }
|
||||||
|
^#line{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); }
|
||||||
|
|
||||||
|
{INTEGER} {
|
||||||
|
yylval.integer_val = strtol (yytext, 0, 0);
|
||||||
|
return INT_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
{FLOAT} {
|
||||||
|
yylval.float_val = strtof (yytext, 0);
|
||||||
|
return FLOAT_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
{ID} return keyword_or_id (yytext);
|
||||||
|
|
||||||
|
\"(\\.|[^"\\])*\" {
|
||||||
|
yylval.string_val = make_string (yytext, 0);
|
||||||
|
return STRING_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
'{s}*{m}{FLOAT}{s}+{m}{FLOAT}{s}+{m}{FLOAT}{s}*' {
|
||||||
|
sscanf (yytext, "' %f %f %f '",
|
||||||
|
&yylval.vector_val[0], &yylval.vector_val[1],
|
||||||
|
&yylval.vector_val[2]);
|
||||||
|
return VECTOR_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
'{s}*{m}{FLOAT}{s}+{m}{FLOAT}{s}+{m}{FLOAT}{s}+{m}{FLOAT}{s}*' {
|
||||||
|
sscanf (yytext, "' %f %f %f %f '",
|
||||||
|
&yylval.quaternion_val[0],
|
||||||
|
&yylval.quaternion_val[1],
|
||||||
|
&yylval.quaternion_val[2],
|
||||||
|
&yylval.quaternion_val[3]);
|
||||||
|
return QUATERNION_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
{RELOP} {
|
||||||
|
yylval.string_val = save_string (yytext);
|
||||||
|
return RELOP;
|
||||||
|
}
|
||||||
|
{ADDOP} {
|
||||||
|
yylval.integer_val = yytext[0];
|
||||||
|
return ADDOP;
|
||||||
|
}
|
||||||
|
{MULOP} {
|
||||||
|
yylval.integer_val = yytext[0];
|
||||||
|
return MULOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
{ASSIGNOP} return ASSIGNOP;
|
||||||
|
|
||||||
|
{RANGE} return RANGE;
|
||||||
|
|
||||||
|
[!(){}.&|^~\[\];,#%?:] return yytext[0];
|
||||||
|
|
||||||
|
<*>\r*\n {
|
||||||
|
pr.source_line++;
|
||||||
|
BEGIN (INITIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
<*>{s}* /* skip whitespace */
|
||||||
|
|
||||||
|
<*>. error (0, "all your typo are belong to us");
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
int
|
||||||
|
yywrap (void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
int value;
|
||||||
|
type_t *type;
|
||||||
|
} keyword_t;
|
||||||
|
|
||||||
|
static keyword_t keywords[] = {
|
||||||
|
{"real", TYPE, &type_float},
|
||||||
|
{"string", TYPE, &type_string},
|
||||||
|
{"vector", TYPE, &type_vector},
|
||||||
|
{"entity", TYPE, &type_entity},
|
||||||
|
{"quaternion", TYPE, &type_quaternion},
|
||||||
|
{"integer", TYPE, &type_integer},
|
||||||
|
|
||||||
|
{"program", PROGRAM, 0},
|
||||||
|
{"var", VAR, 0},
|
||||||
|
{"array", ARRAY, 0},
|
||||||
|
{"of", OF, 0},
|
||||||
|
{"function", FUNCTION, 0},
|
||||||
|
{"prodedure", PROCEDURE, 0},
|
||||||
|
{"begin", PBEGIN, 0},
|
||||||
|
{"end", END, 0},
|
||||||
|
{"if", IF, 0},
|
||||||
|
{"then", THEN, 0},
|
||||||
|
{"else", ELSE, 0},
|
||||||
|
{"while", WHILE, 0},
|
||||||
|
{"do", DO, 0},
|
||||||
|
{"or", ADDOP, 0},
|
||||||
|
{"div", MULOP, 0},
|
||||||
|
{"mod", MULOP, 0},
|
||||||
|
{"and", MULOP, 0},
|
||||||
|
{"not", NOT, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
keyword_get_key (void *kw, void *unused)
|
||||||
|
{
|
||||||
|
return ((keyword_t *) kw)->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
keyword_or_id (const char *token)
|
||||||
|
{
|
||||||
|
static hashtab_t *keyword_tab;
|
||||||
|
keyword_t *keyword;
|
||||||
|
|
||||||
|
if (!keyword_tab) {
|
||||||
|
size_t i;
|
||||||
|
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
|
||||||
|
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
|
||||||
|
Hash_Add (keyword_tab, &keywords[i]);
|
||||||
|
}
|
||||||
|
keyword = Hash_Find (keyword_tab, token);
|
||||||
|
if (keyword) {
|
||||||
|
if (keyword->value == ADDOP || keyword->value == MULOP) {
|
||||||
|
yylval.integer_val = yytext[0];
|
||||||
|
} else {
|
||||||
|
yylval.type = keyword->type;
|
||||||
|
}
|
||||||
|
return keyword->value;
|
||||||
|
}
|
||||||
|
yylval.string_val = save_string (token);
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef YY_FLEX_REALLOC_HACK
|
||||||
|
static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc;
|
||||||
|
#else
|
||||||
|
static __attribute__ ((used)) void (*yyunput_hack)(int, char*) = yyunput;
|
||||||
|
static __attribute__ ((used)) int (*input_hack)(void) = input;
|
||||||
|
#endif
|
||||||
|
|
268
tools/qfcc/source/qp-parse.y
Normal file
268
tools/qfcc/source/qp-parse.y
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
%{
|
||||||
|
/*
|
||||||
|
qc-parse.y
|
||||||
|
|
||||||
|
parser for quakec
|
||||||
|
|
||||||
|
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
|
||||||
|
|
||||||
|
Author: Bill Currie <bill@taniwha.org>
|
||||||
|
Date: 2001/06/12
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static __attribute__ ((used)) const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
|
#include "class.h"
|
||||||
|
#include "expr.h"
|
||||||
|
#include "function.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
#define YYDEBUG 1
|
||||||
|
#define YYERROR_VERBOSE 1
|
||||||
|
#undef YYERROR_VERBOSE
|
||||||
|
|
||||||
|
extern char *yytext;
|
||||||
|
|
||||||
|
static void
|
||||||
|
yyerror (const char *s)
|
||||||
|
{
|
||||||
|
#ifdef YYERROR_VERBOSE
|
||||||
|
error (0, "%s %s\n", yytext, s);
|
||||||
|
#else
|
||||||
|
error (0, "%s before %s", s, yytext);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_error (void)
|
||||||
|
{
|
||||||
|
error (0, "parse error before %s", yytext);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PARSE_ERROR do { parse_error (); YYERROR; } while (0)
|
||||||
|
|
||||||
|
int yylex (void);
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union {
|
||||||
|
int op;
|
||||||
|
struct def_s *def;
|
||||||
|
struct hashtab_s *def_list;
|
||||||
|
struct type_s *type;
|
||||||
|
struct typedef_s *typename;
|
||||||
|
struct expr_s *expr;
|
||||||
|
int integer_val;
|
||||||
|
unsigned uinteger_val;
|
||||||
|
float float_val;
|
||||||
|
const char *string_val;
|
||||||
|
float vector_val[3];
|
||||||
|
float quaternion_val[4];
|
||||||
|
struct function_s *function;
|
||||||
|
struct switch_block_s *switch_block;
|
||||||
|
struct param_s *param;
|
||||||
|
struct method_s *method;
|
||||||
|
struct class_s *class;
|
||||||
|
struct category_s *category;
|
||||||
|
struct class_type_s *class_type;
|
||||||
|
struct protocol_s *protocol;
|
||||||
|
struct protocollist_s *protocol_list;
|
||||||
|
struct keywordarg_s *keywordarg;
|
||||||
|
struct methodlist_s *methodlist;
|
||||||
|
struct struct_s *strct;
|
||||||
|
}
|
||||||
|
|
||||||
|
%nonassoc IFX
|
||||||
|
%nonassoc ELSE
|
||||||
|
|
||||||
|
%left <string_val> RELOP
|
||||||
|
%left <integer_val> ADDOP
|
||||||
|
%left <integer_val> MULOP
|
||||||
|
%right UNARY
|
||||||
|
|
||||||
|
%token <type> TYPE
|
||||||
|
%token <string_val> ID
|
||||||
|
%token <integer_val> INT_VAL
|
||||||
|
%token <string_val> STRING_VAL
|
||||||
|
%token <quaternion_val> QUATERNION_VAL
|
||||||
|
%token <vector_val> VECTOR_VAL
|
||||||
|
%token <float_val> FLOAT_VAL
|
||||||
|
|
||||||
|
%token PROGRAM VAR ARRAY OF FUNCTION PROCEDURE PBEGIN END IF THEN ELSE
|
||||||
|
%token WHILE DO RANGE ASSIGNOP NOT
|
||||||
|
|
||||||
|
%type <type> standard_type type
|
||||||
|
%type <expr> const num
|
||||||
|
|
||||||
|
%{
|
||||||
|
function_t *current_func;
|
||||||
|
class_type_t *current_class;
|
||||||
|
expr_t *local_expr;
|
||||||
|
scope_t *current_scope;
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
program
|
||||||
|
: program_header
|
||||||
|
declarations
|
||||||
|
subprogram_declarations
|
||||||
|
compound_statement
|
||||||
|
'.'
|
||||||
|
;
|
||||||
|
|
||||||
|
program_header
|
||||||
|
: PROGRAM ID '(' identifier_list ')' ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier_list
|
||||||
|
: ID
|
||||||
|
| identifier_list ',' ID
|
||||||
|
;
|
||||||
|
|
||||||
|
declarations
|
||||||
|
: declarations VAR identifier_list ':' type ';'
|
||||||
|
| /* empty */
|
||||||
|
;
|
||||||
|
|
||||||
|
type
|
||||||
|
: standard_type { $$ = $1; }
|
||||||
|
| ARRAY '[' num RANGE num ']' OF standard_type
|
||||||
|
{
|
||||||
|
int top = $5->e.integer_val;
|
||||||
|
int bot = $3->e.integer_val;
|
||||||
|
$$ = array_type ($8, top - bot + 1);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
standard_type
|
||||||
|
: TYPE { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
subprogram_declarations
|
||||||
|
: subprogram_declarations subprogram_declaration
|
||||||
|
| /* emtpy */
|
||||||
|
;
|
||||||
|
|
||||||
|
subprogram_declaration
|
||||||
|
: subprogram_head ';' declarations compound_statement ';'
|
||||||
|
| subprogram_head '=' '#' const ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
subprogram_head
|
||||||
|
: FUNCTION ID arguments ':' standard_type
|
||||||
|
| PROCEDURE ID arguments
|
||||||
|
;
|
||||||
|
|
||||||
|
arguments
|
||||||
|
: '(' parameter_list ')'
|
||||||
|
| /* emtpy */
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_list
|
||||||
|
: identifier_list ':' type
|
||||||
|
| parameter_list ';' identifier_list ':' type
|
||||||
|
;
|
||||||
|
|
||||||
|
compound_statement
|
||||||
|
: PBEGIN optional_statements END
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_statements
|
||||||
|
: statement_list
|
||||||
|
| /* emtpy */
|
||||||
|
;
|
||||||
|
|
||||||
|
statement_list
|
||||||
|
: statement
|
||||||
|
| statement_list ';' statement
|
||||||
|
;
|
||||||
|
|
||||||
|
statement
|
||||||
|
: variable ASSIGNOP expression
|
||||||
|
| procedure_statement
|
||||||
|
| compound_statement
|
||||||
|
| IF expression THEN statement ELSE statement
|
||||||
|
| IF expression THEN statement %prec IFX
|
||||||
|
| WHILE expression DO statement
|
||||||
|
;
|
||||||
|
|
||||||
|
variable
|
||||||
|
: ID
|
||||||
|
| ID '[' expression ']'
|
||||||
|
;
|
||||||
|
|
||||||
|
procedure_statement
|
||||||
|
: ID
|
||||||
|
| ID '(' expression_list ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
expression_list
|
||||||
|
: expression
|
||||||
|
| expression_list ',' expression
|
||||||
|
;
|
||||||
|
|
||||||
|
unary_expr
|
||||||
|
: primary
|
||||||
|
| sign unary_expr %prec UNARY
|
||||||
|
| NOT expression %prec UNARY
|
||||||
|
;
|
||||||
|
|
||||||
|
primary
|
||||||
|
: variable
|
||||||
|
| const
|
||||||
|
| ID '(' expression_list ')'
|
||||||
|
| '(' expression ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: unary_expr
|
||||||
|
| expression RELOP expression
|
||||||
|
| expression ADDOP expression
|
||||||
|
| expression MULOP expression
|
||||||
|
;
|
||||||
|
|
||||||
|
sign
|
||||||
|
: ADDOP
|
||||||
|
{
|
||||||
|
if ($1 == 'o')
|
||||||
|
PARSE_ERROR;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
const
|
||||||
|
: num
|
||||||
|
| STRING_VAL { $$ = new_string_expr ($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
num
|
||||||
|
: INT_VAL { $$ = new_integer_expr ($1); }
|
||||||
|
| FLOAT_VAL { $$ = new_float_expr ($1); }
|
||||||
|
| VECTOR_VAL { $$ = new_vector_expr ($1); }
|
||||||
|
| QUATERNION_VAL { $$ = new_quaternion_expr ($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
Loading…
Reference in a new issue