Author: cwittich Date: Sun Oct 18 20:40:13 2009 New Revision: 43568
URL: http://svn.reactos.org/svn/reactos?rev=43568&view=rev Log: add a regression test for RosBE (flex/bison)
Added: trunk/tools/RosBE/RosBE-Windows/regtest/ (with props) trunk/tools/RosBE/RosBE-Windows/regtest/parser.l (with props) trunk/tools/RosBE/RosBE-Windows/regtest/parser.y (with props) trunk/tools/RosBE/RosBE-Windows/regtest/regtest.cmd (with props)
Propchange: trunk/tools/RosBE/RosBE-Windows/regtest/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Sun Oct 18 20:40:13 2009 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: trunk/tools/RosBE/RosBE-Windows/regtest/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: trunk/tools/RosBE/RosBE-Windows/regtest/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Added: trunk/tools/RosBE/RosBE-Windows/regtest/parser.l URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/regtest/p... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/regtest/parser.l (added) +++ trunk/tools/RosBE/RosBE-Windows/regtest/parser.l [iso-8859-1] Sun Oct 18 20:40:13 2009 @@ -1,0 +1,482 @@ +/* -*-C-*- + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +%option stack +%option noinput nounput noyy_top_state +%option 8bit never-interactive prefix="parser_" + +nl \r?\n +ws [ \f\t\r] +cident [a-zA-Z_][0-9a-zA-Z_]* +u_suffix (u|U) +l_suffix (l|L) +int [0-9]+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)? +hexd [0-9a-fA-F] +hex 0(x|X){hexd}+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)? +uuid {hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12} +double [0-9]+.[0-9]+([eE][+-]?[0-9]+)* + +%x QUOTE +%x WSTRQUOTE +%x ATTR +%x PP_LINE + +%{ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <errno.h> +#include <limits.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#else +#define YY_NO_UNISTD_H +#endif + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "wine/wpp.h" + +#include "parser.tab.h" + +extern char *temp_name; + +static void addcchar(char c); +static char *get_buffered_cstring(void); + +static char *cbuffer; +static int cbufidx; +static int cbufalloc = 0; + +static int kw_token(const char *kw); +static int attr_token(const char *kw); + +#define MAX_IMPORT_DEPTH 10 +struct { + YY_BUFFER_STATE state; + char *input_name; + int line_number; + char *temp_name; +} import_stack[MAX_IMPORT_DEPTH]; +int import_stack_ptr = 0; + +/* converts an integer in string form to an unsigned long and prints an error + * on overflow */ +static unsigned long xstrtoul(const char *nptr, char **endptr, int base) +{ + unsigned long l; + + errno = 0; + l = strtoul(nptr, endptr, base); + if (l == ULONG_MAX && errno == ERANGE) + error_loc("integer constant %s is too large\n", nptr); + return l; +} + +UUID *parse_uuid(const char *u) +{ + UUID* uuid = xmalloc(sizeof(UUID)); + char b[3]; + /* it would be nice to use UuidFromStringA */ + uuid->Data1 = strtoul(u, NULL, 16); + uuid->Data2 = strtoul(u+9, NULL, 16); + uuid->Data3 = strtoul(u+14, NULL, 16); + b[2] = 0; + memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16); + memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16); + memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16); + memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16); + memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16); + memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16); + memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16); + memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16); + return uuid; +} + +%} + +/* + ************************************************************************** + * The flexer starts here + ************************************************************************** + */ +%% +<INITIAL,ATTR>^{ws}*#{ws}* yy_push_state(PP_LINE); +<PP_LINE>[^\n]* { + int lineno; + char *cptr, *fname; + yy_pop_state(); + lineno = (int)strtol(yytext, &cptr, 10); + if(!lineno) + error_loc("Malformed '#...' line-directive; invalid linenumber\n"); + fname = strchr(cptr, '"'); + if(!fname) + error_loc("Malformed '#...' line-directive; missing filename\n"); + fname++; + cptr = strchr(fname, '"'); + if(!cptr) + error_loc("Malformed '#...' line-directive; missing terminating "\n"); + *cptr = '\0'; + line_number = lineno - 1; /* We didn't read the newline */ + free( input_name ); + input_name = xstrdup(fname); + } +<INITIAL,ATTR>" yy_push_state(QUOTE); cbufidx = 0; +<QUOTE>" { + yy_pop_state(); + parser_lval.str = get_buffered_cstring(); + return aSTRING; + } +<INITIAL,ATTR>L" yy_push_state(WSTRQUOTE); +<WSTRQUOTE>" { + yy_pop_state(); + parser_lval.str = get_buffered_cstring(); + return aWSTRING; + } +<QUOTE,WSTRQUOTE>\\ | +<QUOTE,WSTRQUOTE>\" addcchar(yytext[1]); +<QUOTE,WSTRQUOTE>\. addcchar('\'); addcchar(yytext[1]); +<QUOTE,WSTRQUOTE>. addcchar(yytext[0]); +<INITIAL,ATTR>[ yy_push_state(ATTR); return '['; +<ATTR>] yy_pop_state(); return ']'; +<ATTR>{cident} return attr_token(yytext); +<ATTR>{uuid} { + parser_lval.uuid = parse_uuid(yytext); + return aUUID; + } +<INITIAL,ATTR>{hex} { + parser_lval.num = xstrtoul(yytext, NULL, 0); + return aHEXNUM; + } +<INITIAL,ATTR>{int} { + parser_lval.num = xstrtoul(yytext, NULL, 0); + return aNUM; + } +<INITIAL>{double} { + parser_lval.dbl = strtod(yytext, NULL); + return aDOUBLE; + } +SAFEARRAY{ws}*/( return tSAFEARRAY; +{cident} return kw_token(yytext); +<INITIAL,ATTR>\n line_number++; +<INITIAL,ATTR>{ws} +<INITIAL,ATTR><< return SHL; +<INITIAL,ATTR>>> return SHR; +<INITIAL,ATTR>-> return MEMBERPTR; +<INITIAL,ATTR>== return EQUALITY; +<INITIAL,ATTR>!= return INEQUALITY; +<INITIAL,ATTR>>= return GREATEREQUAL; +<INITIAL,ATTR><= return LESSEQUAL; +<INITIAL,ATTR>|| return LOGICALOR; +<INITIAL,ATTR>&& return LOGICALAND; +<INITIAL,ATTR>. return yytext[0]; +<<EOF>> { + if (import_stack_ptr) + return aEOF; + else yyterminate(); + } +%% + +#ifndef parser_wrap +int parser_wrap(void) +{ + return 1; +} +#endif + +struct keyword { + const char *kw; + int token; +}; + +/* This table MUST be alphabetically sorted on the kw field */ +static const struct keyword keywords[] = { + {"FALSE", tFALSE}, + {"NULL", tNULL}, + {"TRUE", tTRUE}, + {"__cdecl", tCDECL}, + {"__fastcall", tFASTCALL}, + {"__int64", tINT64}, + {"__pascal", tPASCAL}, + {"__stdcall", tSTDCALL}, + {"_cdecl", tCDECL}, + {"_fastcall", tFASTCALL}, + {"_pascal", tPASCAL}, + {"_stdcall", tSTDCALL}, + {"boolean", tBOOLEAN}, + {"byte", tBYTE}, + {"case", tCASE}, + {"cdecl", tCDECL}, + {"char", tCHAR}, + {"coclass", tCOCLASS}, + {"const", tCONST}, + {"cpp_quote", tCPPQUOTE}, + {"default", tDEFAULT}, + {"dispinterface", tDISPINTERFACE}, + {"double", tDOUBLE}, + {"enum", tENUM}, + {"error_status_t", tERRORSTATUST}, + {"extern", tEXTERN}, + {"float", tFLOAT}, + {"handle_t", tHANDLET}, + {"hyper", tHYPER}, + {"import", tIMPORT}, + {"importlib", tIMPORTLIB}, + {"inline", tINLINE}, + {"int", tINT}, + {"interface", tINTERFACE}, + {"library", tLIBRARY}, + {"long", tLONG}, + {"methods", tMETHODS}, + {"module", tMODULE}, + {"pascal", tPASCAL}, + {"properties", tPROPERTIES}, + {"register", tREGISTER}, + {"short", tSHORT}, + {"signed", tSIGNED}, + {"sizeof", tSIZEOF}, + {"small", tSMALL}, + {"static", tSTATIC}, + {"stdcall", tSTDCALL}, + {"struct", tSTRUCT}, + {"switch", tSWITCH}, + {"typedef", tTYPEDEF}, + {"union", tUNION}, + {"unsigned", tUNSIGNED}, + {"void", tVOID}, + {"wchar_t", tWCHAR}, +}; +#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) + +/* keywords only recognized in attribute lists + * This table MUST be alphabetically sorted on the kw field + */ +static const struct keyword attr_keywords[] = +{ + {"aggregatable", tAGGREGATABLE}, + {"allocate", tALLOCATE}, + {"appobject", tAPPOBJECT}, + {"async", tASYNC}, + {"async_uuid", tASYNCUUID}, + {"auto_handle", tAUTOHANDLE}, + {"bindable", tBINDABLE}, + {"broadcast", tBROADCAST}, + {"byte_count", tBYTECOUNT}, + {"call_as", tCALLAS}, + {"callback", tCALLBACK}, + {"code", tCODE}, + {"comm_status", tCOMMSTATUS}, + {"context_handle", tCONTEXTHANDLE}, + {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE}, + {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE}, + {"control", tCONTROL}, + {"defaultcollelem", tDEFAULTCOLLELEM}, + {"defaultvalue", tDEFAULTVALUE}, + {"defaultvtable", tDEFAULTVTABLE}, + {"displaybind", tDISPLAYBIND}, + {"dllname", tDLLNAME}, + {"dual", tDUAL}, + {"endpoint", tENDPOINT}, + {"entry", tENTRY}, + {"explicit_handle", tEXPLICITHANDLE}, + {"handle", tHANDLE}, + {"helpcontext", tHELPCONTEXT}, + {"helpfile", tHELPFILE}, + {"helpstring", tHELPSTRING}, + {"helpstringcontext", tHELPSTRINGCONTEXT}, + {"helpstringdll", tHELPSTRINGDLL}, + {"hidden", tHIDDEN}, + {"id", tID}, + {"idempotent", tIDEMPOTENT}, + {"iid_is", tIIDIS}, + {"immediatebind", tIMMEDIATEBIND}, + {"implicit_handle", tIMPLICITHANDLE}, + {"in", tIN}, + {"in_line", tIN_LINE}, + {"input_sync", tINPUTSYNC}, + {"lcid", tLCID}, + {"length_is", tLENGTHIS}, + {"local", tLOCAL}, + {"nonbrowsable", tNONBROWSABLE}, + {"noncreatable", tNONCREATABLE}, + {"nonextensible", tNONEXTENSIBLE}, + {"object", tOBJECT}, + {"odl", tODL}, + {"oleautomation", tOLEAUTOMATION}, + {"optional", tOPTIONAL}, + {"out", tOUT}, + {"pointer_default", tPOINTERDEFAULT}, + {"propget", tPROPGET}, + {"propput", tPROPPUT}, + {"propputref", tPROPPUTREF}, + {"ptr", tPTR}, + {"public", tPUBLIC}, + {"range", tRANGE}, + {"readonly", tREADONLY}, + {"ref", tREF}, + {"requestedit", tREQUESTEDIT}, + {"restricted", tRESTRICTED}, + {"retval", tRETVAL}, + {"size_is", tSIZEIS}, + {"source", tSOURCE}, + {"strict_context_handle", tSTRICTCONTEXTHANDLE}, + {"string", tSTRING}, + {"switch_is", tSWITCHIS}, + {"switch_type", tSWITCHTYPE}, + {"transmit_as", tTRANSMITAS}, + {"unique", tUNIQUE}, + {"uuid", tUUID}, + {"v1_enum", tV1ENUM}, + {"vararg", tVARARG}, + {"version", tVERSION}, + {"wire_marshal", tWIREMARSHAL}, +}; + + +#define KWP(p) ((const struct keyword *)(p)) + +static int kw_cmp_func(const void *s1, const void *s2) +{ + return strcmp(KWP(s1)->kw, KWP(s2)->kw); +} + +static int kw_token(const char *kw) +{ + struct keyword key, *kwp; + key.kw = kw; + kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func); + if (kwp) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } + parser_lval.str = xstrdup(kw); + return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER; +} + +static int attr_token(const char *kw) +{ + struct keyword key, *kwp; + key.kw = kw; + kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]), + sizeof(attr_keywords[0]), kw_cmp_func); + if (kwp) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } + return kw_token(kw); +} + +static void addcchar(char c) +{ + if(cbufidx >= cbufalloc) + { + cbufalloc += 1024; + cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0])); + if(cbufalloc > 65536) + parser_warning("Reallocating string buffer larger than 64kB\n"); + } + cbuffer[cbufidx++] = c; +} + +static char *get_buffered_cstring(void) +{ + addcchar(0); + return xstrdup(cbuffer); +} + +void pop_import(void) +{ + int ptr = import_stack_ptr-1; + + fclose(yyin); + yy_delete_buffer( YY_CURRENT_BUFFER ); + yy_switch_to_buffer( import_stack[ptr].state ); + if (temp_name) { + unlink(temp_name); + free(temp_name); + } + temp_name = import_stack[ptr].temp_name; + input_name = import_stack[ptr].input_name; + line_number = import_stack[ptr].line_number; + import_stack_ptr--; +} + +struct imports { + char *name; + struct imports *next; +} *first_import; + +int do_import(char *fname) +{ + FILE *f; + char *path; + struct imports *import; + int ptr = import_stack_ptr; + int ret; + + import = first_import; + while (import && strcmp(import->name, fname)) + import = import->next; + if (import) return 0; /* already imported */ + + import = xmalloc(sizeof(struct imports)); + import->name = xstrdup(fname); + import->next = first_import; + first_import = import; + + /* don't search for a file name with a path in the include directories, + * for compatibility with MIDL */ + if (strchr( fname, '/' ) || strchr( fname, '\' )) + path = strdup( fname ); + else if (!(path = wpp_find_include( fname, input_name ))) + error_loc("Unable to open include file %s\n", fname); + + import_stack[ptr].temp_name = temp_name; + import_stack[ptr].input_name = input_name; + import_stack[ptr].line_number = line_number; + import_stack_ptr++; + input_name = path; + line_number = 1; + + ret = wpp_parse_temp( path, NULL, &temp_name ); + if (ret) exit(1); + + if((f = fopen(temp_name, "r")) == NULL) + error_loc("Unable to open %s\n", temp_name); + + import_stack[ptr].state = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); + return 1; +} + +void abort_import(void) +{ + int ptr; + + for (ptr=0; ptr<import_stack_ptr; ptr++) + unlink(import_stack[ptr].temp_name); +}
Propchange: trunk/tools/RosBE/RosBE-Windows/regtest/parser.l ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/tools/RosBE/RosBE-Windows/regtest/parser.y URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/regtest/p... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/regtest/parser.y (added) +++ trunk/tools/RosBE/RosBE-Windows/regtest/parser.y [iso-8859-1] Sun Oct 18 20:40:13 2009 @@ -1,0 +1,1636 @@ +/* + * Copyright 2008 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +%{ + +#include "jscript.h" +#include "engine.h" + +#define YYLEX_PARAM ctx +#define YYPARSE_PARAM ctx + +static int parser_error(const char*); +static void set_error(parser_ctx_t*,UINT); +static BOOL explicit_error(parser_ctx_t*,void*,WCHAR); +static BOOL allow_auto_semicolon(parser_ctx_t*); +static void program_parsed(parser_ctx_t*,source_elements_t*); +static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*); + +typedef struct _statement_list_t { + statement_t *head; + statement_t *tail; +} statement_list_t; + +static literal_t *new_string_literal(parser_ctx_t*,const WCHAR*); +static literal_t *new_null_literal(parser_ctx_t*); +static literal_t *new_undefined_literal(parser_ctx_t*); +static literal_t *new_boolean_literal(parser_ctx_t*,VARIANT_BOOL); + +typedef struct _property_list_t { + prop_val_t *head; + prop_val_t *tail; +} property_list_t; + +static property_list_t *new_property_list(parser_ctx_t*,literal_t*,expression_t*); +static property_list_t *property_list_add(parser_ctx_t*,property_list_t*,literal_t*,expression_t*); + +typedef struct _element_list_t { + array_element_t *head; + array_element_t *tail; +} element_list_t; + +static element_list_t *new_element_list(parser_ctx_t*,int,expression_t*); +static element_list_t *element_list_add(parser_ctx_t*,element_list_t*,int,expression_t*); + +typedef struct _argument_list_t { + argument_t *head; + argument_t *tail; +} argument_list_t; + +static argument_list_t *new_argument_list(parser_ctx_t*,expression_t*); +static argument_list_t *argument_list_add(parser_ctx_t*,argument_list_t*,expression_t*); + +typedef struct _case_list_t { + case_clausule_t *head; + case_clausule_t *tail; +} case_list_t; + +static catch_block_t *new_catch_block(parser_ctx_t*,const WCHAR*,statement_t*); +static case_clausule_t *new_case_clausule(parser_ctx_t*,expression_t*,statement_list_t*); +static case_list_t *new_case_list(parser_ctx_t*,case_clausule_t*); +static case_list_t *case_list_add(parser_ctx_t*,case_list_t*,case_clausule_t*); +static case_clausule_t *new_case_block(parser_ctx_t*,case_list_t*,case_clausule_t*,case_list_t*); + +typedef struct _variable_list_t { + variable_declaration_t *head; + variable_declaration_t *tail; +} variable_list_t; + +static variable_declaration_t *new_variable_declaration(parser_ctx_t*,const WCHAR*,expression_t*); +static variable_list_t *new_variable_list(parser_ctx_t*,variable_declaration_t*); +static variable_list_t *variable_list_add(parser_ctx_t*,variable_list_t*,variable_declaration_t*); + +static statement_t *new_block_statement(parser_ctx_t*,statement_list_t*); +static statement_t *new_var_statement(parser_ctx_t*,variable_list_t*); +static statement_t *new_empty_statement(parser_ctx_t*); +static statement_t *new_expression_statement(parser_ctx_t*,expression_t*); +static statement_t *new_if_statement(parser_ctx_t*,expression_t*,statement_t*,statement_t*); +static statement_t *new_while_statement(parser_ctx_t*,BOOL,expression_t*,statement_t*); +static statement_t *new_for_statement(parser_ctx_t*,variable_list_t*,expression_t*,expression_t*, + expression_t*,statement_t*); +static statement_t *new_forin_statement(parser_ctx_t*,variable_declaration_t*,expression_t*,expression_t*,statement_t*); +static statement_t *new_continue_statement(parser_ctx_t*,const WCHAR*); +static statement_t *new_break_statement(parser_ctx_t*,const WCHAR*); +static statement_t *new_return_statement(parser_ctx_t*,expression_t*); +static statement_t *new_with_statement(parser_ctx_t*,expression_t*,statement_t*); +static statement_t *new_labelled_statement(parser_ctx_t*,const WCHAR*,statement_t*); +static statement_t *new_switch_statement(parser_ctx_t*,expression_t*,case_clausule_t*); +static statement_t *new_throw_statement(parser_ctx_t*,expression_t*); +static statement_t *new_try_statement(parser_ctx_t*,statement_t*,catch_block_t*,statement_t*); + +struct statement_list_t { + statement_t *head; + statement_t *tail; +}; + +static statement_list_t *new_statement_list(parser_ctx_t*,statement_t*); +static statement_list_t *statement_list_add(statement_list_t*,statement_t*); + +typedef struct _parameter_list_t { + parameter_t *head; + parameter_t *tail; +} parameter_list_t; + +static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*); +static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*); + +static void push_func(parser_ctx_t*); +static inline void pop_func(parser_ctx_t *ctx) +{ + ctx->func_stack = ctx->func_stack->next; +} + +static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*, + source_elements_t*,const WCHAR*,DWORD); +static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*); +static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*); +static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*); +static expression_t *new_array_expression(parser_ctx_t*,expression_t*,expression_t*); +static expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*); +static expression_t *new_new_expression(parser_ctx_t*,expression_t*,argument_list_t*); +static expression_t *new_call_expression(parser_ctx_t*,expression_t*,argument_list_t*); +static expression_t *new_this_expression(parser_ctx_t*); +static expression_t *new_identifier_expression(parser_ctx_t*,const WCHAR*); +static expression_t *new_literal_expression(parser_ctx_t*,literal_t*); +static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int); +static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t*); + +static source_elements_t *new_source_elements(parser_ctx_t*); +static source_elements_t *source_elements_add_statement(source_elements_t*,statement_t*); + +%} + +%pure_parser +%start Program + +%union { + int ival; + const WCHAR *srcptr; + LPCWSTR wstr; + literal_t *literal; + struct _argument_list_t *argument_list; + case_clausule_t *case_clausule; + struct _case_list_t *case_list; + catch_block_t *catch_block; + struct _element_list_t *element_list; + expression_t *expr; + const WCHAR *identifier; + struct _parameter_list_t *parameter_list; + struct _property_list_t *property_list; + source_elements_t *source_elements; + statement_t *statement; + struct _statement_list_t *statement_list; + struct _variable_list_t *variable_list; + variable_declaration_t *variable_declaration; +} + +/* keywords */ +%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kIN +%token kINSTANCEOF kNEW kNULL kUNDEFINED kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH +%token tANDAND tOROR tINC tDEC tHTMLCOMMENT + +%token <srcptr> kFUNCTION '}' + +/* tokens */ +%token <identifier> tIdentifier +%token <ival> tAssignOper tEqOper tShiftOper tRelOper +%token <literal> tNumericLiteral +%token <wstr> tStringLiteral + +%type <source_elements> SourceElements +%type <source_elements> FunctionBody +%type <statement> Statement +%type <statement> Block +%type <statement> VariableStatement +%type <statement> EmptyStatement +%type <statement> ExpressionStatement +%type <statement> IfStatement +%type <statement> IterationStatement +%type <statement> ContinueStatement +%type <statement> BreakStatement +%type <statement> ReturnStatement +%type <statement> WithStatement +%type <statement> LabelledStatement +%type <statement> SwitchStatement +%type <statement> ThrowStatement +%type <statement> TryStatement +%type <statement> Finally +%type <statement_list> StatementList StatementList_opt +%type <parameter_list> FormalParameterList FormalParameterList_opt +%type <expr> Expression Expression_opt Expression_err +%type <expr> ExpressionNoIn ExpressionNoIn_opt +%type <expr> FunctionExpression +%type <expr> AssignmentExpression AssignmentExpressionNoIn +%type <expr> ConditionalExpression ConditionalExpressionNoIn +%type <expr> LeftHandSideExpression +%type <expr> LogicalORExpression LogicalORExpressionNoIn +%type <expr> LogicalANDExpression LogicalANDExpressionNoIn +%type <expr> BitwiseORExpression BitwiseORExpressionNoIn +%type <expr> BitwiseXORExpression BitwiseXORExpressionNoIn +%type <expr> BitwiseANDExpression BitwiseANDExpressionNoIn +%type <expr> EqualityExpression EqualityExpressionNoIn +%type <expr> RelationalExpression RelationalExpressionNoIn +%type <expr> ShiftExpression +%type <expr> AdditiveExpression +%type <expr> MultiplicativeExpression +%type <expr> Initialiser_opt Initialiser +%type <expr> InitialiserNoIn_opt InitialiserNoIn +%type <expr> UnaryExpression +%type <expr> PostfixExpression +%type <expr> NewExpression +%type <expr> CallExpression +%type <expr> MemberExpression +%type <expr> PrimaryExpression +%type <identifier> Identifier_opt +%type <variable_list> VariableDeclarationList +%type <variable_list> VariableDeclarationListNoIn +%type <variable_declaration> VariableDeclaration +%type <variable_declaration> VariableDeclarationNoIn +%type <case_list> CaseClausules CaseClausules_opt +%type <case_clausule> CaseClausule DefaultClausule CaseBlock +%type <catch_block> Catch +%type <argument_list> Arguments +%type <argument_list> ArgumentList +%type <literal> Literal +%type <expr> ArrayLiteral +%type <expr> ObjectLiteral +%type <ival> Elision Elision_opt +%type <element_list> ElementList +%type <property_list> PropertyNameAndValueList +%type <literal> PropertyName +%type <literal> BooleanLiteral +%type <srcptr> KFunction + +%nonassoc LOWER_THAN_ELSE +%nonassoc kELSE + +%% + +/* ECMA-262 3rd Edition 14 */ +Program + : SourceElements HtmlComment + { program_parsed(ctx, $1); } + +HtmlComment + : tHTMLCOMMENT {} + | /* empty */ {} + +/* ECMA-262 3rd Edition 14 */ +SourceElements + : /* empty */ { $$ = new_source_elements(ctx); } + | SourceElements Statement + { $$ = source_elements_add_statement($1, $2); } + +/* ECMA-262 3rd Edition 13 */ +FunctionExpression + : KFunction Identifier_opt left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + { $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); } + +KFunction + : kFUNCTION { push_func(ctx); $$ = $1; } + +/* ECMA-262 3rd Edition 13 */ +FunctionBody + : SourceElements { $$ = function_body_parsed(ctx, $1); } + +/* ECMA-262 3rd Edition 13 */ +FormalParameterList + : tIdentifier { $$ = new_parameter_list(ctx, $1); } + | FormalParameterList ',' tIdentifier + { $$ = parameter_list_add(ctx, $1, $3); } + +/* ECMA-262 3rd Edition 13 */ +FormalParameterList_opt + : /* empty */ { $$ = NULL; } + | FormalParameterList { $$ = $1; } + +/* ECMA-262 3rd Edition 12 */ +Statement + : Block { $$ = $1; } + | VariableStatement { $$ = $1; } + | EmptyStatement { $$ = $1; } + | ExpressionStatement { $$ = $1; } + | IfStatement { $$ = $1; } + | IterationStatement { $$ = $1; } + | ContinueStatement { $$ = $1; } + | BreakStatement { $$ = $1; } + | ReturnStatement { $$ = $1; } + | WithStatement { $$ = $1; } + | LabelledStatement { $$ = $1; } + | SwitchStatement { $$ = $1; } + | ThrowStatement { $$ = $1; } + | TryStatement { $$ = $1; } + +/* ECMA-262 3rd Edition 12.2 */ +StatementList + : Statement { $$ = new_statement_list(ctx, $1); } + | StatementList Statement + { $$ = statement_list_add($1, $2); } + +/* ECMA-262 3rd Edition 12.2 */ +StatementList_opt + : /* empty */ { $$ = NULL; } + | StatementList { $$ = $1; } + +/* ECMA-262 3rd Edition 12.1 */ +Block + : '{' StatementList '}' { $$ = new_block_statement(ctx, $2); } + | '{' '}' { $$ = new_block_statement(ctx, NULL); } + +/* ECMA-262 3rd Edition 12.2 */ +VariableStatement + : kVAR VariableDeclarationList semicolon_opt + { $$ = new_var_statement(ctx, $2); } + +/* ECMA-262 3rd Edition 12.2 */ +VariableDeclarationList + : VariableDeclaration { $$ = new_variable_list(ctx, $1); } + | VariableDeclarationList ',' VariableDeclaration + { $$ = variable_list_add(ctx, $1, $3); } + +/* ECMA-262 3rd Edition 12.2 */ +VariableDeclarationListNoIn + : VariableDeclarationNoIn + { $$ = new_variable_list(ctx, $1); } + | VariableDeclarationListNoIn ',' VariableDeclarationNoIn + { $$ = variable_list_add(ctx, $1, $3); } + +/* ECMA-262 3rd Edition 12.2 */ +VariableDeclaration + : tIdentifier Initialiser_opt + { $$ = new_variable_declaration(ctx, $1, $2); } + +/* ECMA-262 3rd Edition 12.2 */ +VariableDeclarationNoIn + : tIdentifier InitialiserNoIn_opt + { $$ = new_variable_declaration(ctx, $1, $2); } + +/* ECMA-262 3rd Edition 12.2 */ +Initialiser_opt + : /* empty */ { $$ = NULL; } + | Initialiser { $$ = $1; } + +/* ECMA-262 3rd Edition 12.2 */ +Initialiser + : '=' AssignmentExpression + { $$ = $2; } + +/* ECMA-262 3rd Edition 12.2 */ +InitialiserNoIn_opt + : /* empty */ { $$ = NULL; } + | InitialiserNoIn { $$ = $1; } + +/* ECMA-262 3rd Edition 12.2 */ +InitialiserNoIn + : '=' AssignmentExpressionNoIn + { $$ = $2; } + +/* ECMA-262 3rd Edition 12.3 */ +EmptyStatement + : ';' { $$ = new_empty_statement(ctx); } + +/* ECMA-262 3rd Edition 12.4 */ +ExpressionStatement + : Expression semicolon_opt + { $$ = new_expression_statement(ctx, $1); } + +/* ECMA-262 3rd Edition 12.5 */ +IfStatement + : kIF left_bracket Expression_err right_bracket Statement kELSE Statement + { $$ = new_if_statement(ctx, $3, $5, $7); } + | kIF left_bracket Expression_err right_bracket Statement %prec LOWER_THAN_ELSE + { $$ = new_if_statement(ctx, $3, $5, NULL); } + +/* ECMA-262 3rd Edition 12.6 */ +IterationStatement + : kDO Statement kWHILE left_bracket Expression_err right_bracket semicolon_opt + { $$ = new_while_statement(ctx, TRUE, $5, $2); } + | kWHILE left_bracket Expression_err right_bracket Statement + { $$ = new_while_statement(ctx, FALSE, $3, $5); } + | kFOR left_bracket ExpressionNoIn_opt + { if(!explicit_error(ctx, $3, ';')) YYABORT; } + semicolon Expression_opt + { if(!explicit_error(ctx, $6, ';')) YYABORT; } + semicolon Expression_opt right_bracket Statement + { $$ = new_for_statement(ctx, NULL, $3, $6, $9, $11); } + | kFOR left_bracket kVAR VariableDeclarationListNoIn + { if(!explicit_error(ctx, $4, ';')) YYABORT; } + semicolon Expression_opt + { if(!explicit_error(ctx, $7, ';')) YYABORT; } + semicolon Expression_opt right_bracket Statement + { $$ = new_for_statement(ctx, $4, NULL, $7, $10, $12); } + | kFOR left_bracket LeftHandSideExpression kIN Expression_err right_bracket Statement + { $$ = new_forin_statement(ctx, NULL, $3, $5, $7); } + | kFOR left_bracket kVAR VariableDeclarationNoIn kIN Expression_err right_bracket Statement + { $$ = new_forin_statement(ctx, $4, NULL, $6, $8); } + +/* ECMA-262 3rd Edition 12.7 */ +ContinueStatement + : kCONTINUE /* NONL */ Identifier_opt semicolon_opt + { $$ = new_continue_statement(ctx, $2); } + +/* ECMA-262 3rd Edition 12.8 */ +BreakStatement + : kBREAK /* NONL */ Identifier_opt semicolon_opt + { $$ = new_break_statement(ctx, $2); } + +/* ECMA-262 3rd Edition 12.9 */ +ReturnStatement + : kRETURN /* NONL */ Expression_opt semicolon_opt + { $$ = new_return_statement(ctx, $2); } + +/* ECMA-262 3rd Edition 12.10 */ +WithStatement + : kWITH left_bracket Expression right_bracket Statement + { $$ = new_with_statement(ctx, $3, $5); } + +/* ECMA-262 3rd Edition 12.12 */ +LabelledStatement + : tIdentifier ':' Statement + { $$ = new_labelled_statement(ctx, $1, $3); } + +/* ECMA-262 3rd Edition 12.11 */ +SwitchStatement + : kSWITCH left_bracket Expression right_bracket CaseBlock + { $$ = new_switch_statement(ctx, $3, $5); } + +/* ECMA-262 3rd Edition 12.11 */ +CaseBlock + : '{' CaseClausules_opt '}' + { $$ = new_case_block(ctx, $2, NULL, NULL); } + | '{' CaseClausules_opt DefaultClausule CaseClausules_opt '}' + { $$ = new_case_block(ctx, $2, $3, $4); } + +/* ECMA-262 3rd Edition 12.11 */ +CaseClausules_opt + : /* empty */ { $$ = NULL; } + | CaseClausules { $$ = $1; } + +/* ECMA-262 3rd Edition 12.11 */ +CaseClausules + : CaseClausule { $$ = new_case_list(ctx, $1); } + | CaseClausules CaseClausule + { $$ = case_list_add(ctx, $1, $2); } + +/* ECMA-262 3rd Edition 12.11 */ +CaseClausule + : kCASE Expression ':' StatementList_opt + { $$ = new_case_clausule(ctx, $2, $4); } + +/* ECMA-262 3rd Edition 12.11 */ +DefaultClausule + : kDEFAULT ':' StatementList_opt + { $$ = new_case_clausule(ctx, NULL, $3); } + +/* ECMA-262 3rd Edition 12.13 */ +ThrowStatement + : kTHROW /* NONL */ Expression semicolon_opt + { $$ = new_throw_statement(ctx, $2); } + +/* ECMA-262 3rd Edition 12.14 */ +TryStatement + : kTRY Block Catch { $$ = new_try_statement(ctx, $2, $3, NULL); } + | kTRY Block Finally { $$ = new_try_statement(ctx, $2, NULL, $3); } + | kTRY Block Catch Finally + { $$ = new_try_statement(ctx, $2, $3, $4); } + +/* ECMA-262 3rd Edition 12.14 */ +Catch + : kCATCH left_bracket tIdentifier right_bracket Block + { $$ = new_catch_block(ctx, $3, $5); } + +/* ECMA-262 3rd Edition 12.14 */ +Finally + : kFINALLY Block { $$ = $2; } + +/* ECMA-262 3rd Edition 11.14 */ +Expression_opt + : /* empty */ { $$ = NULL; } + | Expression { $$ = $1; } + +Expression_err + : Expression { $$ = $1; } + | error { set_error(ctx, IDS_SYNTAX_ERROR); YYABORT; } + +/* ECMA-262 3rd Edition 11.14 */ +Expression + : AssignmentExpression { $$ = $1; } + | Expression ',' AssignmentExpression + { $$ = new_binary_expression(ctx, EXPR_COMMA, $1, $3); } + +/* ECMA-262 3rd Edition 11.14 */ +ExpressionNoIn_opt + : /* empty */ { $$ = NULL; } + | ExpressionNoIn { $$ = $1; } + +/* ECMA-262 3rd Edition 11.14 */ +ExpressionNoIn + : AssignmentExpressionNoIn + { $$ = $1; } + | ExpressionNoIn ',' AssignmentExpressionNoIn + { $$ = new_binary_expression(ctx, EXPR_COMMA, $1, $3); } + +/* ECMA-262 3rd Edition 11.13 */ +AssignmentExpression + : ConditionalExpression { $$ = $1; } + | LeftHandSideExpression '=' AssignmentExpression + { $$ = new_binary_expression(ctx, EXPR_ASSIGN, $1, $3); } + | LeftHandSideExpression tAssignOper AssignmentExpression + { $$ = new_binary_expression(ctx, $2, $1, $3); } + +/* ECMA-262 3rd Edition 11.13 */ +AssignmentExpressionNoIn + : ConditionalExpressionNoIn + { $$ = $1; } + | LeftHandSideExpression '=' AssignmentExpressionNoIn + { $$ = new_binary_expression(ctx, EXPR_ASSIGN, $1, $3); } + | LeftHandSideExpression tAssignOper AssignmentExpressionNoIn + { $$ = new_binary_expression(ctx, $2, $1, $3); } + +/* ECMA-262 3rd Edition 11.12 */ +ConditionalExpression + : LogicalORExpression { $$ = $1; } + | LogicalORExpression '?' AssignmentExpression ':' AssignmentExpression + { $$ = new_conditional_expression(ctx, $1, $3, $5); } + +/* ECMA-262 3rd Edition 11.12 */ +ConditionalExpressionNoIn + : LogicalORExpressionNoIn + { $$ = $1; } + | LogicalORExpressionNoIn '?' AssignmentExpressionNoIn ':' AssignmentExpressionNoIn + { $$ = new_conditional_expression(ctx, $1, $3, $5); } + +/* ECMA-262 3rd Edition 11.11 */ +LogicalORExpression + : LogicalANDExpression { $$ = $1; } + | LogicalORExpression tOROR LogicalANDExpression + { $$ = new_binary_expression(ctx, EXPR_OR, $1, $3); } + +/* ECMA-262 3rd Edition 11.11 */ +LogicalORExpressionNoIn + : LogicalANDExpressionNoIn + { $$ = $1; } + | LogicalORExpressionNoIn tOROR LogicalANDExpressionNoIn + { $$ = new_binary_expression(ctx, EXPR_OR, $1, $3); } + +/* ECMA-262 3rd Edition 11.11 */ +LogicalANDExpression + : BitwiseORExpression { $$ = $1; } + | LogicalANDExpression tANDAND BitwiseORExpression + { $$ = new_binary_expression(ctx, EXPR_AND, $1, $3); } + +/* ECMA-262 3rd Edition 11.11 */ +LogicalANDExpressionNoIn + : BitwiseORExpressionNoIn + { $$ = $1; } + | LogicalANDExpressionNoIn tANDAND BitwiseORExpressionNoIn + { $$ = new_binary_expression(ctx, EXPR_AND, $1, $3); } + +/* ECMA-262 3rd Edition 11.10 */ +BitwiseORExpression + : BitwiseXORExpression { $$ = $1; } + | BitwiseORExpression '|' BitwiseXORExpression + { $$ = new_binary_expression(ctx, EXPR_BOR, $1, $3); } + +/* ECMA-262 3rd Edition 11.10 */ +BitwiseORExpressionNoIn + : BitwiseXORExpressionNoIn + { $$ = $1; } + | BitwiseORExpressionNoIn '|' BitwiseXORExpressionNoIn + { $$ = new_binary_expression(ctx, EXPR_BOR, $1, $3); } + +/* ECMA-262 3rd Edition 11.10 */ +BitwiseXORExpression + : BitwiseANDExpression { $$ = $1; } + | BitwiseXORExpression '^' BitwiseANDExpression + { $$ = new_binary_expression(ctx, EXPR_BXOR, $1, $3); } + +/* ECMA-262 3rd Edition 11.10 */ +BitwiseXORExpressionNoIn + : BitwiseANDExpressionNoIn + { $$ = $1; } + | BitwiseXORExpressionNoIn '^' BitwiseANDExpressionNoIn + { $$ = new_binary_expression(ctx, EXPR_BXOR, $1, $3); } + +/* ECMA-262 3rd Edition 11.10 */ +BitwiseANDExpression + : EqualityExpression { $$ = $1; } + | BitwiseANDExpression '&' EqualityExpression + { $$ = new_binary_expression(ctx, EXPR_BAND, $1, $3); } + +/* ECMA-262 3rd Edition 11.10 */ +BitwiseANDExpressionNoIn + : EqualityExpressionNoIn + { $$ = $1; } + | BitwiseANDExpressionNoIn '&' EqualityExpressionNoIn + { $$ = new_binary_expression(ctx, EXPR_BAND, $1, $3); } + +/* ECMA-262 3rd Edition 11.9 */ +EqualityExpression + : RelationalExpression { $$ = $1; } + | EqualityExpression tEqOper RelationalExpression + { $$ = new_binary_expression(ctx, $2, $1, $3); } + +/* ECMA-262 3rd Edition 11.9 */ +EqualityExpressionNoIn + : RelationalExpressionNoIn { $$ = $1; } + | EqualityExpressionNoIn tEqOper RelationalExpressionNoIn + { $$ = new_binary_expression(ctx, $2, $1, $3); } + +/* ECMA-262 3rd Edition 11.8 */ +RelationalExpression + : ShiftExpression { $$ = $1; } + | RelationalExpression tRelOper ShiftExpression + { $$ = new_binary_expression(ctx, $2, $1, $3); } + | RelationalExpression kINSTANCEOF ShiftExpression + { $$ = new_binary_expression(ctx, EXPR_INSTANCEOF, $1, $3); } + | RelationalExpression kIN ShiftExpression + { $$ = new_binary_expression(ctx, EXPR_IN, $1, $3); } + +/* ECMA-262 3rd Edition 11.8 */ +RelationalExpressionNoIn + : ShiftExpression { $$ = $1; } + | RelationalExpressionNoIn tRelOper ShiftExpression + { $$ = new_binary_expression(ctx, $2, $1, $3); } + | RelationalExpressionNoIn kINSTANCEOF ShiftExpression + { $$ = new_binary_expression(ctx, EXPR_INSTANCEOF, $1, $3); } + +/* ECMA-262 3rd Edition 11.7 */ +ShiftExpression + : AdditiveExpression { $$ = $1; } + | ShiftExpression tShiftOper AdditiveExpression + { $$ = new_binary_expression(ctx, $2, $1, $3); } + +/* ECMA-262 3rd Edition 11.6 */ +AdditiveExpression + : MultiplicativeExpression + { $$ = $1; } + | AdditiveExpression '+' MultiplicativeExpression + { $$ = new_binary_expression(ctx, EXPR_ADD, $1, $3); } + | AdditiveExpression '-' MultiplicativeExpression + { $$ = new_binary_expression(ctx, EXPR_SUB, $1, $3); } + +/* ECMA-262 3rd Edition 11.5 */ +MultiplicativeExpression + : UnaryExpression { $$ = $1; } + | MultiplicativeExpression '*' UnaryExpression + { $$ = new_binary_expression(ctx, EXPR_MUL, $1, $3); } + | MultiplicativeExpression '/' UnaryExpression + { $$ = new_binary_expression(ctx, EXPR_DIV, $1, $3); } + | MultiplicativeExpression '%' UnaryExpression + { $$ = new_binary_expression(ctx, EXPR_MOD, $1, $3); } + +/* ECMA-262 3rd Edition 11.4 */ +UnaryExpression + : PostfixExpression { $$ = $1; } + | kDELETE UnaryExpression + { $$ = new_unary_expression(ctx, EXPR_DELETE, $2); } + | kVOID UnaryExpression { $$ = new_unary_expression(ctx, EXPR_VOID, $2); } + | kTYPEOF UnaryExpression + { $$ = new_unary_expression(ctx, EXPR_TYPEOF, $2); } + | tINC UnaryExpression { $$ = new_unary_expression(ctx, EXPR_PREINC, $2); } + | tDEC UnaryExpression { $$ = new_unary_expression(ctx, EXPR_PREDEC, $2); } + | '+' UnaryExpression { $$ = new_unary_expression(ctx, EXPR_PLUS, $2); } + | '-' UnaryExpression { $$ = new_unary_expression(ctx, EXPR_MINUS, $2); } + | '~' UnaryExpression { $$ = new_unary_expression(ctx, EXPR_BITNEG, $2); } + | '!' UnaryExpression { $$ = new_unary_expression(ctx, EXPR_LOGNEG, $2); } + +/* ECMA-262 3rd Edition 11.2 */ +PostfixExpression + : LeftHandSideExpression + { $$ = $1; } + | LeftHandSideExpression /* NONL */ tINC + { $$ = new_unary_expression(ctx, EXPR_POSTINC, $1); } + | LeftHandSideExpression /* NONL */ tDEC + { $$ = new_unary_expression(ctx, EXPR_POSTDEC, $1); } + + +/* ECMA-262 3rd Edition 11.2 */ +LeftHandSideExpression + : NewExpression { $$ = $1; } + | CallExpression { $$ = $1; } + +/* ECMA-262 3rd Edition 11.2 */ +NewExpression + : MemberExpression { $$ = $1; } + | kNEW NewExpression { $$ = new_new_expression(ctx, $2, NULL); } + +/* ECMA-262 3rd Edition 11.2 */ +MemberExpression + : PrimaryExpression { $$ = $1; } + | FunctionExpression { $$ = $1; } + | MemberExpression '[' Expression ']' + { $$ = new_array_expression(ctx, $1, $3); } + | MemberExpression '.' tIdentifier + { $$ = new_member_expression(ctx, $1, $3); } + | kNEW MemberExpression Arguments + { $$ = new_new_expression(ctx, $2, $3); } + +/* ECMA-262 3rd Edition 11.2 */ +CallExpression + : MemberExpression Arguments + { $$ = new_call_expression(ctx, $1, $2); } + | CallExpression Arguments + { $$ = new_call_expression(ctx, $1, $2); } + | CallExpression '[' Expression ']' + { $$ = new_array_expression(ctx, $1, $3); } + | CallExpression '.' tIdentifier + { $$ = new_member_expression(ctx, $1, $3); } + +/* ECMA-262 3rd Edition 11.2 */ +Arguments + : '(' ')' { $$ = NULL; } + | '(' ArgumentList ')' { $$ = $2; } + +/* ECMA-262 3rd Edition 11.2 */ +ArgumentList + : AssignmentExpression { $$ = new_argument_list(ctx, $1); } + | ArgumentList ',' AssignmentExpression + { $$ = argument_list_add(ctx, $1, $3); } + +/* ECMA-262 3rd Edition 11.1 */ +PrimaryExpression + : kTHIS { $$ = new_this_expression(ctx); } + | tIdentifier { $$ = new_identifier_expression(ctx, $1); } + | Literal { $$ = new_literal_expression(ctx, $1); } + | ArrayLiteral { $$ = $1; } + | ObjectLiteral { $$ = $1; } + | '(' Expression ')' { $$ = $2; } + +/* ECMA-262 3rd Edition 11.1.4 */ +ArrayLiteral + : '[' ']' { $$ = new_array_literal_expression(ctx, NULL, 0); } + | '[' Elision ']' { $$ = new_array_literal_expression(ctx, NULL, $2+1); } + | '[' ElementList ']' { $$ = new_array_literal_expression(ctx, $2, 0); } + | '[' ElementList ',' Elision_opt ']' + { $$ = new_array_literal_expression(ctx, $2, $4+1); } + +/* ECMA-262 3rd Edition 11.1.4 */ +ElementList + : Elision_opt AssignmentExpression + { $$ = new_element_list(ctx, $1, $2); } + | ElementList ',' Elision_opt AssignmentExpression + { $$ = element_list_add(ctx, $1, $3, $4); } + +/* ECMA-262 3rd Edition 11.1.4 */ +Elision + : ',' { $$ = 1; } + | Elision ',' { $$ = $1 + 1; } + +/* ECMA-262 3rd Edition 11.1.4 */ +Elision_opt + : /* empty */ { $$ = 0; } + | Elision { $$ = $1; } + +/* ECMA-262 3rd Edition 11.1.5 */ +ObjectLiteral + : '{' '}' { $$ = new_prop_and_value_expression(ctx, NULL); } + | '{' PropertyNameAndValueList '}' + { $$ = new_prop_and_value_expression(ctx, $2); } + +/* ECMA-262 3rd Edition 11.1.5 */ +PropertyNameAndValueList + : PropertyName ':' AssignmentExpression + { $$ = new_property_list(ctx, $1, $3); } + | PropertyNameAndValueList ',' PropertyName ':' AssignmentExpression + { $$ = property_list_add(ctx, $1, $3, $5); } + +/* ECMA-262 3rd Edition 11.1.5 */ +PropertyName + : tIdentifier { $$ = new_string_literal(ctx, $1); } + | tStringLiteral { $$ = new_string_literal(ctx, $1); } + | tNumericLiteral { $$ = $1; } + +/* ECMA-262 3rd Edition 7.6 */ +Identifier_opt + : /* empty*/ { $$ = NULL; } + | tIdentifier { $$ = $1; } + +/* ECMA-262 3rd Edition 7.8 */ +Literal + : kNULL { $$ = new_null_literal(ctx); } + | kUNDEFINED { $$ = new_undefined_literal(ctx); } + | BooleanLiteral { $$ = $1; } + | tNumericLiteral { $$ = $1; } + | tStringLiteral { $$ = new_string_literal(ctx, $1); } + | '/' { $$ = parse_regexp(ctx); + if(!$$) YYABORT; } + +/* ECMA-262 3rd Edition 7.8.2 */ +BooleanLiteral + : kTRUE { $$ = new_boolean_literal(ctx, TRUE); } + | kFALSE { $$ = new_boolean_literal(ctx, FALSE); } + +semicolon_opt + : ';' + | error { if(!allow_auto_semicolon(ctx)) {YYABORT;} } + +left_bracket + : '(' + | error { set_error(ctx, IDS_LBRACKET); YYABORT; } + +right_bracket + : ')' + | error { set_error(ctx, IDS_RBRACKET); YYABORT; } + +semicolon + : ';' + | error { set_error(ctx, IDS_SEMICOLON); YYABORT; } + +%% + +static BOOL allow_auto_semicolon(parser_ctx_t *ctx) +{ + return ctx->nl || ctx->ptr == ctx->end || *(ctx->ptr-1) == '}'; +} + +static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str) +{ + literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); + + ret->vt = VT_BSTR; + ret->u.wstr = str; + + return ret; +} + +static literal_t *new_null_literal(parser_ctx_t *ctx) +{ + literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); + + ret->vt = VT_NULL; + + return ret; +} + +static literal_t *new_undefined_literal(parser_ctx_t *ctx) +{ + literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); + + ret->vt = VT_EMPTY; + + return ret; +} + +static literal_t *new_boolean_literal(parser_ctx_t *ctx, VARIANT_BOOL bval) +{ + literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); + + ret->vt = VT_BOOL; + ret->u.bval = bval; + + return ret; +} + +static prop_val_t *new_prop_val(parser_ctx_t *ctx, literal_t *name, expression_t *value) +{ + prop_val_t *ret = parser_alloc(ctx, sizeof(prop_val_t)); + + ret->name = name; + ret->value = value; + ret->next = NULL; + + return ret; +} + +static property_list_t *new_property_list(parser_ctx_t *ctx, literal_t *name, expression_t *value) +{ + property_list_t *ret = parser_alloc_tmp(ctx, sizeof(property_list_t)); + + ret->head = ret->tail = new_prop_val(ctx, name, value); + + return ret; +} + +static property_list_t *property_list_add(parser_ctx_t *ctx, property_list_t *list, literal_t *name, expression_t *value) +{ + list->tail = list->tail->next = new_prop_val(ctx, name, value); + + return list; +} + +static array_element_t *new_array_element(parser_ctx_t *ctx, int elision, expression_t *expr) +{ + array_element_t *ret = parser_alloc(ctx, sizeof(array_element_t)); + + ret->elision = elision; + ret->expr = expr; + ret->next = NULL; + + return ret; +} + +static element_list_t *new_element_list(parser_ctx_t *ctx, int elision, expression_t *expr) +{ + element_list_t *ret = parser_alloc_tmp(ctx, sizeof(element_list_t)); + + ret->head = ret->tail = new_array_element(ctx, elision, expr); + + return ret; +} + +static element_list_t *element_list_add(parser_ctx_t *ctx, element_list_t *list, int elision, expression_t *expr) +{ + list->tail = list->tail->next = new_array_element(ctx, elision, expr); + + return list; +} + +static argument_t *new_argument(parser_ctx_t *ctx, expression_t *expr) +{ + argument_t *ret = parser_alloc(ctx, sizeof(argument_t)); + + ret->expr = expr; + ret->next = NULL; + + return ret; +} + +static argument_list_t *new_argument_list(parser_ctx_t *ctx, expression_t *expr) +{ + argument_list_t *ret = parser_alloc_tmp(ctx, sizeof(argument_list_t)); + + ret->head = ret->tail = new_argument(ctx, expr); + + return ret; +} + +static argument_list_t *argument_list_add(parser_ctx_t *ctx, argument_list_t *list, expression_t *expr) +{ + list->tail = list->tail->next = new_argument(ctx, expr); + + return list; +} + +static catch_block_t *new_catch_block(parser_ctx_t *ctx, const WCHAR *identifier, statement_t *statement) +{ + catch_block_t *ret = parser_alloc(ctx, sizeof(catch_block_t)); + + ret->identifier = identifier; + ret->statement = statement; + + return ret; +} + +static case_clausule_t *new_case_clausule(parser_ctx_t *ctx, expression_t *expr, statement_list_t *stat_list) +{ + case_clausule_t *ret = parser_alloc(ctx, sizeof(case_clausule_t)); + + ret->expr = expr; + ret->stat = stat_list ? stat_list->head : NULL; + ret->next = NULL; + + return ret; +} + +static case_list_t *new_case_list(parser_ctx_t *ctx, case_clausule_t *case_clausule) +{ + case_list_t *ret = parser_alloc_tmp(ctx, sizeof(case_list_t)); + + ret->head = ret->tail = case_clausule; + + return ret; +} + +static case_list_t *case_list_add(parser_ctx_t *ctx, case_list_t *list, case_clausule_t *case_clausule) +{ + list->tail = list->tail->next = case_clausule; + + return list; +} + +static case_clausule_t *new_case_block(parser_ctx_t *ctx, case_list_t *case_list1, + case_clausule_t *default_clausule, case_list_t *case_list2) +{ + case_clausule_t *ret = NULL, *iter = NULL, *iter2; + statement_t *stat = NULL; + + if(case_list1) { + ret = case_list1->head; + iter = case_list1->tail; + } + + if(default_clausule) { + if(ret) + iter = iter->next = default_clausule; + else + ret = iter = default_clausule; + } + + if(case_list2) { + if(ret) + iter->next = case_list2->head; + else + ret = case_list2->head; + } + + if(!ret) + return NULL; + + for(iter = ret; iter; iter = iter->next) { + for(iter2 = iter; iter2 && !iter2->stat; iter2 = iter2->next); + if(!iter2) + break; + + while(iter != iter2) { + iter->stat = iter2->stat; + iter = iter->next; + } + + if(stat) { + while(stat->next) + stat = stat->next; + stat->next = iter->stat; + }else { + stat = iter->stat; + } + } + + return ret; +} + +static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *list) +{ + block_statement_t *ret = parser_alloc(ctx, sizeof(block_statement_t)); + + ret->stat.eval = block_statement_eval; + ret->stat.next = NULL; + ret->stat_list = list ? list->head : NULL; + + return &ret->stat; +} + +static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr) +{ + variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t)); + var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t)); + + ret->identifier = identifier; + ret->expr = expr; + ret->next = NULL; + + var_list->identifier = identifier; + var_list->next = NULL; + + if(ctx->func_stack->var_tail) + ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list; + else + ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list; + + return ret; +} + +static variable_list_t *new_variable_list(parser_ctx_t *ctx, variable_declaration_t *decl) +{ + variable_list_t *ret = parser_alloc_tmp(ctx, sizeof(variable_list_t)); + + ret->head = ret->tail = decl; + + return ret; +} + +static variable_list_t *variable_list_add(parser_ctx_t *ctx, variable_list_t *list, variable_declaration_t *decl) +{ + list->tail = list->tail->next = decl; + + return list; +} + +static statement_t *new_var_statement(parser_ctx_t *ctx, variable_list_t *variable_list) +{ + var_statement_t *ret = parser_alloc(ctx, sizeof(var_statement_t)); + + ret->stat.eval = var_statement_eval; + ret->stat.next = NULL; + ret->variable_list = variable_list->head; + + return &ret->stat; +} + +static statement_t *new_empty_statement(parser_ctx_t *ctx) +{ + statement_t *ret = parser_alloc(ctx, sizeof(statement_t)); + + ret->eval = empty_statement_eval; + ret->next = NULL; + + return ret; +} + +static statement_t *new_expression_statement(parser_ctx_t *ctx, expression_t *expr) +{ + expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + + ret->stat.eval = expression_statement_eval; + ret->stat.next = NULL; + ret->expr = expr; + + return &ret->stat; +} + +static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *if_stat, statement_t *else_stat) +{ + if_statement_t *ret = parser_alloc(ctx, sizeof(if_statement_t)); + + ret->stat.eval = if_statement_eval; + ret->stat.next = NULL; + ret->expr = expr; + ret->if_stat = if_stat; + ret->else_stat = else_stat; + + return &ret->stat; +} + +static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, expression_t *expr, statement_t *stat) +{ + while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t)); + + ret->stat.eval = while_statement_eval; + ret->stat.next = NULL; + ret->do_while = dowhile; + ret->expr = expr; + ret->statement = stat; + + return &ret->stat; +} + +static statement_t *new_for_statement(parser_ctx_t *ctx, variable_list_t *variable_list, expression_t *begin_expr, + expression_t *expr, expression_t *end_expr, statement_t *statement) +{ + for_statement_t *ret = parser_alloc(ctx, sizeof(for_statement_t)); + + ret->stat.eval = for_statement_eval; + ret->stat.next = NULL; + ret->variable_list = variable_list ? variable_list->head : NULL; + ret->begin_expr = begin_expr; + ret->expr = expr; + ret->end_expr = end_expr; + ret->statement = statement; + + return &ret->stat; +} + +static statement_t *new_forin_statement(parser_ctx_t *ctx, variable_declaration_t *variable, expression_t *expr, + expression_t *in_expr, statement_t *statement) +{ + forin_statement_t *ret = parser_alloc(ctx, sizeof(forin_statement_t)); + + ret->stat.eval = forin_statement_eval; + ret->stat.next = NULL; + ret->variable = variable; + ret->expr = expr; + ret->in_expr = in_expr; + ret->statement = statement; + + return &ret->stat; +} + +static statement_t *new_continue_statement(parser_ctx_t *ctx, const WCHAR *identifier) +{ + branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t)); + + ret->stat.eval = continue_statement_eval; + ret->stat.next = NULL; + ret->identifier = identifier; + + return &ret->stat; +} + +static statement_t *new_break_statement(parser_ctx_t *ctx, const WCHAR *identifier) +{ + branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t)); + + ret->stat.eval = break_statement_eval; + ret->stat.next = NULL; + ret->identifier = identifier; + + return &ret->stat; +} + +static statement_t *new_return_statement(parser_ctx_t *ctx, expression_t *expr) +{ + expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + + ret->stat.eval = return_statement_eval; + ret->stat.next = NULL; + ret->expr = expr; + + return &ret->stat; +} + +static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *statement) +{ + with_statement_t *ret = parser_alloc(ctx, sizeof(with_statement_t)); + + ret->stat.eval = with_statement_eval; + ret->stat.next = NULL; + ret->expr = expr; + ret->statement = statement; + + return &ret->stat; +} + +static statement_t *new_labelled_statement(parser_ctx_t *ctx, const WCHAR *identifier, statement_t *statement) +{ + labelled_statement_t *ret = parser_alloc(ctx, sizeof(labelled_statement_t)); + + ret->stat.eval = labelled_statement_eval; + ret->stat.next = NULL; + ret->identifier = identifier; + ret->statement = statement; + + return &ret->stat; +} + +static statement_t *new_switch_statement(parser_ctx_t *ctx, expression_t *expr, case_clausule_t *case_list) +{ + switch_statement_t *ret = parser_alloc(ctx, sizeof(switch_statement_t)); + + ret->stat.eval = switch_statement_eval; + ret->stat.next = NULL; + ret->expr = expr; + ret->case_list = case_list; + + return &ret->stat; +} + +static statement_t *new_throw_statement(parser_ctx_t *ctx, expression_t *expr) +{ + expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t)); + + ret->stat.eval = throw_statement_eval; + ret->stat.next = NULL; + ret->expr = expr; + + return &ret->stat; +} + +static statement_t *new_try_statement(parser_ctx_t *ctx, statement_t *try_statement, + catch_block_t *catch_block, statement_t *finally_statement) +{ + try_statement_t *ret = parser_alloc(ctx, sizeof(try_statement_t)); + + ret->stat.eval = try_statement_eval; + ret->stat.next = NULL; + ret->try_statement = try_statement; + ret->catch_block = catch_block; + ret->finally_statement = finally_statement; + + return &ret->stat; +} + +static parameter_t *new_parameter(parser_ctx_t *ctx, const WCHAR *identifier) +{ + parameter_t *ret = parser_alloc(ctx, sizeof(parameter_t)); + + ret->identifier = identifier; + ret->next = NULL; + + return ret; +} + +static parameter_list_t *new_parameter_list(parser_ctx_t *ctx, const WCHAR *identifier) +{ + parameter_list_t *ret = parser_alloc_tmp(ctx, sizeof(parameter_list_t)); + + ret->head = ret->tail = new_parameter(ctx, identifier); + + return ret; +} + +static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t *list, const WCHAR *identifier) +{ + list->tail = list->tail->next = new_parameter(ctx, identifier); + + return list; +} + +static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, + parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len) +{ + function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t)); + + ret->expr.eval = function_expression_eval; + ret->identifier = identifier; + ret->parameter_list = parameter_list ? parameter_list->head : NULL; + ret->source_elements = source_elements; + ret->src_str = src_str; + ret->src_len = src_len; + + if(ret->identifier) { + function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t)); + + decl->expr = ret; + decl->next = NULL; + + if(ctx->func_stack->func_tail) + ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl; + else + ctx->func_stack->func_head = ctx->func_stack->func_tail = decl; + } + + return &ret->expr; +} + +static const expression_eval_t expression_eval_table[] = { + comma_expression_eval, + logical_or_expression_eval, + logical_and_expression_eval, + binary_or_expression_eval, + binary_xor_expression_eval, + binary_and_expression_eval, + instanceof_expression_eval, + in_expression_eval, + add_expression_eval, + sub_expression_eval, + mul_expression_eval, + div_expression_eval, + mod_expression_eval, + delete_expression_eval, + void_expression_eval, + typeof_expression_eval, + minus_expression_eval, + plus_expression_eval, + post_increment_expression_eval, + post_decrement_expression_eval, + pre_increment_expression_eval, + pre_decrement_expression_eval, + equal_expression_eval, + equal2_expression_eval, + not_equal_expression_eval, + not_equal2_expression_eval, + less_expression_eval, + lesseq_expression_eval, + greater_expression_eval, + greatereq_expression_eval, + binary_negation_expression_eval, + logical_negation_expression_eval, + left_shift_expression_eval, + right_shift_expression_eval, + right2_shift_expression_eval, + assign_expression_eval, + assign_lshift_expression_eval, + assign_rshift_expression_eval, + assign_rrshift_expression_eval, + assign_add_expression_eval, + assign_sub_expression_eval, + assign_mul_expression_eval, + assign_div_expression_eval, + assign_mod_expression_eval, + assign_and_expression_eval, + assign_or_expression_eval, + assign_xor_expression_eval, +}; + +static expression_t *new_binary_expression(parser_ctx_t *ctx, expression_type_t type, + expression_t *expression1, expression_t *expression2) +{ + binary_expression_t *ret = parser_alloc(ctx, sizeof(binary_expression_t)); + + ret->expr.eval = expression_eval_table[type]; + ret->expression1 = expression1; + ret->expression2 = expression2; + + return &ret->expr; +} + +static expression_t *new_unary_expression(parser_ctx_t *ctx, expression_type_t type, expression_t *expression) +{ + unary_expression_t *ret = parser_alloc(ctx, sizeof(unary_expression_t)); + + ret->expr.eval = expression_eval_table[type]; + ret->expression = expression; + + return &ret->expr; +} + +static expression_t *new_conditional_expression(parser_ctx_t *ctx, expression_t *expression, + expression_t *true_expression, expression_t *false_expression) +{ + conditional_expression_t *ret = parser_alloc(ctx, sizeof(conditional_expression_t)); + + ret->expr.eval = conditional_expression_eval; + ret->expression = expression; + ret->true_expression = true_expression; + ret->false_expression = false_expression; + + return &ret->expr; +} + +static expression_t *new_array_expression(parser_ctx_t *ctx, expression_t *member_expr, expression_t *expression) +{ + array_expression_t *ret = parser_alloc(ctx, sizeof(array_expression_t)); + + ret->expr.eval = array_expression_eval; + ret->member_expr = member_expr; + ret->expression = expression; + + return &ret->expr; +} + +static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expression, const WCHAR *identifier) +{ + member_expression_t *ret = parser_alloc(ctx, sizeof(member_expression_t)); + + ret->expr.eval = member_expression_eval; + ret->expression = expression; + ret->identifier = identifier; + + return &ret->expr; +} + +static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list) +{ + call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t)); + + ret->expr.eval = new_expression_eval; + ret->expression = expression; + ret->argument_list = argument_list ? argument_list->head : NULL; + + return &ret->expr; +} + +static expression_t *new_call_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list) +{ + call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t)); + + ret->expr.eval = call_expression_eval; + ret->expression = expression; + ret->argument_list = argument_list ? argument_list->head : NULL; + + return &ret->expr; +} + +static expression_t *new_this_expression(parser_ctx_t *ctx) +{ + expression_t *ret = parser_alloc(ctx, sizeof(expression_t)); + + ret->eval = this_expression_eval; + + return ret; +} + +static int parser_error(const char *str) +{ + return 0; +} + +static void set_error(parser_ctx_t *ctx, UINT error) +{ + ctx->hres = JSCRIPT_ERROR|error; +} + +static BOOL explicit_error(parser_ctx_t *ctx, void *obj, WCHAR next) +{ + if(obj || *(ctx->ptr-1)==next) return TRUE; + + set_error(ctx, IDS_SYNTAX_ERROR); + return FALSE; +} + + +static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *identifier) +{ + identifier_expression_t *ret = parser_alloc(ctx, sizeof(identifier_expression_t)); + + ret->expr.eval = identifier_expression_eval; + ret->identifier = identifier; + + return &ret->expr; +} + +static expression_t *new_array_literal_expression(parser_ctx_t *ctx, element_list_t *element_list, int length) +{ + array_literal_expression_t *ret = parser_alloc(ctx, sizeof(array_literal_expression_t)); + + ret->expr.eval = array_literal_expression_eval; + ret->element_list = element_list ? element_list->head : NULL; + ret->length = length; + + return &ret->expr; +} + +static expression_t *new_prop_and_value_expression(parser_ctx_t *ctx, property_list_t *property_list) +{ + property_value_expression_t *ret = parser_alloc(ctx, sizeof(property_value_expression_t)); + + ret->expr.eval = property_value_expression_eval; + ret->property_list = property_list ? property_list->head : NULL; + + return &ret->expr; +} + +static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *literal) +{ + literal_expression_t *ret = parser_alloc(ctx, sizeof(literal_expression_t)); + + ret->expr.eval = literal_expression_eval; + ret->literal = literal; + + return &ret->expr; +} + +static source_elements_t *new_source_elements(parser_ctx_t *ctx) +{ + source_elements_t *ret = parser_alloc(ctx, sizeof(source_elements_t)); + + memset(ret, 0, sizeof(*ret)); + + return ret; +} + +static source_elements_t *source_elements_add_statement(source_elements_t *source_elements, statement_t *statement) +{ + if(source_elements->statement_tail) + source_elements->statement_tail = source_elements->statement_tail->next = statement; + else + source_elements->statement = source_elements->statement_tail = statement; + + return source_elements; +} + +static statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement) +{ + statement_list_t *ret = parser_alloc_tmp(ctx, sizeof(statement_list_t)); + + ret->head = ret->tail = statement; + + return ret; +} + +static statement_list_t *statement_list_add(statement_list_t *list, statement_t *statement) +{ + list->tail = list->tail->next = statement; + + return list; +} + +static void push_func(parser_ctx_t *ctx) +{ + func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t)); + + new_func->func_head = new_func->func_tail = NULL; + new_func->var_head = new_func->var_tail = NULL; + + new_func->next = ctx->func_stack; + ctx->func_stack = new_func; +} + +static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source) +{ + source->functions = ctx->func_stack->func_head; + source->variables = ctx->func_stack->var_head; + pop_func(ctx); + + return source; +} + +static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) +{ + source->functions = ctx->func_stack->func_head; + source->variables = ctx->func_stack->var_head; + pop_func(ctx); + + ctx->source = source; + if(!ctx->lexer_error) + ctx->hres = S_OK; +} + +void parser_release(parser_ctx_t *ctx) +{ + obj_literal_t *iter; + + if(--ctx->ref) + return; + + for(iter = ctx->obj_literals; iter; iter = iter->next) + jsdisp_release(iter->obj); + + jsheap_free(&ctx->heap); + heap_free(ctx); +} + +HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, + parser_ctx_t **ret) +{ + parser_ctx_t *parser_ctx; + jsheap_t *mark; + HRESULT hres; + + const WCHAR html_tagW[] = {'<','/','s','c','r','i','p','t','>',0}; + + parser_ctx = heap_alloc_zero(sizeof(parser_ctx_t)); + if(!parser_ctx) + return E_OUTOFMEMORY; + + parser_ctx->ref = 1; + parser_ctx->hres = JSCRIPT_ERROR|IDS_SYNTAX_ERROR; + parser_ctx->is_html = delimiter && !strcmpiW(delimiter, html_tagW); + + parser_ctx->begin = parser_ctx->ptr = code; + parser_ctx->end = code + strlenW(code); + + script_addref(ctx); + parser_ctx->script = ctx; + + mark = jsheap_mark(&ctx->tmp_heap); + jsheap_init(&parser_ctx->heap); + + push_func(parser_ctx); + + parser_parse(parser_ctx); + jsheap_clear(mark); + if(FAILED(parser_ctx->hres)) { + hres = parser_ctx->hres; + parser_release(parser_ctx); + return hres; + } + + *ret = parser_ctx; + return S_OK; +}
Propchange: trunk/tools/RosBE/RosBE-Windows/regtest/parser.y ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/tools/RosBE/RosBE-Windows/regtest/regtest.cmd URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/regtest/r... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/regtest/regtest.cmd (added) +++ trunk/tools/RosBE/RosBE-Windows/regtest/regtest.cmd [iso-8859-1] Sun Oct 18 20:40:13 2009 @@ -1,0 +1,32 @@ +@echo off +setlocal enabledelayedexpansion + +echo RosBE Regression Test +echo. + +set /p "dummyvar=Checking for Bison......" < NUL +bison 2> NUL + +if %ERRORLEVEL% == 1 ( + start /min bison parser.y -p parser_ -d -o parser.tab.c + choice /C:AB /T 3 /D A > NUL + taskkill /f /im "bison.exe" > NUL + if !ERRORLEVEL! == 0 ( + echo [broken] + ) else ( + echo [ok] + ) +) else ( + echo [missing] +) + +set /p "dummyvar=Checking for Flex......." <nul +flex -oparser.yy.c -Pparser_ parser.l +if %ERRORLEVEL% == 0 ( + echo [ok] +) else ( + echo [missing] +) +del parser.yy.c 2> NUL +del parser.tab.c 2> NUL +del parser.tab.h 2> NUL
Propchange: trunk/tools/RosBE/RosBE-Windows/regtest/regtest.cmd ------------------------------------------------------------------------------ svn:eol-style = native