2016-03-27 11:49:47 +02:00
|
|
|
%{
|
|
|
|
/*
|
|
|
|
* ===========================================================================
|
|
|
|
* Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
*
|
|
|
|
* This file is part of OpenMoHAA source code.
|
|
|
|
*
|
|
|
|
* OpenMoHAA source code 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.
|
|
|
|
*
|
|
|
|
* OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
* ===========================================================================
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* yyLexer.*: FLEX Lexical grammar for MoHScript.
|
|
|
|
*/
|
|
|
|
|
2023-01-30 18:20:50 +01:00
|
|
|
#include "scriptcompiler.h"
|
2023-06-17 16:54:12 +02:00
|
|
|
#include "./yyParser.hpp"
|
2017-02-19 21:14:27 +01:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
void fprintf2( FILE *f, const char *format, ... )
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
static char buffer[ 4200 ];
|
|
|
|
|
|
|
|
va_start( va, format );
|
|
|
|
vsprintf( buffer, format, va );
|
|
|
|
va_end( va );
|
|
|
|
|
2023-06-17 16:54:12 +02:00
|
|
|
gi.Printf( buffer );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define fprintf fprintf2
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
extern int prev_yylex;
|
|
|
|
extern int out_pos;
|
|
|
|
extern int success_pos;
|
|
|
|
parseStage_e parseStage;
|
|
|
|
|
|
|
|
/*
|
|
|
|
extern "C" int yywrap(void);
|
|
|
|
|
|
|
|
int yywrap(void) {
|
|
|
|
if (parseStage == PS_TYPE) {
|
|
|
|
parseStage = PS_BODY;
|
|
|
|
out_pos = 0;
|
|
|
|
success_pos = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parseStage == PS_BODY)
|
|
|
|
{
|
|
|
|
if (YY_START != 0)
|
|
|
|
{
|
|
|
|
parseStage = PS_BODY_END;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Compiler.CompileError(success_pos, "unexpected end of file found in comment");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
*/
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
extern yyparsedata parsedata;
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
void yyllocset(YYLTYPE *loc, uint32_t off)
|
|
|
|
{
|
|
|
|
success_pos = out_pos - yyleng + off;
|
|
|
|
loc->sourcePos = success_pos;
|
|
|
|
parsedata.pos = success_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void yyreducepos(uint32_t off)
|
|
|
|
{
|
|
|
|
out_pos -= off;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define YYLEX(n) { yyllocset(&yylloc, 0); prev_yylex = n; return n; }
|
|
|
|
#define YYLEXOFF(n, off) { yyllocset(&yylloc, off); prev_yylex = n; return n; }
|
|
|
|
|
|
|
|
#define YY_USER_ACTION \
|
|
|
|
{ \
|
|
|
|
out_pos += yyleng - yy_more_len; \
|
|
|
|
yylloc.sourcePos = out_pos; \
|
|
|
|
parsedata.pos = out_pos; \
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
#define YY_FATAL_ERROR( n ) yylexerror( n )
|
|
|
|
|
|
|
|
void yylexerror( const char *msg )
|
|
|
|
{
|
2023-06-17 16:54:12 +02:00
|
|
|
gi.Printf( "%s\n%s", msg, yytext );
|
2016-03-27 11:49:47 +02:00
|
|
|
assert( 0 );
|
|
|
|
}
|
|
|
|
|
2017-02-19 21:14:27 +01:00
|
|
|
static void TextEscapeValue( char *str, size_t len )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
char *to = parsetree_malloc( len + 1 );
|
|
|
|
|
|
|
|
yylval.s.val.stringValue = to;
|
|
|
|
|
|
|
|
while( len )
|
|
|
|
{
|
|
|
|
if( *str == '\\' )
|
|
|
|
{
|
|
|
|
len--;
|
|
|
|
|
|
|
|
if( !len )
|
|
|
|
break;
|
|
|
|
|
|
|
|
str++;
|
|
|
|
if( *str == 'n' )
|
|
|
|
{
|
|
|
|
*to = '\n';
|
|
|
|
}
|
|
|
|
else if( *str == 't' )
|
|
|
|
{
|
|
|
|
*to = '\t';
|
|
|
|
}
|
|
|
|
else if( *str == '"' )
|
|
|
|
{
|
|
|
|
*to = '\"';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*to = *str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*to = *str;
|
|
|
|
}
|
|
|
|
|
|
|
|
len--;
|
|
|
|
str++;
|
|
|
|
to++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*to = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-19 21:14:27 +01:00
|
|
|
static void TextValue( char *str, size_t len )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-08-12 19:59:40 +02:00
|
|
|
char* s = parsetree_malloc(len + 1);
|
|
|
|
strncpy(s, str, len);
|
|
|
|
s[len] = 0;
|
|
|
|
yylval.s.val.stringValue = s;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool UseField( void )
|
|
|
|
{
|
2023-08-12 19:59:40 +02:00
|
|
|
return prev_yylex == TOKEN_PERIOD
|
|
|
|
|| prev_yylex == TOKEN_DOLLAR;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
%}
|
|
|
|
|
|
|
|
/*%option debug*/
|
2023-06-17 16:54:12 +02:00
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
%option warn nodefault
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
%option never-interactive
|
2016-03-27 11:49:47 +02:00
|
|
|
%option yylineno
|
2023-08-12 19:59:40 +02:00
|
|
|
%option noyywrap
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
%x C_COMMENT
|
|
|
|
%x C_LINE_COMMENT
|
|
|
|
%x VARIABLES
|
|
|
|
%x IDENTIFIER
|
|
|
|
|
2023-06-17 17:00:17 +02:00
|
|
|
string ([^\\\"]|\\.)*
|
|
|
|
identifier [^\{\}\(\)\[\]\r\n\,:; \t]
|
|
|
|
alphanum [a-zA-Z0-9_]+
|
|
|
|
varname [a-zA-Z0-9_\"]+
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
%%
|
|
|
|
|
|
|
|
"/*" { BEGIN( C_COMMENT ); }
|
|
|
|
<C_COMMENT>"*/" { BEGIN( INITIAL ); }
|
|
|
|
<C_COMMENT>\n { ; }
|
|
|
|
<C_COMMENT>. { ; }
|
|
|
|
"*/" { Compiler.CompileError( parsedata.pos - yyleng, "'*/' found outside of comment" ); }
|
|
|
|
|
2017-07-07 19:19:46 +02:00
|
|
|
\\[\r\n]+ { ; }
|
2016-03-27 11:49:47 +02:00
|
|
|
"//"[^\r\n]* { if( prev_yylex != TOKEN_EOL ) YYLEX( TOKEN_EOL ); }
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
<VARIABLES>"size" { BEGIN(INITIAL); YYLEX(TOKEN_SIZE); }
|
|
|
|
<VARIABLES>"." { YYLEX(TOKEN_PERIOD); }
|
|
|
|
<VARIABLES>\"{string}\" { BEGIN(INITIAL); TextEscapeValue(yytext + 1, strlen( yytext ) - 2 ); YYLEX(TOKEN_STRING); }
|
|
|
|
<VARIABLES>{varname} {
|
|
|
|
TextValue(yytext, strlen(yytext));
|
|
|
|
YYLEX(TOKEN_IDENTIFIER);
|
|
|
|
}
|
|
|
|
<VARIABLES>[ \t\r\n] {
|
|
|
|
BEGIN(INITIAL);
|
|
|
|
unput(yytext[yyleng - 1]);
|
|
|
|
yyreducepos(1);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
<VARIABLES>. {
|
2023-08-12 19:59:40 +02:00
|
|
|
BEGIN(INITIAL);
|
|
|
|
unput(yytext[yyleng - 1]);
|
|
|
|
yyreducepos(1);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
\"{string}\" { TextEscapeValue( yytext + 1, strlen( yytext ) - 2 ); YYLEX( TOKEN_STRING ); }
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
"?" { YYLEX( TOKEN_TERNARY ); }
|
|
|
|
"if" { YYLEX( TOKEN_IF ); }
|
|
|
|
"else" { YYLEX( TOKEN_ELSE ); }
|
|
|
|
"while" { YYLEX( TOKEN_WHILE ); }
|
|
|
|
"for" { YYLEX( TOKEN_FOR ); }
|
|
|
|
"do" { YYLEX( TOKEN_DO ); }
|
|
|
|
|
|
|
|
"game"? { BEGIN( VARIABLES ); yylval.s.val = node1_( method_game ); YYLEX( TOKEN_LISTENER ); }
|
|
|
|
"group" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_group ); YYLEX( TOKEN_LISTENER ); }
|
|
|
|
"level" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_level ); YYLEX( TOKEN_LISTENER ); }
|
|
|
|
"local" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_local ); YYLEX( TOKEN_LISTENER ); }
|
|
|
|
"parm" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_parm ); YYLEX( TOKEN_LISTENER ); }
|
|
|
|
"owner" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_owner ); YYLEX( TOKEN_LISTENER ); }
|
|
|
|
"self" { BEGIN( VARIABLES ); yylval.s.val = node1_( method_self ); YYLEX( TOKEN_LISTENER ); }
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
"{" { parsedata.braces_count++; YYLEX( TOKEN_LEFT_BRACES ); }
|
|
|
|
"}" { parsedata.braces_count--; YYLEX( TOKEN_RIGHT_BRACES ); }
|
|
|
|
"(" { YYLEX(TOKEN_LEFT_BRACKET); }
|
|
|
|
")" { BEGIN(VARIABLES); YYLEX(TOKEN_RIGHT_BRACKET); }
|
|
|
|
"[" { YYLEX(TOKEN_LEFT_SQUARE_BRACKET); }
|
|
|
|
"]" { BEGIN(VARIABLES); YYLEX(TOKEN_RIGHT_SQUARE_BRACKET); }
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
"=" { YYLEX( TOKEN_ASSIGNMENT ); }
|
|
|
|
":" { YYLEX( TOKEN_COLON ); }
|
|
|
|
"::" { YYLEX( TOKEN_DOUBLE_COLON ); }
|
|
|
|
";" { YYLEX( TOKEN_SEMICOLON ); }
|
|
|
|
|
|
|
|
"==" { YYLEX( TOKEN_EQUALITY ); }
|
|
|
|
"||" { YYLEX( TOKEN_LOGICAL_OR ); }
|
|
|
|
"&&" { YYLEX( TOKEN_LOGICAL_AND ); }
|
|
|
|
|
|
|
|
"|" { YYLEX( TOKEN_BITWISE_OR ); }
|
|
|
|
"^" { YYLEX( TOKEN_BITWISE_EXCL_OR ); }
|
|
|
|
"&" { YYLEX( TOKEN_BITWISE_AND ); }
|
|
|
|
"!=" { YYLEX( TOKEN_INEQUALITY ); }
|
|
|
|
"<" { YYLEX( TOKEN_LESS_THAN ); }
|
|
|
|
">" { YYLEX( TOKEN_GREATER_THAN ); }
|
|
|
|
"<=" { YYLEX( TOKEN_LESS_THAN_OR_EQUAL ); }
|
|
|
|
">=" { YYLEX( TOKEN_GREATER_THAN_OR_EQUAL ); }
|
|
|
|
[ ]"-" { YYLEX( TOKEN_NEG ); }
|
|
|
|
|
|
|
|
"+" { YYLEX( TOKEN_PLUS ); }
|
|
|
|
"+=" { YYLEX( TOKEN_PLUS_EQUALS ); }
|
|
|
|
"++"|[ ]"++" { YYLEX( TOKEN_INCREMENT ); }
|
|
|
|
"-"|"-"[ ]|[ ]"-"[ ] { YYLEX( TOKEN_MINUS ); }
|
|
|
|
"-=" { YYLEX( TOKEN_MINUS_EQUALS ); }
|
|
|
|
[ ]"-=" { YYLEX( TOKEN_MINUS_EQUALS ); }
|
|
|
|
"--"|[ ]"--" { YYLEX( TOKEN_DECREMENT ); }
|
|
|
|
"*" { YYLEX( TOKEN_MULTIPLY ); }
|
|
|
|
"*=" { YYLEX( TOKEN_MULTIPLY_EQUALS ); }
|
|
|
|
"/" { YYLEX( TOKEN_DIVIDE ); }
|
|
|
|
"/=" { YYLEX( TOKEN_DIVIDE_EQUALS ); }
|
|
|
|
"%" { YYLEX( TOKEN_MODULUS ); }
|
|
|
|
"%=" { YYLEX( TOKEN_MODULUS_EQUALS ); }
|
|
|
|
"<<" { YYLEX( TOKEN_SHIFT_LEFT ); }
|
|
|
|
"<<=" { YYLEX( TOKEN_SHIFT_LEFT_EQUALS ); }
|
|
|
|
">>" { YYLEX( TOKEN_SHIFT_RIGHT ); }
|
|
|
|
">>=" { YYLEX( TOKEN_SHIFT_RIGHT_EQUALS ); }
|
|
|
|
"&=" { YYLEX( TOKEN_AND_EQUALS ); }
|
|
|
|
"^=" { YYLEX( TOKEN_EXCL_OR_EQUALS ); }
|
|
|
|
"|=" { YYLEX( TOKEN_OR_EQUALS ); }
|
|
|
|
"$" { BEGIN( VARIABLES ); YYLEX( TOKEN_DOLLAR ); }
|
|
|
|
"!" { YYLEX( TOKEN_NOT ); }
|
|
|
|
"~" { YYLEX( TOKEN_COMPLEMENT ); }
|
|
|
|
|
|
|
|
"." { YYLEX( TOKEN_PERIOD ); }
|
|
|
|
|
|
|
|
"," { YYLEX( TOKEN_COMMA ); }
|
|
|
|
"#" { YYLEX( TOKEN_NUMBER ); }
|
|
|
|
|
|
|
|
"NULL" { YYLEX( TOKEN_NULL ); }
|
|
|
|
"NIL" { YYLEX( TOKEN_NIL ); }
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
"try" { YYLEX( TOKEN_TRY ); }
|
|
|
|
"catch" { YYLEX( TOKEN_CATCH ); }
|
|
|
|
"switch" { YYLEX( TOKEN_SWITCH ); }
|
|
|
|
|
|
|
|
"case" { YYLEX( TOKEN_CASE ); }
|
|
|
|
"break" { YYLEX( TOKEN_BREAK ); }
|
|
|
|
"continue" { YYLEX( TOKEN_CONTINUE ); }
|
|
|
|
|
|
|
|
"makearray"|"makeArray" { YYLEX( TOKEN_MAKEARRAY ); }
|
|
|
|
"endarray"|"endArray" { YYLEX( TOKEN_ENDARRAY ); }
|
|
|
|
|
|
|
|
[\r\n]* { if (prev_yylex != TOKEN_EOL) YYLEX(TOKEN_EOL); }
|
|
|
|
[ \t] { ; }
|
|
|
|
|
2023-06-17 17:00:17 +02:00
|
|
|
[0-9]+ {
|
|
|
|
char* p = nullptr;
|
2023-08-12 19:59:40 +02:00
|
|
|
yylval.s.val.intValue = std::strtol(yytext, &p, 10);
|
2023-06-17 17:00:17 +02:00
|
|
|
YYLEX(TOKEN_INTEGER);
|
|
|
|
}
|
|
|
|
[0-9\.]+|[0-9\.]+("e+"|"e-")+[0-9\.] {
|
|
|
|
char* p = nullptr;
|
|
|
|
yylval.s.val.floatValue = std::strtof(yytext, &p);
|
|
|
|
YYLEX(TOKEN_FLOAT);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
<IDENTIFIER>{identifier}* {
|
|
|
|
BEGIN(INITIAL);
|
|
|
|
TextEscapeValue(yytext, yyleng);
|
|
|
|
YYLEX(TOKEN_IDENTIFIER);
|
|
|
|
}
|
|
|
|
<IDENTIFIER>[ \t\r\n] {
|
|
|
|
BEGIN(INITIAL);
|
|
|
|
unput(yytext[yyleng - 1]);
|
|
|
|
yyreducepos(1);
|
|
|
|
TextEscapeValue(yytext, yyleng - 1);
|
|
|
|
YYLEXOFF(TOKEN_IDENTIFIER, 1);
|
|
|
|
}
|
|
|
|
<IDENTIFIER>. {
|
|
|
|
BEGIN(INITIAL);
|
|
|
|
unput(yytext[yyleng - 1]);
|
|
|
|
yyreducepos(1);
|
|
|
|
TextEscapeValue(yytext, yyleng - 1);
|
|
|
|
YYLEXOFF(TOKEN_IDENTIFIER, 1);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
{identifier} {
|
|
|
|
BEGIN(IDENTIFIER);
|
|
|
|
yymore();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
[a-zA-Z0-9]+ {
|
|
|
|
BEGIN(IDENTIFIER);
|
|
|
|
yymore();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-08-12 19:59:40 +02:00
|
|
|
<<EOF>> { YYLEX(TOKEN_EOF); }
|
|
|
|
|
|
|
|
. { YY_FATAL_ERROR("bad token:\n"); }
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
%{
|
|
|
|
|
|
|
|
#undef fprintf
|
|
|
|
|
|
|
|
%}
|
|
|
|
|
|
|
|
%%
|