mirror of https://github.com/ademakov/libjit
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
7.7 KiB
351 lines
7.7 KiB
%{
|
|
/*
|
|
* dpas-scanner.l - Input file for lex for the Dynamic Pascal token syntax.
|
|
*
|
|
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
|
|
*
|
|
* 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 the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "dpas-internal.h"
|
|
#include "dpas-parser.h"
|
|
|
|
extern YYSTYPE yylval;
|
|
|
|
/*
|
|
* Current file and line number.
|
|
*/
|
|
char *dpas_filename = "";
|
|
long dpas_linenum = 1;
|
|
|
|
/*
|
|
* Return a token code from the lexical analyser.
|
|
*/
|
|
#define RETURNTOK(x) return (x)
|
|
|
|
/*
|
|
* Parse a string value.
|
|
*/
|
|
static char *dpas_parse_string(const char *text)
|
|
{
|
|
int quote = *text++;
|
|
char *str = (char *)jit_malloc(jit_strlen(text));
|
|
char *temp;
|
|
if(!str)
|
|
{
|
|
dpas_out_of_memory();
|
|
}
|
|
temp = str;
|
|
while(*text != '\0')
|
|
{
|
|
if(text[0] == quote && text[1] == quote)
|
|
{
|
|
*temp++ = (char)quote;
|
|
text += 2;
|
|
}
|
|
else if(text[0] == quote)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
*temp++ = *text++;
|
|
}
|
|
}
|
|
*temp = '\0';
|
|
return str;
|
|
}
|
|
|
|
/*
|
|
* Parse a floating-point value.
|
|
*/
|
|
static jit_nfloat dpas_parse_float(const char *text)
|
|
{
|
|
double value = 0.0;
|
|
sscanf(text, "%lf", &value);
|
|
return (jit_nfloat)value;
|
|
}
|
|
|
|
/*
|
|
* Infer the best type for an integer constant.
|
|
*/
|
|
static void dpas_infer_type(YYSTYPE *lval)
|
|
{
|
|
jit_ulong value = lval->int_const.value;
|
|
if(value <= (jit_ulong)(jit_long)jit_max_int)
|
|
{
|
|
lval->int_const.type = jit_type_int;
|
|
}
|
|
else if(value <= (jit_ulong)jit_max_uint)
|
|
{
|
|
lval->int_const.type = jit_type_uint;
|
|
}
|
|
else if(value <= (jit_ulong)jit_max_long)
|
|
{
|
|
lval->int_const.type = jit_type_long;
|
|
}
|
|
else
|
|
{
|
|
lval->int_const.type = jit_type_ulong;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Parse a decimal integer value.
|
|
*/
|
|
static void dpas_parse_decimal(const char *text, YYSTYPE *lval)
|
|
{
|
|
jit_ulong value = 0;
|
|
while(*text != '\0')
|
|
{
|
|
value = value * 10 + (jit_ulong)(*text - '0');
|
|
++text;
|
|
}
|
|
lval->int_const.value = value;
|
|
dpas_infer_type(lval);
|
|
}
|
|
|
|
/*
|
|
* Parse a hexadecimal integer value.
|
|
*/
|
|
static void dpas_parse_hex(const char *text, YYSTYPE *lval)
|
|
{
|
|
jit_ulong value = 0;
|
|
while(*text != '\0')
|
|
{
|
|
if(*text >= '0' && *text <= '9')
|
|
{
|
|
value = value * 16 + (jit_ulong)(*text - '0');
|
|
}
|
|
else if(*text >= 'A' && *text <= 'F')
|
|
{
|
|
value = value * 16 + (jit_ulong)(*text - 'A' + 10);
|
|
}
|
|
else if(*text >= 'a' && *text <= 'f')
|
|
{
|
|
value = value * 16 + (jit_ulong)(*text - 'a' + 10);
|
|
}
|
|
++text;
|
|
}
|
|
lval->int_const.value = value;
|
|
dpas_infer_type(lval);
|
|
}
|
|
|
|
/*
|
|
* Forward declaration.
|
|
*/
|
|
static void dpas_skip_comment(int star_style);
|
|
|
|
%}
|
|
|
|
%option outfile="lex.yy.c"
|
|
%option noyywrap
|
|
%option nounput
|
|
%option case-insensitive
|
|
|
|
DIGIT [0-9]
|
|
HEX [0-9A-Fa-f]
|
|
IDALPHA [a-zA-Z_]
|
|
EXPONENT [Ee][+-]?{DIGIT}+
|
|
WHITE [ \t\v\r\f]
|
|
|
|
%%
|
|
|
|
"<>" { RETURNTOK(K_NE); }
|
|
"<=" { RETURNTOK(K_LE); }
|
|
">=" { RETURNTOK(K_GE); }
|
|
":=" { RETURNTOK(K_ASSIGN); }
|
|
".." { RETURNTOK(K_DOT_DOT); }
|
|
"**" { RETURNTOK(K_POW); }
|
|
|
|
"and" { RETURNTOK(K_AND); }
|
|
"array" { RETURNTOK(K_ARRAY); }
|
|
"begin" { RETURNTOK(K_BEGIN); }
|
|
"case" { RETURNTOK(K_CASE); }
|
|
"catch" { RETURNTOK(K_CATCH); }
|
|
"const" { RETURNTOK(K_CONST); }
|
|
"div" { RETURNTOK(K_DIV); }
|
|
"do" { RETURNTOK(K_DO); }
|
|
"downto" { RETURNTOK(K_DOWNTO); }
|
|
"else" { RETURNTOK(K_ELSE); }
|
|
"end" { RETURNTOK(K_END); }
|
|
"exit" { RETURNTOK(K_EXIT); }
|
|
"fastcall" { RETURNTOK(K_FASTCALL); }
|
|
"finally" { RETURNTOK(K_FINALLY); }
|
|
"for" { RETURNTOK(K_FOR); }
|
|
"forward" { RETURNTOK(K_FORWARD); }
|
|
"function" { RETURNTOK(K_FUNCTION); }
|
|
"goto" { RETURNTOK(K_GOTO); }
|
|
"if" { RETURNTOK(K_IF); }
|
|
"in" { RETURNTOK(K_IN); }
|
|
"label" { RETURNTOK(K_LABEL); }
|
|
"import" { RETURNTOK(K_IMPORT); }
|
|
"mod" { RETURNTOK(K_MOD); }
|
|
"module" { RETURNTOK(K_MODULE); }
|
|
"nil" { RETURNTOK(K_NIL); }
|
|
"not" { RETURNTOK(K_NOT); }
|
|
"of" { RETURNTOK(K_OF); }
|
|
"or" { RETURNTOK(K_OR); }
|
|
"packed" { RETURNTOK(K_PACKED); }
|
|
"pow" { RETURNTOK(K_POW); }
|
|
"procedure" { RETURNTOK(K_PROCEDURE); }
|
|
"program" { RETURNTOK(K_PROGRAM); }
|
|
"record" { RETURNTOK(K_RECORD); }
|
|
"repeat" { RETURNTOK(K_REPEAT); }
|
|
"set" { RETURNTOK(K_SET); }
|
|
"shl" { RETURNTOK(K_SHL); }
|
|
"shr" { RETURNTOK(K_SHR); }
|
|
"sizeof" { RETURNTOK(K_SIZEOF); }
|
|
"stdcall" { RETURNTOK(K_STDCALL); }
|
|
"then" { RETURNTOK(K_THEN); }
|
|
"throw" { RETURNTOK(K_THROW); }
|
|
"to" { RETURNTOK(K_TO); }
|
|
"try" { RETURNTOK(K_TRY); }
|
|
"type" { RETURNTOK(K_TYPE); }
|
|
"until" { RETURNTOK(K_UNTIL); }
|
|
"var" { RETURNTOK(K_VAR); }
|
|
"va_arg" { RETURNTOK(K_VA_ARG); }
|
|
"with" { RETURNTOK(K_WITH); }
|
|
"while" { RETURNTOK(K_WHILE); }
|
|
"xor" { RETURNTOK(K_XOR); }
|
|
|
|
'(''|[^'])*' { yylval.name = dpas_parse_string(yytext);
|
|
RETURNTOK(STRING_CONSTANT); }
|
|
|
|
\"(\"\"|[^"])*\" { yylval.name = dpas_parse_string(yytext);
|
|
RETURNTOK(STRING_CONSTANT); }
|
|
|
|
{IDALPHA}({DIGIT}|{IDALPHA})* {
|
|
yylval.name = jit_strdup(yytext);
|
|
if(!(yylval.name))
|
|
{
|
|
dpas_out_of_memory();
|
|
}
|
|
RETURNTOK(IDENTIFIER);
|
|
}
|
|
|
|
{DIGIT}+{EXPONENT} { yylval.real_const = dpas_parse_float(yytext);
|
|
RETURNTOK(REAL_CONSTANT); }
|
|
{DIGIT}+"."{DIGIT}*{EXPONENT} { yylval.real_const = dpas_parse_float(yytext);
|
|
RETURNTOK(REAL_CONSTANT); }
|
|
{DIGIT}+"."{DIGIT}+ { yylval.real_const = dpas_parse_float(yytext);
|
|
RETURNTOK(REAL_CONSTANT); }
|
|
{DIGIT}+"."[^.] { yylval.real_const = dpas_parse_float(yytext);
|
|
RETURNTOK(REAL_CONSTANT); }
|
|
|
|
{DIGIT}{HEX}*[hH] { dpas_parse_hex(yytext, &yylval);
|
|
RETURNTOK(INTEGER_CONSTANT); }
|
|
|
|
{DIGIT}+ { dpas_parse_decimal(yytext, &yylval);
|
|
RETURNTOK(INTEGER_CONSTANT); }
|
|
|
|
{WHITE}+ ;
|
|
|
|
\n { ++dpas_linenum; }
|
|
|
|
"{" { dpas_skip_comment(0); }
|
|
"(*" { dpas_skip_comment(1); }
|
|
|
|
. { RETURNTOK(((int)(yytext[0])) & 0xFF); }
|
|
|
|
%%
|
|
|
|
void dpas_load_file(char *filename, FILE *file)
|
|
{
|
|
char *saved_filename;
|
|
long saved_linenum;
|
|
YY_BUFFER_STATE saved_buffer;
|
|
YY_BUFFER_STATE new_buffer;
|
|
extern int yyparse(void);
|
|
|
|
/* Save the current state */
|
|
saved_filename = dpas_filename;
|
|
saved_linenum = dpas_linenum;
|
|
saved_buffer = YY_CURRENT_BUFFER;
|
|
|
|
/* Create a buffer for the new file */
|
|
new_buffer = yy_create_buffer(file, BUFSIZ);
|
|
if(!new_buffer)
|
|
{
|
|
dpas_out_of_memory();
|
|
}
|
|
|
|
/* Switch to the new state */
|
|
dpas_filename = filename;
|
|
dpas_linenum = 1;
|
|
yy_switch_to_buffer(new_buffer);
|
|
|
|
/* Call the parser */
|
|
if(yyparse())
|
|
{
|
|
dpas_error_reported = 1;
|
|
}
|
|
|
|
/* Bail out if this was the top-most file in the parse process,
|
|
because flex cannot switch to a NULL buffer */
|
|
if(!saved_buffer)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Switch back to the original file */
|
|
dpas_filename = saved_filename;
|
|
dpas_linenum = saved_linenum;
|
|
yy_switch_to_buffer(saved_buffer);
|
|
|
|
/* Delete the buffer that we used on the file we just parsed */
|
|
yy_delete_buffer(new_buffer);
|
|
}
|
|
|
|
/*
|
|
* Skip a comment in the input stream.
|
|
*/
|
|
static void dpas_skip_comment(int star_style)
|
|
{
|
|
int ch;
|
|
for(;;)
|
|
{
|
|
ch = input();
|
|
if(ch == EOF)
|
|
{
|
|
break;
|
|
}
|
|
else if(ch == '}' && !star_style)
|
|
{
|
|
break;
|
|
}
|
|
else if(ch == '*' && star_style)
|
|
{
|
|
ch = input();
|
|
while(ch == '*')
|
|
{
|
|
ch = input();
|
|
}
|
|
if(ch == EOF || ch == ')')
|
|
{
|
|
break;
|
|
}
|
|
else if(ch == '\n')
|
|
{
|
|
++dpas_linenum;
|
|
}
|
|
}
|
|
else if(ch == '\n')
|
|
{
|
|
++dpas_linenum;
|
|
}
|
|
}
|
|
}
|
|
|
|
|