%{ /* * =========================================================================== * 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. */ #include "scriptcompiler.h" #include "./yyParser.hpp" #include 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 ); } "*/" { BEGIN( INITIAL ); } \n { ; } . { ; } "*/" { Compiler.CompileError( parsedata.pos - yyleng, "'*/' found outside of comment" ); } \\[\r\n]+ { ; } "//"[^\r\n]* { if( prev_yylex != TOKEN_EOL ) YYLEX( TOKEN_EOL ); } "size" { BEGIN(INITIAL); YYLEX(TOKEN_SIZE); } [ \t]*\./([0-9]*[^0-9[:space:]]) { YYLEX(TOKEN_PERIOD); } \"{string}\" { BEGIN(INITIAL); TextEscapeValue(yytext + 1, strlen( yytext ) - 2 ); YYLEX(TOKEN_STRING); } {varname} { TextValue(yytext, strlen(yytext)); YYLEX(TOKEN_IDENTIFIER); } [ \t\r\n] { BEGIN(INITIAL); unput(yytext[yyleng - 1]); yyreducepos(1); } . { 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 ); } "||" { 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 ); } [ \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}* { BEGIN(INITIAL); TextEscapeValue(yytext, yyleng); YYLEX(TOKEN_IDENTIFIER); } [ \t\r\n] { BEGIN(INITIAL); unput(yytext[yyleng - 1]); yyreducepos(1); TextEscapeValue(yytext, yyleng - 1); YYLEXOFF(TOKEN_IDENTIFIER, 1); } . { 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(); }