30 #include "../clib/clib.h" 31 #include "../clib/filecont.h" 32 #include "../clib/fileutil.h" 33 #include "../clib/logfacility.h" 34 #include "../clib/passert.h" 35 #include "../clib/stlutil.h" 36 #include "../clib/strutil.h" 37 #include "../plib/pkg.h" 48 #include <format/format.h> 61 std::string::size_type pos = fname.find_last_of(
"\\/" );
62 if ( pos == std::string::npos )
65 return fname.substr( 0, pos + 1 );
71 for (
int i = static_cast<int>(
variables_.size() - 1 ); i >= 0; --i )
78 <<
"' declared as unused but used.\n";
80 throw std::runtime_error(
"Warnings treated as errors." );
92 for (
int i = static_cast<int>(
variables_.size() - 1 ); i >= 0; --i )
117 INFO_PRINT <<
"Warning: local variable '" << bk.
name <<
"' not used.\n";
119 throw std::runtime_error(
"Warnings treated as errors." );
137 throw std::runtime_error(
"Variable " + varname +
" is already in scope." );
141 newvar.
name = varname;
143 newvar.
used = !warn_on_notused;
156 while ( !tokens.empty() )
158 Token* tkn = tokens.back();
164 while ( !TX.empty() )
166 Token* tkn = TX.top();
172 while ( !CA.empty() )
174 Token* tkn = CA.front();
182 while ( !expr.
CA.empty() )
184 CA.push( expr.
CA.front() );
191 while ( !expr.
tokens.empty() )
193 CA.push( expr.
tokens.front() );
213 if ( right->
lval == 0 )
214 throw std::runtime_error(
"Program would divide by zero" );
219 lval = ( left->
lval == right->
lval );
222 lval = ( left->
lval != right->
lval );
225 lval = ( left->
lval < right->
lval );
228 lval = ( left->
lval <= right->
lval );
231 lval = ( left->
lval > right->
lval );
234 lval = ( left->
lval >= right->
lval );
238 lval = ( left->
lval && right->
lval );
241 lval = ( left->
lval || right->
lval );
245 lval = ( left->
lval >> right->
lval );
248 lval = ( left->
lval << right->
lval );
251 lval = ( left->
lval & right->
lval );
254 lval = ( left->
lval | right->
lval );
257 lval = ( left->
lval ^ right->
lval );
266 auto ntoken =
new Token( *left );
287 if ( right->
dval == 0.0 )
288 throw std::runtime_error(
"Program would divide by zero" );
296 auto ntoken =
new Token( *left );
304 Token* ntoken = NULL;
309 ntoken =
new Token( *left );
310 std::string combined;
311 combined = std::string( left->
tokval() ) + std::string( right->
tokval() );
312 ntoken->
copyStr( combined.c_str() );
324 Token* ntoken = NULL;
328 ntoken =
new Token( *value );
332 ntoken =
new Token( *value );
336 ntoken =
new Token( *value );
347 Token* ntoken = NULL;
351 ntoken =
new Token( *value );
367 for (
unsigned i = 0; i < tokens.size(); i++ )
369 Token* oper = tokens[i];
375 throw std::runtime_error(
"Unbalanced binary operator: " +
Clib::tostring( *oper ) );
377 Token* left = tokens[i - 2];
378 Token* right = tokens[i - 1];
379 if ( left->
id != right->
id )
389 Token* ntoken = NULL;
411 tokens[i - 2] = ntoken;
412 tokens.erase( tokens.begin() + ( i - 1 ), tokens.begin() + ( i + 1 ) );
419 for (
unsigned i = 0; i < tokens.size(); i++ )
421 Token* oper = tokens[i];
427 throw std::runtime_error(
"Unbalanced unary operator: " +
Clib::tostring( *oper ) );
429 Token* value = tokens[i - 1];
435 tokens.erase( tokens.begin() + i, tokens.begin() + i + 1 );
442 Token* ntoken = NULL;
461 tokens[i - 1] = ntoken;
462 tokens.erase( tokens.begin() + i, tokens.begin() + ( i + 1 ) );
469 Token* tkn = tokens[idx];
492 children = 1 + tkn->
lval;
496 children = 1 + tkn->
lval;
512 children = 1 + tkn->
lval;
534 for (
int i = 0; i < children; ++i )
536 count += get_num_tokens( idx - count );
543 Token* oper = tokens[i];
546 int right_idx = i - 1;
547 int left_idx = right_idx - get_num_tokens( i - 1 );
548 if ( right_idx < 0 || left_idx < 0 )
550 throw std::runtime_error(
"Unbalanced operator: " +
Clib::tostring( *oper ) );
553 Token* left = tokens[left_idx];
560 tokens.erase( tokens.begin() + left_idx, tokens.begin() + ( left_idx + 1 ) );
569 tokens.erase( tokens.begin() + left_idx, tokens.begin() + ( left_idx + 1 ) );
578 tokens.erase( tokens.begin() + left_idx, tokens.begin() + ( left_idx + 1 ) );
591 tokens.erase( tokens.begin() + left_idx, tokens.begin() + ( left_idx + 1 ) );
597 int right_idx = i - 1;
598 int left_idx = right_idx - get_num_tokens( i - 1 );
600 Token* left = tokens[left_idx];
613 tokens.erase( tokens.begin() + left_idx, tokens.begin() + left_idx + 1 );
619 Token* operand = tokens[i - 1];
651 Token* operand = tokens[i - 1];
660 oper->
lval = (int)objmemb->
id;
663 tokens.erase( tokens.begin() + i - 1, tokens.begin() + i );
672 operand = tokens[tokens.size() - 2];
674 operand = tokens[tokens.size() - 1];
697 tokens.erase( tokens.begin() + i - 1, tokens.begin() + i );
698 tokens.insert( tokens.end(), oper );
714 tokens.erase( tokens.begin() + i - 1, tokens.begin() + i );
720 throw std::runtime_error(
"Expected an identifier to follow the member (.) operator." );
728 for (
unsigned i = 1; i < tokens.size(); i++ )
730 if ( optimize_token( i ) )
766 size_t starting_size;
769 starting_size = tokens.size();
770 optimize_binary_operations();
771 optimize_unary_operations();
772 optimize_assignments();
774 }
while ( tokens.size() != starting_size );
779 program->enterblock();
789 bd.
label = latest_label;
806 const BlockDesc& bd = localscope.blockdesc();
809 patchoffset( patchip, breakPC );
815 const BlockDesc& bd = localscope.blockdesc();
818 patchoffset( patchip, continuePC );
824 if ( localscope.numVarsInBlock() )
834 patchblock_breaks( breakPC );
835 patchblock_continues( continuePC );
837 localscope.popblock();
838 program->leaveblock();
843 current_file_path(
"" ),
847 haveProgram( false ),
848 compiling_include( false ),
852 program_source( NULL ),
854 referencedPathnames(),
874 for (
unsigned i = 0; i < static_cast<unsigned>(
globals_.size() ); ++i )
905 INFO_PRINT <<
"Warning! possible incorrect assignment.\n" 906 <<
"Near: " <<
curLine <<
"\n";
908 throw std::runtime_error(
"Warnings treated as errors." );
917 Candidate(
int module,
int funcidx ) : module( module ), funcidx( funcidx ), modfunc( nullptr ) {}
925 typedef std::vector<Candidate> Candidates;
926 Candidates candidates;
927 std::string modulename;
928 std::string funcname;
930 if (
const char* colon = strchr( token.
tokval(),
':' ) )
932 std::string tmp( token.
tokval(), colon );
933 if ( tmp.length() >= 9 )
935 INFO_PRINT <<
"'" << tmp <<
"' is too long to be a module name.\n";
939 funcname = std::string( colon + 2 );
944 funcname = token.
tokval();
947 for (
unsigned i = 0; i <
program->modules.size(); i++ )
949 if ( !modulename.empty() &&
950 !( modulename ==
program->modules[i]->modulename ) )
956 if (
program->modules[i]->isFunc( funcname.c_str(), pmf, &funcidx ) )
958 candidates.push_back(
Candidate( i, funcidx ) );
962 if ( candidates.empty() )
966 else if ( candidates.size() == 1 )
969 static_cast<unsigned char>( candidates[0].module );
972 token.
lval = candidates[0].funcidx;
979 <<
"' exists in more than module. It must be qualified.\n";
980 for ( Candidates::const_iterator itr = candidates.begin(); itr != candidates.end(); ++itr )
992 program->modules.push_back( module );
1008 *f = &( *itr ).second;
1049 <<
"Expected expression following comma before right-brace in array initializer list\n";
1054 INFO_PRINT <<
"Unexpected comma in array initializer list\n";
1080 INFO_PRINT <<
"Token '" << token <<
"' unexpected in array initializer list\n";
1115 <<
"Expected expression following comma before right-brace in array initializer list\n";
1121 INFO_PRINT <<
"Unexpected comma in array initializer list\n";
1147 INFO_PRINT <<
"Token '" << token <<
"' unexpected in array initializer list\n";
1186 <<
"Expected expression following comma before right-brace in struct initializer list\n";
1191 INFO_PRINT <<
"Unexpected comma in struct element list\n";
1211 auto addmem =
new Token( ident_tkn );
1215 expr.
CA.push( addmem );
1219 INFO_PRINT <<
"Unexpected token: '" << token <<
"'. Did you mean := for assign?\n";
1224 auto addmem =
new Token( ident_tkn );
1226 expr.
CA.push( addmem );
1231 INFO_PRINT <<
"Unexpected token in struct initializer list: " << token <<
"\n";
1249 INFO_PRINT <<
"Token '" << token <<
"' unexpected in struct initializer list\n";
1288 INFO_PRINT <<
"Expected expression following comma before right-brace in dictionary " 1289 "initializer list\n";
1294 INFO_PRINT <<
"Unexpected comma in dictionary element list\n";
1302 res =
readexpr( key_expression, ctx,
1308 expr.
eat2( key_expression );
1320 res =
readexpr( value_expression, ctx,
1325 expr.
eat2( value_expression );
1348 INFO_PRINT <<
"Token '" << token <<
"' unexpected in struct element list\n";
1375 INFO_PRINT <<
"Unexpected comma in array element list\n";
1400 INFO_PRINT <<
"Token '" << token <<
"' unexpected in array element list\n";
1414 INFO_PRINT <<
"Expected user function reference.\n";
1451 typedef std::map<std::string, Expression> ParamList;
1452 ParamList params_passed;
1461 INFO_PRINT <<
"Expected '(' after function name '" << userfunc->
name <<
"'\n";
1469 std::string varname;
1479 if ( params_passed.empty() )
1485 INFO_PRINT <<
"right paren not allowed here\n";
1490 if ( params_passed.size() >= userfunc->
parameters.size() )
1492 INFO_PRINT <<
"Too many parameters passed to " << userfunc->
name <<
"\n";
1510 INFO_PRINT <<
"Unexpected token: '" << tk2 <<
"'. Did you mean := for assign?\n";
1514 if ( varname ==
"" )
1518 INFO_PRINT <<
"unnamed args cannot follow named args\n";
1521 varname = userfunc->
parameters[params_passed.size()].name;
1524 if ( params_passed.find( varname ) != params_passed.end() )
1526 INFO_PRINT <<
"Variable " << varname <<
" passed more than once to " << userfunc->
name 1531 Expression& arg_expr = params_passed[varname];
1551 INFO_PRINT <<
"Token '" << token <<
"' unexpected (expected comma or right-paren)\n";
1556 for ( UserFunction::Parameters::const_iterator itr = userfunc->
parameters.begin();
1559 if ( params_passed.find( itr->name ) == params_passed.end() )
1561 if ( itr->have_default )
1563 ex.
CA.push(
new Token( itr->dflt_value ) );
1567 INFO_PRINT <<
"Function " << userfunc->
name <<
": Parameter " << itr->name
1568 <<
" was not passed, and there is no default.\n";
1574 Expression& arg_expr = params_passed[itr->name];
1576 params_passed.erase( itr->name );
1580 if ( !params_passed.empty() )
1582 for (
const auto& elem : params_passed )
1584 INFO_PRINT <<
"Parameter '" << elem.first <<
"' passed by name to " << userfunc->
name 1585 <<
", which takes no such parameter.\n";
1590 passert( params_passed.empty() );
1604 t->dbg_linenum = ctx.
line;
1608 t->dbg_linenum = ctx.
line;
1622 for (
auto& tkn : expr.
tokens )
1644 for (
unsigned i = 0; i < static_cast<unsigned>( expr.
tokens.size() ); i++ )
1653 <<
" on line " << ctx.
line <<
".\n";
1660 INFO_PRINT <<
"Deprecated '=' found: did you mean '==' or ':='?\n";
1669 <<
" on line " << ctx.
line <<
" of " << ctx.
filename <<
"\n";
1672 throw std::runtime_error(
"Warnings treated as errors." );
1677 int right_idx = i - 1;
1678 if ( right_idx < 0 )
1680 throw std::runtime_error(
"Unbalanced operator: " +
Clib::tostring( *tkn ) );
1686 throw std::runtime_error(
"Unbalanced operator: " +
Clib::tostring( *tkn ) );
1692 int operand_idx = i - 1;
1693 if ( operand_idx < 0 )
1695 throw std::runtime_error(
"Unbalanced operator: " +
Clib::tostring( *tkn ) );
1710 *tkn = ( *srch ).second;
1723 for (
auto& tkn : expr.
tokens )
1734 res =
IIP( expr, ctx, flags );
1737 while ( !expr.
CA.empty() )
1739 Token* token = expr.
CA.front();
1741 expr.
tokens.push_back( token );
1746 expr.
tokens.push_back( tkn );
1759 for ( Expression::Tokens::const_iterator itr = expr.
tokens.begin(); itr != expr.
tokens.end();
1771 res =
readexpr( *pex, ctx, flags );
1772 if ( exprlen != NULL )
1773 *exprlen = pex->
tokens.size();
1780 if ( exprlen != NULL )
1781 *exprlen = ex.
tokens.size();
1793 res =
getExpr( ctx, expr_flags, NULL, pex );
1847 INFO_PRINT <<
"Expected variable, function or parenthesized expression, got '" << token
1864 if ( token.
id != tokenid )
1877 unsigned body_start = prog_tokens->
next();
1888 program->update_dbg_pos( endblock_tkn );
1918 unsigned body_start = prog_tokens->
next();
1931 program->update_dbg_pos( endblock_tkn );
1957 unsigned default_posn = 0;
1958 unsigned casecmp_posn = 0;
1959 std::vector<unsigned> jmpend;
1960 std::vector<unsigned char> caseblock;
1969 bool onlydefault =
true;
1973 bool anycases =
false;
1990 if ( default_posn != 0 )
1992 INFO_PRINT <<
"CASE statement can have only one DEFAULT clause.\n";
1995 default_posn = prog_tokens->
next();
2032 onlydefault =
false;
2035 unsigned short offset =
static_cast<unsigned short>( prog_tokens->
next() );
2036 unsigned char* tmppch =
reinterpret_cast<unsigned char*
>( &offset );
2037 caseblock.push_back( tmppch[0] );
2038 caseblock.push_back( tmppch[1] );
2040 tmppch =
reinterpret_cast<unsigned char*
>( &token.
lval );
2041 caseblock.push_back( tmppch[0] );
2042 caseblock.push_back( tmppch[1] );
2043 caseblock.push_back( tmppch[2] );
2044 caseblock.push_back( tmppch[3] );
2048 if ( strlen( token.
tokval() ) >= 254 )
2050 INFO_PRINT <<
"String expressions in CASE statements must be <= 253 characters.\n";
2054 unsigned short offset =
static_cast<unsigned short>( prog_tokens->
next() );
2055 unsigned char* tmppch =
reinterpret_cast<unsigned char*
>( &offset );
2056 caseblock.push_back( tmppch[0] );
2057 caseblock.push_back( tmppch[1] );
2058 caseblock.push_back( static_cast<unsigned char>( strlen( token.
tokval() ) ) );
2059 const char* str = token.
tokval();
2060 size_t len = strlen( str );
2062 for (
size_t i = 0; i < len; ++i )
2063 caseblock.push_back( str[i] );
2105 if ( stricmp( token.
tokval(),
"default" ) == 0 )
2120 INFO_PRINT <<
"CASE statement with no options!\n" 2121 <<
"Found '" << token.
tokval() <<
"'" 2122 << ( token.
id ==
CTRL_LABEL ?
" but no such constant is defined.\n" 2123 :
" prematurely.\n" );
2141 unsigned jmpend_posn;
2143 jmpend.push_back( jmpend_posn );
2153 INFO_PRINT <<
"Warning: CASE block only has a DEFAULT clause defined.\n" 2154 <<
"near: " <<
curLine <<
"\n";
2156 throw std::runtime_error(
"Warnings treated as errors." );
2162 if ( default_posn == 0 )
2163 default_posn = prog_tokens->
next();
2168 unsigned char* tmppch =
reinterpret_cast<unsigned char*
>( &default_posn );
2169 caseblock.push_back( tmppch[0] );
2170 caseblock.push_back( tmppch[1] );
2174 while ( !jmpend.empty() )
2176 unsigned posn = jmpend.back();
2182 unsigned caseblock_posn;
2183 auto casecmp_raw =
new unsigned char[caseblock.size()];
2184 for (
size_t i = 0; i < caseblock.size(); ++i )
2185 casecmp_raw[i] = caseblock[i];
2186 program->symbols.append( casecmp_raw, static_cast<unsigned int>( caseblock.size() ),
2188 delete[] casecmp_raw;
2205 INFO_PRINT <<
"FOREACH iterator must be an identifier, got " << itrvar <<
"\n";
2229 unsigned initforeach_posn;
2237 program->addlocalvar(
"_" + std::string( itrvar.
tokval() ) +
"_expr" );
2239 program->addlocalvar(
"_" + std::string( itrvar.
tokval() ) +
"_counter" );
2243 unsigned iter_posn =
program->tokens.next();
2245 Token endforeach_token;
2252 unsigned stepforeach_posn;
2253 program->update_dbg_pos( endforeach_token );
2255 &stepforeach_posn );
2256 patchoffset( initforeach_posn, stepforeach_posn );
2281 program->symbols.append(
"", posn );
2361 bool first_time =
true;
2368 INFO_PRINT <<
"'" << funcName.
tokval() <<
"' is already defined as a function.\n" 2369 <<
"Near: " <<
curLine <<
"\n" 2375 INFO_PRINT <<
"Expected an identifier, got " << funcName <<
" instead.\n" 2376 <<
"Near: " <<
curLine <<
"\n" 2403 bool pass_by_reference =
false;
2404 bool unused =
false;
2410 pass_by_reference =
true;
2437 INFO_PRINT <<
"Default arguments are not allowed in unused parameters\n";
2448 INFO_PRINT <<
"Error reading expression in const declaration\n";
2452 if ( ex.
tokens.size() != 1 )
2454 INFO_PRINT <<
"Const expression must be optimizable\n";
2462 <<
"]: Only simple operands are allowed as default arguments (" << token
2463 <<
" is not allowed)\n";
2470 INFO_PRINT <<
"Unexpected token: '" << token <<
"'. Did you mean := for assign?\n";
2510 throw std::runtime_error(
"Tried to declare a non-identifier" );
2557 <<
"nParams: " << nParams <<
"\n";
2565 unsigned jump_false;
2577 unsigned if_token_posn;
2597 unsigned else_token_posn;
2600 jump_false = prog_tokens->
next();
2612 jump_false = prog_tokens->
next();
2624 if ( token.
id == correct )
2635 INFO_PRINT <<
"Expected " << t <<
" before " << token <<
"\n";
2648 std::vector<unsigned> jumpend;
2657 size_t jumpend_size = jumpend.size();
2659 bool discard_rest =
false;
2661 bool included_any_tests =
false;
2662 unsigned last_if_token_posn =
static_cast<unsigned>( -1 );
2663 unsigned if_token_posn =
static_cast<unsigned>( -1 );
2675 bool patch_if_token =
true;
2676 last_if_token_posn = if_token_posn;
2679 if_token_posn = prog_tokens->
count() - 1;
2688 bool discard_this = discard_rest;
2692 if ( ex.
tokens[0]->lval )
2694 discard_rest =
true;
2698 discard_this =
true;
2702 patch_if_token =
false;
2707 if ( !discard_rest )
2708 included_any_tests =
true;
2733 INFO_PRINT <<
"Error in IF statement starting at " << save_ctx;
2743 if ( !discard_this )
2746 jumpend_size = jumpend.size();
2755 program->update_dbg_pos( token );
2757 jumpend.push_back( temp_posn );
2766 if ( patch_if_token )
2769 prog_tokens->
atGet1( if_token_posn, tkn );
2770 tkn.
offset =
static_cast<unsigned short>( prog_tokens->
next() );
2771 prog_tokens->
atPut1( tkn, if_token_posn );
2778 while ( jumpend.size() > jumpend_size )
2781 if ( last_if_token_posn != static_cast<unsigned>( -1 ) &&
2782 last_if_token_posn < prog_tokens->count() )
2785 prog_tokens->
atGet1( last_if_token_posn, tkn );
2786 tkn.
offset =
static_cast<unsigned short>( prog_tokens->
next() );
2787 prog_tokens->
atPut1( tkn, last_if_token_posn );
2796 INFO_PRINT <<
"Expected ELSE or ENDIF after IF statement starting at " << save_ctx
2797 <<
"Did not expect: " << token <<
"\n";
2829 if ( discard_rest && !included_any_tests )
2832 while ( jumpend.size() > jumpend_size )
2837 while ( !jumpend.empty() )
2839 unsigned pc = jumpend.back();
2862 if ( token.
id == endtokenid )
2864 if ( pBlockEndToken != NULL )
2870 if ( last_statement_id != NULL )
2871 *last_statement_id = token.
id;
2876 INFO_PRINT <<
"Error in block beginning at " << tctx <<
"End-of-File detected, expected '" 2886 unsigned conditional_expr_posn = prog_tokens->
next();
2891 unsigned test_expr_token_posn;
2893 &test_expr_token_posn );
2902 program->update_dbg_pos( endblock_tkn );
2909 unsigned exit_loop_posn = prog_tokens->
next();
2911 test_expr_token_posn );
2936 Token tk_varname, tk_delim;
2940 INFO_PRINT <<
"Globals can only be declared at global scope.\n";
2945 INFO_PRINT <<
"Locals can only be declared within a block or function.\n";
2961 INFO_PRINT <<
"Non-identifier declared as a variable: '" << tk_varname.
tokval() <<
"'\n" 2962 <<
"Token: " << tk_varname <<
"\n";
2973 unsigned varindex = 0;
2986 varindex =
static_cast<unsigned>(
globals_.size() );
2992 INFO_PRINT <<
"Global Variable '" << tk_varname.
tokval() <<
"' is already declared at " 3004 <<
"' hides Global variable of same name.\n";
3006 throw std::runtime_error(
"Warnings treated as errors." );
3028 INFO_PRINT <<
"Warning! Deprecated array-declaration syntax used.\n";
3030 throw std::runtime_error(
"Warnings treated as errors." );
3060 INFO_PRINT <<
"Unexpected token: '" << tk_delim <<
"'. Did you mean := for assign?\n";
3065 INFO_PRINT <<
"Unexpected token: " << tk_delim <<
"\n";
3084 Token tk_varname, tk_assign;
3096 INFO_PRINT <<
"Expected identifier after const declaration\n";
3102 INFO_PRINT <<
"Constant " << tk_varname <<
" has already been defined.\n";
3110 INFO_PRINT <<
"Expected := after identifier in const declaration\n";
3117 INFO_PRINT <<
"Error reading expression in const declaration\n";
3121 if ( ex.
tokens.size() != 1 )
3123 INFO_PRINT <<
"Const expression must be optimizable\n";
3146 if (
getToken( ctx, tk_enum_tag ) < 0 )
3154 INFO_PRINT <<
"Expected an enum tag after 'enum'\n";
3158 int next_counter = 0;
3161 Token tk_varname, tk_assign;
3163 if (
getToken( ctx, tk_varname ) < 0 )
3165 INFO_PRINT <<
"Error reading identifier in enum declaration\n";
3174 INFO_PRINT <<
"Expected identifier in enum statement, got " << tk_varname <<
"\n";
3182 INFO_PRINT <<
"Error reading token in enum statement\n";
3193 INFO_PRINT <<
"Error reading expression in enum declaration\n";
3201 if ( ex.
tokens.size() != 1 )
3203 INFO_PRINT <<
"Enum expression must be optimizable\n";
3208 next_counter = tkn->
lval + 1;
3211 constants.insert( Constants::value_type( tk_varname.
tokval(), *tkn ) );
3219 tkn.
lval = next_counter++;
3220 constants.insert( Constants::value_type( tk_varname.
tokval(), tkn ) );
3225 tkn.
lval = next_counter++;
3226 constants.insert( Constants::value_type( tk_varname.
tokval(), tkn ) );
3231 INFO_PRINT <<
"Unexpected token: '" << tmp <<
"'. Did you mean := for assign?\n";
3236 INFO_PRINT <<
"Unexpected token " << tmp <<
" in enum statement\n";
3245 for (
const auto& elem :
program->modules )
3247 if ( modulename == elem->modulename )
3253 std::string filename_part = modulename;
3254 filename_part +=
".em";
3259 INFO_PRINT <<
"Searching for " << filename_full <<
"\n";
3265 INFO_PRINT <<
"Searching for " << try_filename_full <<
"\n";
3269 INFO_PRINT <<
"Found " << try_filename_full <<
"\n";
3271 filename_full = try_filename_full;
3277 INFO_PRINT <<
"Found " << filename_full <<
"\n";
3285 INFO_PRINT <<
"Unable to find module " << modulename <<
"\n" 3286 <<
"\t(Filename: " << filename_full <<
")\n";
3303 INFO_PRINT <<
"Error reading token in module " << modulename <<
"\n";
3307 else if ( res == 1 )
3323 std::unique_ptr<UserFunction> puserfunc(
new UserFunction );
3326 INFO_PRINT <<
"Error reading function declaration in module " << modulename <<
"\n";
3333 if (
getToken( mod_ctx, tk_semicolon ) )
3335 INFO_PRINT << filename_full <<
": Error in declaration for " << puserfunc->name <<
":\n" 3336 <<
" Expected a semicolon, got end-of-file or error\n";
3344 INFO_PRINT << filename_full <<
": Error in declaration for " << puserfunc->name <<
":\n" 3345 <<
" Expected a semicolon, got '" << tk_semicolon <<
"'\n";
3352 compmodl->addFunction( uf->
name.c_str(),
static_cast<int>( uf->
parameters.size() ), uf );
3369 Token tk_module_name, tk_semicolon;
3371 if (
getToken( ctx, tk_module_name ) )
3373 INFO_PRINT <<
"Error in USE statement: USE should be followed by a module name.\n";
3378 INFO_PRINT <<
"Error in USE statement: Expected identifier, got '" << tk_module_name <<
"'\n";
3382 if (
getToken( ctx, tk_semicolon ) )
3384 INFO_PRINT <<
"Error in USE statement (module " << tk_module_name <<
"): " 3385 <<
"Expected ';', got end-of-file or error\n";
3390 INFO_PRINT <<
"Error in USE statement (module " << tk_module_name <<
"): " 3391 <<
"Expected ';', got '" << tk_semicolon <<
"'\n";
3395 if ( strlen( tk_module_name.
tokval() ) > 10 )
3397 INFO_PRINT <<
"Error in USE statement: Module names must be <= 10 characters\n" 3398 <<
"Module specified was: '" << tk_module_name <<
"'\n";
3414 std::string filename_part = modulename;
3415 filename_part +=
".inc";
3419 if ( filename_part[0] ==
':' )
3427 filename_full = pkg->
dir() + path;
3428 std::string try_filename_full = pkg->
dir() +
"include/" + path;
3431 INFO_PRINT <<
"Searching for " << filename_full <<
"\n";
3436 INFO_PRINT <<
"Searching for " << try_filename_full <<
"\n";
3440 INFO_PRINT <<
"Found " << try_filename_full <<
"\n";
3442 filename_full = try_filename_full;
3448 INFO_PRINT <<
"Found " << filename_full <<
"\n";
3451 INFO_PRINT <<
"Warning: Found '" << filename_full.c_str() <<
"' and '" 3452 << try_filename_full.c_str() <<
"'! Will use first file!\n";
3461 INFO_PRINT <<
"Searching for " << filename_full <<
"\n";
3463 INFO_PRINT <<
"Found " << filename_full <<
"\n";
3469 INFO_PRINT <<
"Unable to read include file '" << modulename <<
"'\n";
3476 INFO_PRINT <<
"Searching for " << filename_full <<
"\n";
3482 INFO_PRINT <<
"Searching for " << try_filename_full <<
"\n";
3486 INFO_PRINT <<
"Found " << try_filename_full <<
"\n";
3489 filename_full = try_filename_full;
3495 INFO_PRINT <<
"Found " << filename_full <<
"\n";
3499 std::string filename_check =
Clib::FullPath( filename_full.c_str() );
3500 if (
included.count( filename_check ) )
3510 INFO_PRINT <<
"Unable to find module " << modulename <<
"\n" 3511 <<
"\t(Filename: " << filename_full <<
")\n";
3533 Token tk_module_name, tk_semicolon;
3535 if (
getToken( ctx, tk_module_name ) )
3537 INFO_PRINT <<
"Error in INCLUDE statement: INCLUDE should be followed by a module name.\n";
3542 INFO_PRINT <<
"Error in INCLUDE statement: Expected identifier, got '" << tk_module_name
3547 if (
getToken( ctx, tk_semicolon ) )
3549 INFO_PRINT <<
"Error in INCLUDE statement (module " << tk_module_name <<
"): " 3550 <<
"Expected ';', got end-of-file or error\n";
3555 INFO_PRINT <<
"Error in INCLUDE statement (module " << tk_module_name <<
"): " 3556 <<
"Expected ';', got '" << tk_semicolon <<
"'\n";
3568 unsigned numVarsToKill = 0;
3575 if ( bd.
break_ok && ( label ==
"" ||
3576 label == bd.
label ) )
3578 if ( numVarsToKill )
3591 INFO_PRINT <<
"Couldn't find an appropriate break point";
3613 INFO_PRINT <<
"break statement: expected 'break;' or 'break label;'\n";
3622 INFO_PRINT <<
"break statement: expected 'break;' or 'break label;'\n";
3646 INFO_PRINT <<
"continue statement: expected 'continue;' or 'continue label;'\n";
3655 INFO_PRINT <<
"continue statement: expected 'continue;' or 'continue label;'\n";
3666 unsigned numVarsToKill = 0;
3673 label == bd.
label ) )
3675 if ( numVarsToKill )
3688 INFO_PRINT <<
"Couldn't find an appropriate continue point";
3715 Token itrvar, tmptoken;
3722 INFO_PRINT <<
"FOR iterator must be an identifier, got " << itrvar <<
"\n";
3728 INFO_PRINT <<
"FOR iterator '" << itrvar <<
"' hides a local variable.\n";
3749 unsigned initfor_posn;
3761 program->addlocalvar(
"_" + std::string( itrvar.
tokval() ) +
"_end" );
3765 unsigned again_posn = prog_tokens->
next();
3774 program->update_dbg_pos( endblock_tkn );
3775 unsigned nextfor_posn;
3843 unsigned againPC = prog_tokens->
next();
3844 inject( predicate_expr );
3855 unsigned nextPC = prog_tokens->
next();
3919 unsigned againPC = prog_tokens->
next();
3920 inject( predicate_expr );
3932 unsigned continuePC = prog_tokens->
next();
3934 program->update_dbg_pos( endblock_tkn );
3964 int cnt =
program->tokens.count();
3965 program->fileline.resize( cnt + 1 );
3972 if (
program->fileline.size() )
3973 last =
program->fileline.back();
3975 if (
program->fileline.size() ==
program->tokens.count() + 1 || last.empty() ||
3983 int cnt =
program->tokens.count();
3984 program->sourcelines.resize( cnt + 1 );
3990 unsigned last_position = 0;
3994 if ( include_debug )
4003 program->symbols.append( &DT,
sizeof DT, last_position );
4024 if ( include_debug )
4025 program->append( stok, &last_position );
4027 last_position =
program->tokens.count();
4031 INFO_PRINT <<
"Warning: Found deprecated token " 4032 <<
"'" << token.
tokval() <<
"'" 4033 <<
" on line " << ctx.
line <<
" of " << ctx.
filename <<
"\n";
4035 throw std::runtime_error(
"Warnings treated as errors." );
4045 INFO_PRINT <<
"_OptionBracketed is obsolete.\n";
4099 INFO_PRINT <<
"Unhandled reserved word: " << token <<
"\n";
4108 INFO_PRINT <<
"Label found! " << token <<
"\n";
4118 <<
"Illegal location for label: " << token.tokval() <<
"\n" 4119 <<
"Labels can only come before DO, WHILE, FOR, FOREACH, REPEAT, and CASE statements.\n";
4123 token.lval = last_position;
4136 prog_tokens->
atGet1( prog_tokens->
count() - 1, tmptoken );
4139 prog_tokens->
atGet1( prog_tokens->
count() - 2, tmptoken );
4165 INFO_PRINT <<
"Warning: Equals test result ignored. Did you mean := for assign?\n" 4166 <<
"near: " <<
curLine <<
"\n";
4168 throw std::runtime_error(
"Warnings treated as errors." );
4175 INFO_PRINT <<
"Warning: Result of operation may have no effect.\n" 4176 <<
"Token ID: " << tmptoken.
id <<
"\n" 4177 <<
"near: " <<
curLine <<
"\n";
4179 throw std::runtime_error(
"Warnings treated as errors." );
4195 program->setcontext( savectx );
4204 _tmp <<
"Error compiling statement at ";
4209 catch ( std::exception& ex )
4212 _tmp <<
"Error compiling statement at ";
4214 _tmp << ex.what() <<
"\n";
4229 INFO_PRINT <<
"Can't declare a function inside another function.\n" 4230 <<
"(attempt to declare " << funcName <<
")\n";
4255 unsigned skip_goto_posn;
4258 if ( include_debug )
4277 prog_tokens->
atGet1( prog_tokens->
count() - 1, tmptoken );
4281 skip_goto_posn = prog_tokens->
count() - 2;
4285 program->symbols.append( userfunc.
name.c_str(), posn );
4299 INFO_PRINT <<
"Error reading function definition for " << userfunc.
name <<
"()\n" 4300 <<
"Expected BEGIN .. END block, got token: '" << token <<
"'\n";
4309 for (
int i = static_cast<unsigned int>( userfunc.
parameters.size() - 1 ); i >= 0; --i )
4312 program->symbols.append( user_param->
name.c_str(), posn );
4327 prog_tokens->
atGet1( prog_tokens->
count() - 1, tmp );
4330 program->symbols.append(
"", posn );
4354 INFO_PRINT <<
"Can't declare a function inside another function.\n";
4379 unsigned skip_goto_posn;
4382 if ( include_debug )
4400 prog_tokens->
atGet1( prog_tokens->
count() - 1, tmptoken );
4404 skip_goto_posn = prog_tokens->
count() - 2;
4408 program->symbols.append( userfunc.
name.c_str(), posn );
4420 for (
int i = static_cast<unsigned int>( userfunc.
parameters.size() - 1 ); i >= 0; --i )
4423 program->symbols.append( params->
name.c_str(), posn );
4437 INFO_PRINT <<
"Error occurred reading function body for '" << userfunc.
name <<
"'\n" 4438 <<
"Function location: " << save_ctx <<
"Error location: \n";
4442 program->update_dbg_pos( endblock_tkn );
4444 prog_tokens->
atGet1( prog_tokens->
count() - 1, tmp );
4447 program->symbols.append(
"", posn );
4473 res =
getToken( ctx, tk_function );
4478 INFO_PRINT <<
"Expected 'function' after 'exported'.\n";
4485 INFO_PRINT <<
"Can't declare a function inside another function.\n";
4503 INFO_PRINT <<
"End-of-File detected, expected 'ENDFUNCTION'\n";
4509 INFO_PRINT <<
"Error occurred reading function body for '" << tk_funcname.
tokval() <<
"'\n" 4510 <<
"Function location: " << save_ctx <<
"Error location: \n";
4524 INFO_PRINT <<
"'program' function has already been defined.\n";
4530 const char* program_body_start = ctx.
s;
4540 const char* program_body_end = ctx.
s;
4541 size_t len = program_body_end - program_body_start + 1;
4550 INFO_PRINT <<
"End of file detected, expected 'endprogram'\n";
4562 res =
getToken( ctx, tk_progname );
4567 INFO_PRINT <<
"Error: expected identified after 'program', got '" << tk_progname <<
"'\n";
4581 bool unused =
false;
4586 INFO_PRINT <<
"End-of-file reached reading program argument list\n";
4605 INFO_PRINT <<
"Program argument '" << token <<
"' multiply defined.\n";
4623 INFO_PRINT <<
"Expected arguments or right-paren in program arglist, got '" << token <<
"'\n";
4634 program->update_dbg_pos( endblock_tkn );
4644 unsigned first_PC = program_tokens->
count();
4647 program->function_decls.resize( program_tokens->
count() + 1 );
4672 ef.
PC = program_tokens->
count();
4673 program->exported_functions.push_back( ef );
4687 for (
int i = static_cast<unsigned int>( userfunc.
parameters.size() - 1 ); i >= 0; --i )
4690 program->symbols.append( params->
name.c_str(), posn );
4704 INFO_PRINT <<
"Error in function '" << userfunc.
name <<
"', " << ctx <<
"\n";
4707 program->update_dbg_pos( endblock_tkn );
4710 program_tokens->
atGet1( program_tokens->
count() - 1, tmp );
4723 program->symbols.append(
int( 0 ), posn );
4733 unsigned last_PC = program_tokens->
count() - 1;
4734 program->addfunction( userfunc.
name, first_PC, last_PC );
4760 INFO_PRINT <<
"Expected 'function' after 'exported'\n";
4772 const char* function_body_start = ctx.
s;
4781 const char* function_body_end = ctx.
s;
4782 size_t len = function_body_end - function_body_start + 1;
4785 memcpy( userfunc.
function_body, function_body_start, len - 1 );
4795 INFO_PRINT <<
"End-of-File detected, expected 'ENDFUNCTION'\n" << save_ctx;
4801 INFO_PRINT <<
"Error occurred reading function body for '" << userfunc.
name <<
"'\n" 4802 <<
"Function location: " << save_ctx <<
"Error location: \n";
4813 program->tokens.atGet1( instruc, tkn );
4814 tkn.
offset =
static_cast<unsigned short>( newoffset );
4815 program->tokens.atPut1( tkn, instruc );
4829 while ( ( res >= 0 ) && ctx.
s[0] )
4834 catch ( std::exception& )
4836 INFO_PRINT <<
"Exception detected during compilation.\n" << ctx;
4874 program->symbols.append(
"", dummy );
4896 catch ( std::runtime_error& excep )
4908 _tmp <<
"Error detected in program body.\n" 4909 <<
"Error occurred at ";
4921 program->append( tkn, &last_posn );
4939 <<
" Specified: " << filepart <<
"\n" 4940 <<
" Filesystem: " << truename <<
"\n";
4948 FILE* fp = fopen( file,
"rb" );
4953 if ( fseek( fp, 0, SEEK_END ) != 0 )
4960 int filelen = ftell( fp );
4968 if ( fseek( fp, 0, SEEK_SET ) != 0 )
4974 s = (
char*)calloc( 1, filelen + 1 );
4981 if (fread( s, filelen, 1, fp ) != 1 )
4994 std::string filename_part = modulename;
4995 filename_part +=
".inc";
4999 if ( filename_part[0] ==
':' )
5007 filename_full = pkg->
dir() + path;
5008 std::string try_filename_full = pkg->
dir() +
"include/" + path;
5011 INFO_PRINT <<
"Searching for " << filename_full <<
"\n";
5016 INFO_PRINT <<
"Searching for " << try_filename_full <<
"\n";
5020 INFO_PRINT <<
"Found " << try_filename_full <<
"\n";
5022 filename_full = try_filename_full;
5028 INFO_PRINT <<
"Found " << filename_full <<
"\n";
5031 INFO_PRINT <<
"Warning: Found '" << filename_full.c_str() <<
"' and '" 5032 << try_filename_full.c_str() <<
"'! Will use first file!\n";
5041 INFO_PRINT <<
"Searching for " << filename_full <<
"\n";
5043 INFO_PRINT <<
"Found " << filename_full <<
"\n";
5049 INFO_PRINT <<
"Unable to read include file '" << modulename <<
"'\n";
5056 INFO_PRINT <<
"Searching for " << filename_full <<
"\n";
5062 INFO_PRINT <<
"Searching for " << try_filename_full <<
"\n";
5066 INFO_PRINT <<
"Found " << try_filename_full <<
"\n";
5068 filename_full = try_filename_full;
5074 INFO_PRINT <<
"Found " << filename_full <<
"\n";
5078 std::string filename_check =
Clib::FullPath( filename_full.c_str() );
5079 if (
included.count( filename_check ) )
5087 INFO_PRINT <<
"Unable to read include file '" << filename_full <<
"'\n";
5137 INFO_PRINT <<
"Error in const declaration\n" << tctx;
5145 INFO_PRINT <<
"Error in enum declaration\n" << tctx;
5154 INFO_PRINT <<
"Error reading function\n" << tctx;
5160 Token tk_module_name;
5162 if (
getToken( tctx, tk_module_name ) == 0 &&
5174 Token tk_module_name;
5175 if (
getToken( tctx, tk_module_name ) == 0 &&
5287 const char* ext = strstr( file,
".hsr" );
5288 if ( ext && memcmp( ext,
".hsr", 5 ) == 0 )
5290 ext = strstr( file,
".asp" );
5291 if ( ext && memcmp( ext,
".asp", 5 ) == 0 )
5302 output =
"use http;";
5305 bool reading_html =
true;
5306 bool source_is_emit =
false;
5313 if ( s[0] ==
'<' && s[1] ==
'%' )
5315 reading_html =
false;
5318 output +=
"WriteHtmlRaw( \"" + acc +
"\");\n";
5322 source_is_emit = ( s[0] ==
'=' );
5323 if ( source_is_emit )
5325 output +=
"WriteHtmlRaw( ";
5333 else if ( *s ==
'\r' )
5335 else if ( *s ==
'\n' )
5344 if ( s[0] ==
'%' && s[1] ==
'>' )
5346 reading_html =
true;
5348 if ( source_is_emit )
5358 output +=
"WriteHtmlRaw( \"" + acc +
"\");\n";
5399 catch (
const char* s )
5401 INFO_PRINT <<
"Exception Detected:" << s <<
"\n";
5404 catch ( std::exception& ex )
5406 INFO_PRINT <<
"Exception Detected:\n" << ex.what() <<
"\n";
5427 return program->write( fname );
5432 return program->write_dbg( fname, gen_txt );
5437 std::ofstream ofs( fname, std::ios::out | std::ios::trunc );
5441 ofs << elem << std::endl;
int handleProgram2(CompilerContext &ctx, int level)
void dump(std::ostream &os)
std::vector< unsigned > dbg_ins_blocks
const unsigned EXPR_FLAG_DICTKEY_TERM_ALLOWED
std::string FullPath(const char *filename)
int readFunctionDeclaration(CompilerContext &ctx, UserFunction &userfunc)
int compileContext(CompilerContext &ctx)
virtual int isUserFunc(Token &tok, UserFunction **userfunc) POL_OVERRIDE
int getExpr(CompilerContext &ctx, unsigned expr_flags, size_t *exprlen=NULL, Expression *ex=NULL)
const unsigned EXPR_FLAG_AUTO_TERM_ALLOWED
void preprocess_web_script(Clib::FileContents &fc)
int getExpr2(CompilerContext &ctx, unsigned expr_flags, Expression *ex=NULL)
int emit_function(UserFunction &uf)
bool substitute_constant(Token *tkn) const
bool varexists(const std::string &varname, unsigned &idx) const
virtual int getToken(CompilerContext &ctx, Token &token, Expression *expr=NULL) POL_OVERRIDE
void atGet1(unsigned position, StoredToken &token) const
static bool check_filecase_
virtual int getDictionaryMembers(Expression &expr, CompilerContext &ctx) POL_OVERRIDE
int compile(CompilerContext &ctx)
unsigned numVarsInBlock() const
bool mismatched_end(const Token &token, BTokenId correct)
int handleExit(CompilerContext &ctx)
void eat2(Expression &expr)
virtual int getUserArgs(Expression &ex, CompilerContext &ctx, bool inject_jsr) POL_OVERRIDE
void convert_variables(Expression &expr) const
void inject(Expression &expr)
std::vector< bool > dbg_ins_statementbegin
int handleEnumDeclare(CompilerContext &ctx)
const char * tokval() const
void readCurLine(CompilerContext &ctx)
bool is_web_script(const char *file)
Token * optimize_double_operation(Token *left, Token *oper, Token *right)
void enterblock(eb_label_ok eblabel, eb_break_ok ebbreak, eb_continue_ok ebcontinue)
void fillFunctionsByName()
void reinit(Expression &ex)
ObjMember * getKnownObjMember(const char *token)
int handleBreak(CompilerContext &ctx)
void popblock(bool varsOnly)
virtual int getMethodArguments(Expression &expr, CompilerContext &ctx, int &nargs) POL_OVERRIDE
std::string decint(unsigned short v)
std::vector< BlockDesc > blockdescs_
TokenAddrs continue_tokens
const char * contents() const
std::string ModuleDirectory
void patch_callers(UserFunction &uf)
const unsigned EXPR_FLAG_SINGLE_ELEMENT
bool read_function_declarations(const CompilerContext &ctx)
void addToken(Token &tok)
char * stracpy(char *dest, const char *src, size_t maxlen)
virtual int getFunctionPArgument(Expression &expr, CompilerContext &ctx, Token *tok) POL_OVERRIDE
bool optimize_token(int i)
std::vector< std::string > referencedPathnames
Addresses forward_callers
#define OSTRINGSTREAM_STR(x)
int getStatement(CompilerContext &ctx, int level)
void optimize_binary_operations()
CompilerConfig compilercfg
int handleContinue(CompilerContext &ctx)
const unsigned EXPR_FLAG_RIGHTPAREN_TERM_ALLOWED
int handleProgram(CompilerContext &ctx, int level)
int handleRepeatUntil(CompilerContext &ctx, int level)
std::string GetFilePart(const char *filename)
int IIP(Expression &expr, CompilerContext &ctx, unsigned expr_flags)
void leaveblock(unsigned breakPC, unsigned continuePC)
UserFunctions userFunctions
int handleConstDeclare(CompilerContext &ctx)
static int verbosity_level_
int handleBracketedFor_c(CompilerContext &ctx)
bool pkgdef_split(const std::string &spec, const Package *inpkg, const Package **outpkg, std::string *path)
const unsigned EXPR_FLAG_CONSUME_RESULT
int handleBlock(CompilerContext &ctx, int level)
int handleDeclare(CompilerContext &ctx)
void optimize_unary_operations()
void copyStr(const char *s)
const unsigned EXPR_FLAG_TO_TERM_ALLOWED
int get_num_tokens(int idx) const
void checkpoint(const char *msg, unsigned short minlvl)
void commit(const EScriptProgram &prog)
void patchblock_breaks(unsigned breakPC)
Token * optimize_long_operation(Token *left, Token *oper, Token *right)
unsigned int numVariables() const
std::vector< char * > delete_these_arrays
std::vector< std::string > fileline
virtual int isFunc(Token &tok, ModuleFunction **v) POL_OVERRIDE
unsigned count(void) const
int handleFor(CompilerContext &ctx)
std::string tostring(const Bscript::BTokenType &v)
std::vector< std::string > sourcelines
virtual int getToken(CompilerContext &ctx, Token &token, Expression *expr=NULL)
int handleReturn(CompilerContext &ctx)
void substitute_constants(Expression &expr) const
int eatToken(CompilerContext &ctx, BTokenId tokenid)
int handleBracketedFunction2(CompilerContext &ctx, int level, int tokentype)
Candidate(int module, int funcidx)
bool varexists(const std::string &varname) const
int handleIf(CompilerContext &ctx, int level)
int forward_read_function(CompilerContext &ctx)
int handleBracketedFor_basic(CompilerContext &ctx)
int handleUse(CompilerContext &ctx)
int getExprInParens(CompilerContext &ctx, Expression *ex=NULL)
int _getStatement(CompilerContext &ctx, int level)
std::string PolScriptRoot
std::string GetTrueName(const char *filename)
bool OptimizeObjectMembers
int write_dbg(const char *fname, bool generate_txtfile)
virtual int getNewArrayElements(Expression &expr, CompilerContext &ctx) POL_OVERRIDE
void emitFileLine(CompilerContext &ctx)
int insertBreak(const std::string &label)
const char * ParseErrorStr[PERR_NUM_ERRORS]
void writeIncludedFilenames(const char *fname) const
std::string IncludeDirectory
void eat(Expression &expr)
void atPut1(const StoredToken &token, unsigned position)
int readblock(CompilerContext &ctx, int level, BTokenId endtokenid, BTokenId *last_statement_id=NULL, Token *block_end=NULL)
void rollback(EScriptProgram &prog, const EScriptProgramCheckpoint &checkpoint)
StoredTokenContainer tokens
const unsigned EXPR_FLAG_RIGHTBRACE_TERM_ALLOWED
int stringicmp(const S1 &str1, const S2 &str2)
virtual int getStructMembers(Expression &expr, CompilerContext &ctx) POL_OVERRIDE
int readexpr(Expression &expr, CompilerContext &ctx, unsigned flags)
int getSimpleExpr(CompilerContext &ctx)
int handleBracketedWhile(CompilerContext &ctx, int level)
std::vector< unsigned > dbg_linenum
std::vector< unsigned > dbg_filenum
int handleInclude(CompilerContext &ctx)
int getFileContents(const char *filename, char **contents)
std::string current_file_path
bool inGlobalScope() const
void addModule(FunctionalityModule *module)
std::string getpathof(const std::string &fname)
int validate(const Expression &expr, CompilerContext &ctx) const
int handleFor_c(CompilerContext &ctx)
virtual int peekToken(const CompilerContext &ctx, Token &token, Expression *expr=NULL)
virtual int isLegal(Token &tok) POL_OVERRIDE
void set_contents(const std::string &str)
virtual int getArrayElements(Expression &expr, CompilerContext &ctx) POL_OVERRIDE
void setcount(unsigned newCount)
void emitFileLineIfFileChanged(CompilerContext &ctx)
int handleBracketedIf(CompilerContext &ctx, int level)
void setlength(unsigned newLen)
int handleBracketedFunction(CompilerContext &ctx)
bool read_function_declarations_in_included_file(const char *modulename)
int handleFunction(CompilerContext &ctx)
const unsigned EXPR_FLAG_COMMA_TERM_ALLOWED
void addvar(const std::string &varname, const CompilerContext &ctx, bool warn_on_notused=true, bool unused=false)
bool globalexists(const std::string &varname, unsigned &idx, CompilerContext *atctx=NULL) const
bool FileExists(const char *filename)
#define passert_always(exp)
void printOnShort(std::ostream &os) const
int handleDoClause(CompilerContext &ctx, int level)
eb_continue_ok continue_ok
int includeModule(const std::string &modulename)
int handleBracketedFunction3(UserFunction &userfunc, CompilerContext &ctx)
CompilerContext program_ctx
ref_ptr< EScriptProgram > program
int handleVarDeclare(CompilerContext &ctx, unsigned save_id)
bool inner_read_function_declarations(const CompilerContext &ctx)
int write(const char *fname)
std::vector< FunctionalityModule * > modules
int useModule(const char *modulename)
void patchoffset(unsigned instruc, unsigned newoffset)
void optimize_assignments()
Token * optimize_string_operation(Token *left, Token *oper, Token *right)
const unsigned EXPR_FLAG_ENDENUM_TERM_ALLOWED
unsigned sourcelines_count
const std::string & dir() const
int handleSwitch(CompilerContext &ctx, int level)
void patchblock_continues(unsigned continuePC)
int compileFile(const char *fname)
const unsigned EXPR_FLAG_SEMICOLON_TERM_ALLOWED
int handleForEach(CompilerContext &ctx, int level)