mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +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
|
||||
qfcc=qfcc
|
||||
qfpc=qfpc
|
||||
qfpreqcc=qfpreqcc
|
||||
qfprogs=qfprogs
|
||||
else
|
||||
qfcc=
|
||||
qfpc=
|
||||
qfpreqcc=
|
||||
qfprogs=
|
||||
endif
|
||||
|
||||
bin_PROGRAMS= $(qfcc) $(qfprogs)
|
||||
bin_PROGRAMS= $(qfcc) $(qfpc) $(qfprogs)
|
||||
bin_SCRIPTS= $(qfpreqcc)
|
||||
EXTRA_PROGRAMS= qfcc qfprogs
|
||||
EXTRA_PROGRAMS= qfcc qfpc qfprogs
|
||||
|
||||
common_src=\
|
||||
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_DEPENDENCIES= $(QFCC_DEPS)
|
||||
|
||||
qfpc_SOURCES= qp-lex.l qp-parse.y $(common_src)
|
||||
qfpc_LDADD= $(QFCC_LIBS)
|
||||
qfpc_DEPENDENCIES= $(QFCC_DEPS)
|
||||
|
||||
qfprogs_SOURCES= \
|
||||
disassemble.c globals.c lines.c modules.c obj_file.c stub.c qfprogs.c strings.c
|
||||
qfprogs_LDADD= $(QFCC_LIBS)
|
||||
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