mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00
412 lines
15 KiB
Text
412 lines
15 KiB
Text
%{
|
|
/*
|
|
* ===========================================================================
|
|
* Copyright (C) 2025 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.
|
|
*/
|
|
|
|
#include "scriptcompiler.h"
|
|
#include "./yyParser.hpp"
|
|
|
|
#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);
|
|
|
|
gi.Printf(buffer);
|
|
}
|
|
|
|
#define fprintf fprintf2
|
|
|
|
const char *start_ptr;
|
|
const char *in_ptr;
|
|
extern int prev_yylex;
|
|
extern int out_pos;
|
|
extern int success_pos;
|
|
parseStage_e parseStage;
|
|
|
|
extern yyparsedata parsedata;
|
|
|
|
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; \
|
|
}
|
|
|
|
#define YY_FATAL_ERROR(n) yylexerror(n)
|
|
|
|
void yylexerror(const char *msg)
|
|
{
|
|
gi.DPrintf("%s\n%s", msg, yytext);
|
|
assert(0);
|
|
}
|
|
|
|
static void TextEscapeValue(char *str, size_t len)
|
|
{
|
|
char *to = parsetree_malloc(len + 1);
|
|
|
|
yylval.s.val.stringValue = to;
|
|
|
|
while (len) {
|
|
if (*str == '\\') {
|
|
if (len == 1) {
|
|
break;
|
|
}
|
|
|
|
if (str[1] == 'n') {
|
|
*to = '\n';
|
|
to++;
|
|
} else if (str[1] == 't') {
|
|
*to = '\t';
|
|
to++;
|
|
} else if (str[1] == '"') {
|
|
*to = '\"';
|
|
to++;
|
|
} else {
|
|
*to = str[1];
|
|
to++;
|
|
}
|
|
|
|
len -= 2;
|
|
str += 2;
|
|
} else {
|
|
*to = *str;
|
|
to++;
|
|
len--;
|
|
str++;
|
|
}
|
|
}
|
|
|
|
*to = 0;
|
|
}
|
|
|
|
static void TextValue(char *str, size_t len)
|
|
{
|
|
char *s = parsetree_malloc(len + 1);
|
|
strncpy(s, str, len);
|
|
s[len] = 0;
|
|
yylval.s.val.stringValue = s;
|
|
}
|
|
|
|
static bool UseField(void)
|
|
{
|
|
return prev_yylex == TOKEN_PERIOD || prev_yylex == TOKEN_DOLLAR;
|
|
}
|
|
|
|
#define YY_INPUT(buf, result, max_size) \
|
|
{ \
|
|
char c; \
|
|
int n; \
|
|
\
|
|
c = '*'; \
|
|
for (n = 0; n < max_size; n++) { \
|
|
c = *in_ptr++; \
|
|
if (!c || c == '\n') { \
|
|
break; \
|
|
} \
|
|
\
|
|
buf[n] = c; \
|
|
} \
|
|
\
|
|
if (c == '\n') { \
|
|
buf[n++] = c; \
|
|
} else if (!c) { \
|
|
in_ptr--; \
|
|
} \
|
|
\
|
|
result = n; \
|
|
}
|
|
|
|
%}
|
|
|
|
/*%option debug*/
|
|
|
|
%option warn nodefault
|
|
|
|
%option never-interactive
|
|
%option yylineno
|
|
|
|
%x SCRIPT
|
|
%x C_COMMENT
|
|
%x C_LINE_COMMENT
|
|
%x VARIABLES
|
|
%x IDENTIFIER
|
|
|
|
string ([^\\\"\r\n]|\\.)*
|
|
identifier [^\{\}\(\)\[\]\r\n\,:; \t]
|
|
nonexpr [0-9a-zA-Z_\"'?@#`\.\x80-\xff]
|
|
nonnumeric [a-zA-Z_\"'?@#`\x80-\xff]
|
|
alphanum [a-zA-Z0-9_]+
|
|
varname [a-zA-Z0-9_\"$\\]+
|
|
|
|
%%
|
|
|
|
"/*" { BEGIN(C_COMMENT); }
|
|
<C_COMMENT>"*/" { BEGIN(INITIAL); }
|
|
<C_COMMENT>\n { ; }
|
|
<C_COMMENT>. { ; }
|
|
"*/" { Compiler.CompileError( parsedata.pos - yyleng, "'*/' found outside of comment" ); }
|
|
|
|
\\[\r\n]+ { ; }
|
|
"//"[^\r\n]* { if(prev_yylex != TOKEN_EOL) YYLEX(TOKEN_EOL); }
|
|
|
|
<VARIABLES>"size" { BEGIN(INITIAL); YYLEX(TOKEN_SIZE); }
|
|
<VARIABLES>[ \t]*\./([0-9]*[^0-9[:space:]]) { YYLEX(TOKEN_PERIOD); }
|
|
<VARIABLES>\"{string}\" { BEGIN(INITIAL); TextEscapeValue(yytext + 1, strlen( yytext ) - 2 ); YYLEX(TOKEN_STRING); }
|
|
<VARIABLES>{varname} {
|
|
TextEscapeValue(yytext, strlen(yytext));
|
|
YYLEX(TOKEN_IDENTIFIER);
|
|
}
|
|
<VARIABLES>[ \t\r\n] {
|
|
BEGIN(INITIAL);
|
|
unput(yytext[yyleng - 1]);
|
|
yyreducepos(1);
|
|
}
|
|
<VARIABLES>. {
|
|
BEGIN(INITIAL);
|
|
unput(yytext[yyleng - 1]);
|
|
yyreducepos(1);
|
|
}
|
|
|
|
\"{string}\"{nonexpr} {
|
|
BEGIN(IDENTIFIER);
|
|
yymore();
|
|
}
|
|
|
|
\"{string}\" { TextEscapeValue(yytext + 1, yyleng - 2); YYLEX(TOKEN_STRING); }
|
|
|
|
"?" { 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); }
|
|
|
|
"{" { 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); }
|
|
|
|
"=" { YYLEX(TOKEN_ASSIGNMENT); }
|
|
":" { YYLEX(TOKEN_COLON); }
|
|
"::" { YYLEX(TOKEN_DOUBLE_COLON); }
|
|
";" { YYLEX(TOKEN_SEMICOLON); }
|
|
|
|
"==" { YYLEX(TOKEN_EQUALITY); }
|
|
"ifequal" { YYLEX(TOKEN_EQUALITY); }
|
|
"ifstrequal" { 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); }
|
|
"ifnotequal" { YYLEX(TOKEN_INEQUALITY); }
|
|
"ifstrnotequal" { YYLEX(TOKEN_INEQUALITY); }
|
|
"<" { YYLEX(TOKEN_LESS_THAN); }
|
|
"ifless" { YYLEX(TOKEN_LESS_THAN); }
|
|
">" { YYLEX(TOKEN_GREATER_THAN); }
|
|
"ifgreater" { YYLEX(TOKEN_GREATER_THAN); }
|
|
"<=" { YYLEX(TOKEN_LESS_THAN_OR_EQUAL); }
|
|
"iflessequal" { YYLEX(TOKEN_LESS_THAN_OR_EQUAL); }
|
|
">=" { YYLEX(TOKEN_GREATER_THAN_OR_EQUAL); }
|
|
"ifgreaterequal" { YYLEX(TOKEN_GREATER_THAN_OR_EQUAL); }
|
|
[ \t]"-" { YYLEX(TOKEN_NEG); }
|
|
|
|
"+" { YYLEX(TOKEN_PLUS); }
|
|
"+=" { YYLEX(TOKEN_PLUS_EQUALS); }
|
|
"++"|[ \t]"++" { YYLEX(TOKEN_INCREMENT); }
|
|
"-"|"-"[ \t]|[ \t]"-"[ \t] { YYLEX(TOKEN_MINUS); }
|
|
"-=" { YYLEX(TOKEN_MINUS_EQUALS); }
|
|
[ \t]"-=" { YYLEX(TOKEN_MINUS_EQUALS); }
|
|
"--"|[ \t]"--" { 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); }
|
|
|
|
"NULL" { YYLEX(TOKEN_NULL); }
|
|
"NIL" { YYLEX(TOKEN_NIL); }
|
|
|
|
"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] { ; }
|
|
|
|
[0-9]+ {
|
|
char* p = nullptr;
|
|
yylval.s.val.intValue = std::strtol(yytext, &p, 10);
|
|
YYLEX(TOKEN_INTEGER);
|
|
}
|
|
|
|
[0-9\.]+{nonnumeric} {
|
|
BEGIN(IDENTIFIER);
|
|
yymore();
|
|
}
|
|
|
|
[0-9\.]+|[0-9\.]+("e+"|"e-")+[0-9\.] {
|
|
char* p = nullptr;
|
|
yylval.s.val.floatValue = std::strtof(yytext, &p);
|
|
YYLEX(TOKEN_FLOAT);
|
|
}
|
|
|
|
<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);
|
|
}
|
|
|
|
{identifier} {
|
|
BEGIN(IDENTIFIER);
|
|
yymore();
|
|
}
|
|
|
|
[a-zA-Z0-9_]+ {
|
|
BEGIN(IDENTIFIER);
|
|
yymore();
|
|
}
|
|
|
|
<SCRIPT>[a-zA-Z0-9]+ { BEGIN(INITIAL); }
|
|
|
|
. { YY_FATAL_ERROR("bad token:\n"); }
|
|
|
|
%{
|
|
|
|
#undef fprintf
|
|
|
|
%}
|
|
|
|
%%
|
|
|
|
//
|
|
// Implements yywrap to always append a newline to the source
|
|
//
|
|
int yywrap(void)
|
|
{
|
|
if (parseStage == PS_TYPE) {
|
|
parseStage = PS_BODY;
|
|
in_ptr = start_ptr;
|
|
out_pos = 0;
|
|
success_pos = 0;
|
|
return 0;
|
|
}
|
|
|
|
if (parseStage == PS_BODY) {
|
|
if (YY_START == C_COMMENT) {
|
|
Compiler.CompileError(success_pos, "unexpected end of file found in comment");
|
|
return 1;
|
|
}
|
|
|
|
parseStage = PS_BODY_END;
|
|
in_ptr = "\n";
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void yy_init_script()
|
|
{
|
|
BEGIN(SCRIPT);
|
|
}
|