openmohaa/code/parser/lex_source.txt

413 lines
15 KiB
Text
Raw Permalink Normal View History

2016-03-27 11:49:47 +02:00
%{
/*
* ===========================================================================
2025-04-26 19:22:34 +02:00
* Copyright (C) 2025 the OpenMoHAA team
2016-03-27 11:49:47 +02:00
*
* 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"
2016-03-27 11:49:47 +02:00
#include <stdio.h>
2025-02-14 23:54:15 +01:00
void fprintf2(FILE * f, const char *format, ...)
2016-03-27 11:49:47 +02:00
{
2025-02-14 23:54:15 +01:00
va_list va;
static char buffer[4200];
2016-03-27 11:49:47 +02:00
2025-02-14 23:54:15 +01:00
va_start(va, format);
vsprintf(buffer, format, va);
va_end(va);
2016-03-27 11:49:47 +02:00
2025-02-14 23:54:15 +01:00
gi.Printf(buffer);
2016-03-27 11:49:47 +02:00
}
#define fprintf fprintf2
2025-02-14 23:54:15 +01:00
const char *start_ptr;
const char *in_ptr;
extern int prev_yylex;
extern int out_pos;
extern int success_pos;
2023-08-12 19:59:40 +02:00
parseStage_e parseStage;
2016-03-27 11:49:47 +02:00
extern yyparsedata parsedata;
2025-02-14 23:54:15 +01:00
void yyllocset(YYLTYPE * loc, uint32_t off)
2023-08-12 19:59:40 +02:00
{
2025-02-14 23:54:15 +01:00
success_pos = out_pos - yyleng + off;
loc->sourcePos = success_pos;
parsedata.pos = success_pos;
2023-08-12 19:59:40 +02:00
}
void yyreducepos(uint32_t off)
{
2025-02-14 23:54:15 +01:00
out_pos -= off;
2023-08-12 19:59:40 +02:00
}
2025-02-14 23:54:15 +01:00
#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)
2016-03-27 11:49:47 +02:00
{
2025-02-14 23:54:15 +01:00
gi.DPrintf("%s\n%s", msg, yytext);
assert(0);
2016-03-27 11:49:47 +02:00
}
2025-02-14 23:54:15 +01:00
static void TextEscapeValue(char *str, size_t len)
2016-03-27 11:49:47 +02:00
{
2025-02-14 23:54:15 +01:00
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;
2016-03-27 11:49:47 +02:00
}
2025-02-14 23:54:15 +01:00
static void TextValue(char *str, size_t len)
2016-03-27 11:49:47 +02:00
{
2025-02-14 23:54:15 +01: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
}
2025-02-14 23:54:15 +01:00
static bool UseField(void)
2016-03-27 11:49:47 +02:00
{
2025-02-14 23:54:15 +01:00
return prev_yylex == TOKEN_PERIOD || prev_yylex == TOKEN_DOLLAR;
2016-03-27 11:49:47 +02:00
}
2025-04-26 19:22:34 +02:00
#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; \
}
2023-08-13 03:33:50 +02:00
2016-03-27 11:49:47 +02:00
%}
/*%option debug*/
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-13 03:33:50 +02:00
%x SCRIPT
2016-03-27 11:49:47 +02:00
%x C_COMMENT
%x C_LINE_COMMENT
%x VARIABLES
%x IDENTIFIER
2025-04-26 19:22:34 +02:00
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_\"$\\]+
2023-06-17 17:00:17 +02:00
2016-03-27 11:49:47 +02:00
%%
2025-04-26 19:22:34 +02:00
"/*" { 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"); }
2016-03-27 11:49:47 +02:00
%{
#undef fprintf
%}
%%
2023-08-13 03:33:50 +02:00
//
// Implements yywrap to always append a newline to the source
//
2025-04-26 19:22:34 +02:00
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;
2023-08-13 03:33:50 +02:00
}
2025-04-26 19:22:34 +02:00
void yy_init_script()
{
BEGIN(SCRIPT);
2023-08-13 03:33:50 +02:00
}