Generate bytecode while parsing
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This allocator only allocates a memmory and doesn't free it.
|
||||
Use it only in dedicated parser, otherwise use jerry fixed pool allocator. */
|
||||
#ifndef ALLOCATOR_H
|
||||
#define ALLOCATOR_H
|
||||
|
||||
#include "../globals.h"
|
||||
|
||||
#define ALLOCATION_BUFFER_SIZE 4096
|
||||
|
||||
char allocation_buffer[ALLOCATION_BUFFER_SIZE];
|
||||
char *free_memory;
|
||||
|
||||
static void *
|
||||
geppetto_allocate_memory (size_t size)
|
||||
{
|
||||
void *res;
|
||||
if (!free_memory)
|
||||
free_memory = allocation_buffer;
|
||||
|
||||
res = free_memory;
|
||||
free_memory += size;
|
||||
JERRY_ASSERT (free_memory - allocation_buffer < ALLOCATION_BUFFER_SIZE);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
malloc (size_t size)
|
||||
{
|
||||
return geppetto_allocate_memory (size);
|
||||
}
|
||||
|
||||
static inline void
|
||||
free (void *mem __unused)
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
|
||||
#endif // ALLOCATOR_H
|
||||
@@ -1,418 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bytecode-generator.h"
|
||||
#include "globals.h"
|
||||
#include "libcoreint/opcodes.h"
|
||||
#include "libruntime/serializer.h"
|
||||
#include "libruntime/jerry-libc.h"
|
||||
|
||||
static uint8_t opcode_index;
|
||||
|
||||
#define MAX_STACK_SIZE 10
|
||||
|
||||
static uint8_t opcode_stack[10];
|
||||
static uint8_t stack_head;
|
||||
|
||||
static void
|
||||
push_opcode (uint8_t opcode)
|
||||
{
|
||||
JERRY_ASSERT (stack_head < MAX_STACK_SIZE);
|
||||
opcode_stack[stack_head++] = opcode;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
pop_opcode (void)
|
||||
{
|
||||
return opcode_stack[--stack_head];
|
||||
}
|
||||
|
||||
void
|
||||
generator_init (void)
|
||||
{
|
||||
opcode_index = 0;
|
||||
stack_head = 0;
|
||||
}
|
||||
|
||||
void
|
||||
generator_dump_strings (const char **strings, uint8_t num)
|
||||
{
|
||||
uint8_t len = num, i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
serializer_dump_data (&len, 1);
|
||||
len = (uint8_t) (len + __strlen (strings[i]));
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
serializer_dump_data (strings[i], __strlen (strings[i]) + 1);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_expression (statement stmt)
|
||||
{
|
||||
switch (stmt.type)
|
||||
{
|
||||
case STMT_IF:
|
||||
case STMT_ELSE_IF:
|
||||
case STMT_END_DO_WHILE:
|
||||
case STMT_WHILE:
|
||||
case STMT_RETURN:
|
||||
case STMT_WITH:
|
||||
case STMT_SWITCH:
|
||||
case STMT_CASE:
|
||||
case STMT_THROW:
|
||||
case STMT_EXPRESSION:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
is_assignment (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (is_expression (stmt));
|
||||
return stmt.data.expr.oper != AO_NONE;
|
||||
}
|
||||
|
||||
static expression_type
|
||||
get_expression_type (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (is_expression (stmt));
|
||||
return stmt.data.expr.type;
|
||||
}
|
||||
|
||||
static bool
|
||||
expression_has_operands (statement stmt)
|
||||
{
|
||||
switch (get_expression_type (stmt))
|
||||
{
|
||||
case ET_OBJECT:
|
||||
case ET_FUNCTION:
|
||||
case ET_ARRAY:
|
||||
case ET_SUBEXPRESSION:
|
||||
case ET_NONE:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static operand
|
||||
first_operand (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (expression_has_operands (stmt));
|
||||
return stmt.data.expr.data.ops.op1;
|
||||
}
|
||||
|
||||
static literal
|
||||
first_operand_as_literal (statement stmt)
|
||||
{
|
||||
operand oper = first_operand (stmt);
|
||||
|
||||
JERRY_ASSERT (oper.is_literal);
|
||||
|
||||
return oper.data.lit;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
first_operand_id (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (expression_has_operands (stmt));
|
||||
if (first_operand (stmt).is_literal)
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
return first_operand (stmt).data.name;
|
||||
}
|
||||
|
||||
static operand
|
||||
second_operand (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (expression_has_operands (stmt));
|
||||
return stmt.data.expr.data.ops.op2;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
second_operand_id (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (expression_has_operands (stmt));
|
||||
if (second_operand (stmt).is_literal)
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
return second_operand (stmt).data.name;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
lhs (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (is_assignment (stmt));
|
||||
|
||||
return stmt.data.expr.var;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_opcode (OPCODE *opcode)
|
||||
{
|
||||
serializer_dump_data (opcode, sizeof (OPCODE));
|
||||
opcode_index++;
|
||||
}
|
||||
|
||||
static assignment_operator
|
||||
get_assignment_operator (statement stmt)
|
||||
{
|
||||
JERRY_ASSERT (is_assignment (stmt));
|
||||
|
||||
return stmt.data.expr.oper;
|
||||
}
|
||||
|
||||
static OPCODE
|
||||
generate_triple_address (OPCODE (*getop)(T_IDX, T_IDX, T_IDX), statement stmt)
|
||||
{
|
||||
return (*getop) (lhs (stmt), first_operand_id (stmt), second_operand_id (stmt));
|
||||
}
|
||||
|
||||
void
|
||||
generator_dump_statement (statement stmt)
|
||||
{
|
||||
OPCODE opcode = getop_nop ();
|
||||
JERRY_STATIC_ASSERT (sizeof (OPCODE) <= sizeof (uint32_t));
|
||||
|
||||
switch (stmt.type)
|
||||
{
|
||||
case STMT_EMPTY:
|
||||
break;
|
||||
|
||||
case STMT_WHILE:
|
||||
if (!is_assignment (stmt))
|
||||
{
|
||||
literal lit;
|
||||
|
||||
switch (get_expression_type (stmt))
|
||||
{
|
||||
case ET_LITERAL:
|
||||
lit = first_operand_as_literal (stmt);
|
||||
if (lit.type == LIT_BOOL && lit.data.is_true)
|
||||
{
|
||||
opcode = getop_loop_inf ((uint8_t) (opcode_index + 1));
|
||||
push_opcode ((uint8_t) (opcode_index + 1));
|
||||
dump_opcode (&opcode);
|
||||
return;
|
||||
}
|
||||
else
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
break;
|
||||
|
||||
default:
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
}
|
||||
}
|
||||
else
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
break;
|
||||
|
||||
case STMT_EXPRESSION:
|
||||
if (is_assignment (stmt))
|
||||
{
|
||||
switch (get_expression_type (stmt))
|
||||
{
|
||||
case ET_NONE:
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
|
||||
case ET_LOGICAL_OR:
|
||||
opcode = generate_triple_address (getop_logical_or, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_LOGICAL_AND:
|
||||
opcode = generate_triple_address (getop_logical_and, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_BITWISE_OR:
|
||||
opcode = generate_triple_address (getop_b_or, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_BITWISE_XOR:
|
||||
opcode = generate_triple_address (getop_b_xor, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_BITWISE_AND:
|
||||
opcode = generate_triple_address (getop_b_and, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_DOUBLE_EQ:
|
||||
opcode = generate_triple_address (getop_equal_value, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_NOT_EQ:
|
||||
opcode = generate_triple_address (getop_not_equal_value, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_TRIPLE_EQ:
|
||||
opcode = generate_triple_address (getop_equal_value_type, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_NOT_DOUBLE_EQ:
|
||||
opcode = generate_triple_address (getop_not_equal_value_type, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_LESS:
|
||||
opcode = generate_triple_address (getop_less_than, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_GREATER:
|
||||
opcode = generate_triple_address (getop_greater_than, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_LESS_EQ:
|
||||
opcode = generate_triple_address (getop_less_or_equal_than, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_GREATER_EQ:
|
||||
opcode = generate_triple_address (getop_greater_or_equal_than, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_INSTANCEOF:
|
||||
case ET_IN:
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
break;
|
||||
|
||||
case ET_LSHIFT:
|
||||
opcode = generate_triple_address (getop_b_shift_left, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_RSHIFT:
|
||||
opcode = generate_triple_address (getop_b_shift_right, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_RSHIFT_EX:
|
||||
opcode = generate_triple_address (getop_b_shift_uright, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_PLUS:
|
||||
opcode = generate_triple_address (getop_addition, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_MINUS:
|
||||
opcode = generate_triple_address (getop_substraction, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_MULT:
|
||||
opcode = generate_triple_address (getop_multiplication, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_DIV:
|
||||
opcode = generate_triple_address (getop_division, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_MOD:
|
||||
opcode = generate_triple_address (getop_remainder, stmt);
|
||||
dump_opcode (&opcode);
|
||||
break;
|
||||
|
||||
case ET_UNARY_DELETE:
|
||||
case ET_UNARY_VOID:
|
||||
case ET_UNARY_TYPEOF:
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
break;
|
||||
|
||||
case ET_UNARY_INCREMENT:
|
||||
// opcode = getop_addition (first_operand_id (stmt), first_operand_id (stmt), INTEGER_ONE);
|
||||
case ET_UNARY_DECREMENT:
|
||||
case ET_UNARY_PLUS:
|
||||
case ET_UNARY_MINUS:
|
||||
case ET_UNARY_COMPL:
|
||||
case ET_UNARY_NOT:
|
||||
case ET_POSTFIX_INCREMENT:
|
||||
case ET_POSTFIX_DECREMENT:
|
||||
case ET_CALL:
|
||||
case ET_NEW:
|
||||
case ET_INDEX:
|
||||
case ET_PROP_REF:
|
||||
case ET_OBJECT:
|
||||
case ET_FUNCTION:
|
||||
case ET_ARRAY:
|
||||
case ET_SUBEXPRESSION:
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
break;
|
||||
|
||||
case ET_LITERAL:
|
||||
case ET_IDENTIFIER:
|
||||
switch (get_assignment_operator (stmt))
|
||||
{
|
||||
case AO_NONE:
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
|
||||
case AO_EQ:
|
||||
opcode = getop_assignment (lhs (stmt), first_operand_id (stmt));
|
||||
dump_opcode (&opcode);
|
||||
return;
|
||||
|
||||
default:
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
}
|
||||
JERRY_UNREACHABLE ();
|
||||
|
||||
default:
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
|
||||
if (get_assignment_operator (stmt) != AO_EQ)
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
call_expression expr = stmt.data.expr.data.call_expr;
|
||||
JERRY_ASSERT (!is_operand_list_empty (expr.args));
|
||||
if (!is_operand_empty (expr.args.ops[1]))
|
||||
JERRY_UNREACHABLE ();
|
||||
if (expr.args.ops[0].is_literal)
|
||||
JERRY_UNREACHABLE ();
|
||||
opcode = getop_call_1 (expr.name, expr.args.ops[0].data.name);
|
||||
}
|
||||
break;
|
||||
|
||||
case STMT_END_WHILE:
|
||||
opcode = getop_jmp (pop_opcode ());
|
||||
break;
|
||||
|
||||
default:
|
||||
__printf (" generator_dump_statement: %d ", stmt.type);
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BYTECODE_GENERATOR_H
|
||||
#define BYTECODE_GENERATOR_H
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
void generator_init (void);
|
||||
void generator_dump_strings (const char **, uint8_t);
|
||||
void generator_dump_statement (statement);
|
||||
|
||||
#endif // BYTECODE_GENERATOR_H
|
||||
+113
-41
@@ -13,14 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "allocator.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "globals.h"
|
||||
#include "jerry-libc.h"
|
||||
#include "lexer.h"
|
||||
#include "parser.h"
|
||||
|
||||
static token saved_token;
|
||||
static token empty_token = { .type = TOK_EMPTY, .data.none = NULL };
|
||||
static token empty_token = { .type = TOK_EMPTY, .data.uid = 0 };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -45,7 +45,7 @@ static string_and_token keyword_tokens[] =
|
||||
{ .str = "enum", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
{ .str = "export", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
{ .str = "extends", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
{ .str = "false", .tok = { .type = TOK_BOOL, .data.is_true = false } },
|
||||
{ .str = "false", .tok = { .type = TOK_BOOL, .data.uid = false } },
|
||||
{ .str = "finally", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FINALLY } },
|
||||
{ .str = "for", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FOR } },
|
||||
{ .str = "function", .tok = { .type = TOK_KEYWORD, .data.kw = KW_FUNCTION } },
|
||||
@@ -57,7 +57,7 @@ static string_and_token keyword_tokens[] =
|
||||
{ .str = "implements", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
{ .str = "let", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
{ .str = "new", .tok = { .type = TOK_KEYWORD, .data.kw = KW_NEW } },
|
||||
{ .str = "null", .tok = { .type = TOK_NULL, .data.none = NULL } },
|
||||
{ .str = "null", .tok = { .type = TOK_NULL, .data.uid = 0 } },
|
||||
{ .str = "package", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
{ .str = "private", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
{ .str = "protected", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } },
|
||||
@@ -68,7 +68,7 @@ static string_and_token keyword_tokens[] =
|
||||
{ .str = "switch", .tok = { .type = TOK_KEYWORD, .data.kw = KW_SWITCH } },
|
||||
{ .str = "this", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THIS } },
|
||||
{ .str = "throw", .tok = { .type = TOK_KEYWORD, .data.kw = KW_THROW } },
|
||||
{ .str = "true", .tok = { .type = TOK_BOOL, .data.is_true = true } },
|
||||
{ .str = "true", .tok = { .type = TOK_BOOL, .data.uid = true } },
|
||||
{ .str = "try", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TRY } },
|
||||
{ .str = "typeof", .tok = { .type = TOK_KEYWORD, .data.kw = KW_TYPEOF } },
|
||||
{ .str = "var", .tok = { .type = TOK_KEYWORD, .data.kw = KW_VAR } },
|
||||
@@ -78,10 +78,25 @@ static string_and_token keyword_tokens[] =
|
||||
{ .str = "yield", .tok = { .type = TOK_KEYWORD, .data.kw = KW_RESERVED } }
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int num;
|
||||
token tok;
|
||||
}
|
||||
num_and_token;
|
||||
|
||||
#define MAX_NAMES 100
|
||||
#define MAX_NUMS 25
|
||||
|
||||
static string_and_token seen_names[MAX_NAMES];
|
||||
static uint8_t seen_names_num;
|
||||
static uint8_t seen_names_count = 0;
|
||||
|
||||
static num_and_token seen_nums[MAX_NAMES] =
|
||||
{
|
||||
[0] = { .num = 0, .tok = { .type = TOK_INT, .data.uid = 0 } },
|
||||
[1] = { .num = 1, .tok = { .type = TOK_INT, .data.uid = 1 } }
|
||||
};
|
||||
static uint8_t seen_nums_count = 2;
|
||||
|
||||
static bool
|
||||
is_empty (token tok)
|
||||
@@ -114,7 +129,7 @@ get_char (size_t i)
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
buffer = (char *) malloc (BUFFER_SIZE);
|
||||
buffer = (char *) mem_HeapAllocBlock (BUFFER_SIZE, MEM_HEAP_ALLOC_SHORT_TERM);
|
||||
error = __fread (buffer, 1, BUFFER_SIZE, file);
|
||||
if (error == 0)
|
||||
return '\0';
|
||||
@@ -184,7 +199,7 @@ decode_keyword (void)
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (!__strncmp (keyword_tokens[i].str, token_start, __strlen (keyword_tokens[i].str)))
|
||||
if (!__strncmp (keyword_tokens[i].str, token_start, (size_t) (buffer - token_start)))
|
||||
return keyword_tokens[i].tok;
|
||||
}
|
||||
|
||||
@@ -196,9 +211,9 @@ convert_seen_name_to_token (void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < seen_names_num; i++)
|
||||
for (i = 0; i < seen_names_count; i++)
|
||||
{
|
||||
if (!__strncmp (seen_names[i].str, token_start, __strlen (seen_names[i].str)))
|
||||
if (!__strncmp (seen_names[i].str, token_start, (size_t) (buffer - token_start)))
|
||||
return seen_names[i].tok;
|
||||
}
|
||||
|
||||
@@ -206,12 +221,33 @@ convert_seen_name_to_token (void)
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_seen_tokens (string_and_token snt)
|
||||
add_name_to_seen_tokens (string_and_token snt)
|
||||
{
|
||||
JERRY_ASSERT (seen_names_num < MAX_NAMES);
|
||||
JERRY_ASSERT (seen_names_count < MAX_NAMES);
|
||||
|
||||
snt.tok.data.name = (string_id) seen_names_num;
|
||||
seen_names[seen_names_num++] = snt;
|
||||
seen_names[seen_names_count++] = snt;
|
||||
}
|
||||
|
||||
static token
|
||||
convert_seen_num_to_token (int num)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < seen_nums_count; i++)
|
||||
{
|
||||
if (seen_nums[i].num == num)
|
||||
return seen_nums[i].tok;
|
||||
}
|
||||
|
||||
return empty_token;
|
||||
}
|
||||
|
||||
static void
|
||||
add_num_to_seen_tokens (num_and_token nat)
|
||||
{
|
||||
JERRY_ASSERT (seen_nums_count < MAX_NUMS);
|
||||
|
||||
seen_nums[seen_nums_count++] = nat;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@@ -219,20 +255,32 @@ lexer_get_strings (const char **strings)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < seen_names_num; i++)
|
||||
strings[i] = seen_names[i].str;
|
||||
if (strings)
|
||||
for (i = 0; i < seen_names_count; i++)
|
||||
strings[i] = seen_names[i].str;
|
||||
|
||||
return seen_names_num;
|
||||
return seen_names_count;
|
||||
}
|
||||
|
||||
const char *
|
||||
lexer_get_string_by_id (string_id id)
|
||||
lexer_get_string_by_id (uint8_t id)
|
||||
{
|
||||
JERRY_ASSERT (id < seen_names_num);
|
||||
JERRY_ASSERT (id < seen_names_count);
|
||||
|
||||
return seen_names[id].str;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
lexer_get_nums (int *nums)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < seen_nums_count; i++)
|
||||
nums[i] = seen_nums[i].num;
|
||||
|
||||
return seen_nums_count;
|
||||
}
|
||||
|
||||
static void
|
||||
new_token (void)
|
||||
{
|
||||
@@ -254,7 +302,7 @@ current_token (void)
|
||||
JERRY_ASSERT (token_start);
|
||||
JERRY_ASSERT (token_start <= buffer);
|
||||
size_t length = (size_t) (buffer - token_start);
|
||||
char *res = (char *) malloc (length + 1);
|
||||
char *res = (char *) mem_HeapAllocBlock (length + 1, MEM_HEAP_ALLOC_SHORT_TERM);
|
||||
__strncpy (res, token_start, length);
|
||||
res[length] = '\0';
|
||||
token_start = NULL;
|
||||
@@ -265,7 +313,7 @@ current_token (void)
|
||||
do \
|
||||
{ \
|
||||
buffer += NUM; \
|
||||
return (token) { .type = TOK, .data.none = NULL }; \
|
||||
return (token) { .type = TOK, .data.uid = 0 }; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
@@ -338,9 +386,9 @@ parse_name (void)
|
||||
}
|
||||
|
||||
string = current_token ();
|
||||
known_token = (token) { .type = TOK_NAME, .data.name = seen_names_num };
|
||||
known_token = (token) { .type = TOK_NAME, .data.uid = seen_names_count };
|
||||
|
||||
add_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
|
||||
add_name_to_seen_tokens ((string_and_token) { .str = string, .tok = known_token });
|
||||
|
||||
return known_token;
|
||||
}
|
||||
@@ -387,6 +435,7 @@ parse_number (void)
|
||||
bool is_exp = false;
|
||||
size_t tok_length = 0, i;
|
||||
int res = 0;
|
||||
token known_token;
|
||||
|
||||
JERRY_ASSERT (__isdigit (c) || c == '.');
|
||||
|
||||
@@ -423,7 +472,14 @@ parse_number (void)
|
||||
res = (res << 4) + hex_to_int (token_start[i]);
|
||||
|
||||
token_start = NULL;
|
||||
return (token) { .type = TOK_INT, .data.num = res };
|
||||
|
||||
known_token = convert_seen_num_to_token (res);
|
||||
if (!is_empty (known_token))
|
||||
return known_token;
|
||||
|
||||
known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count };
|
||||
add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token });
|
||||
return known_token;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (!is_hex && !is_exp);
|
||||
@@ -475,7 +531,8 @@ parse_number (void)
|
||||
{
|
||||
float res = __strtof (token_start, NULL);
|
||||
token_start = NULL;
|
||||
return (token) { .type = TOK_FLOAT, .data.fp_num = res };
|
||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (res);
|
||||
return empty_token;
|
||||
}
|
||||
|
||||
tok_length = (size_t) (buffer - token_start);;
|
||||
@@ -484,7 +541,13 @@ parse_number (void)
|
||||
|
||||
token_start = NULL;
|
||||
|
||||
return (token) { .type = TOK_INT, .data.num = res };
|
||||
known_token = convert_seen_num_to_token (res);
|
||||
if (!is_empty (known_token))
|
||||
return known_token;
|
||||
|
||||
known_token = (token) { .type = TOK_INT, .data.uid = seen_nums_count };
|
||||
add_num_to_seen_tokens ((num_and_token) { .num = res, .tok = known_token });
|
||||
return known_token;
|
||||
}
|
||||
|
||||
static char
|
||||
@@ -513,7 +576,7 @@ parse_string (void)
|
||||
char *tok = NULL;
|
||||
char *index = NULL;
|
||||
const char *i;
|
||||
size_t length;
|
||||
size_t length, num;
|
||||
token res = empty_token;
|
||||
|
||||
JERRY_ASSERT (c == '\'' || c == '"');
|
||||
@@ -553,7 +616,7 @@ parse_string (void)
|
||||
}
|
||||
|
||||
length = (size_t) (buffer - token_start);
|
||||
tok = (char *) malloc (length);
|
||||
tok = (char *) mem_HeapAllocBlock (length, MEM_HEAP_ALLOC_SHORT_TERM);
|
||||
index = tok;
|
||||
|
||||
for (i = token_start; i < buffer; i++)
|
||||
@@ -581,9 +644,18 @@ parse_string (void)
|
||||
// Eat up '"'
|
||||
consume_char ();
|
||||
|
||||
res = (token) { .type = TOK_STRING, .data.str = seen_names_num };
|
||||
for (num = 0; num < seen_names_count; num++)
|
||||
{
|
||||
if (!__strncmp (seen_names[num].str, tok, __strlen (tok)))
|
||||
{
|
||||
mem_HeapFreeBlock ((uint8_t*) tok);
|
||||
return seen_names[num].tok;
|
||||
}
|
||||
}
|
||||
|
||||
add_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
|
||||
res = (token) { .type = TOK_STRING, .data.uid = seen_names_count };
|
||||
|
||||
add_name_to_seen_tokens ((string_and_token) { .str = tok, .tok = res });
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -593,7 +665,7 @@ grobble_whitespaces (void)
|
||||
{
|
||||
char c = LA (0);
|
||||
|
||||
while ((__isspace (c) && c != '\n') || c == '\0')
|
||||
while ((__isspace (c) && c != '\n'))
|
||||
{
|
||||
consume_char ();
|
||||
c = LA (0);
|
||||
@@ -685,11 +757,11 @@ lexer_next_token (void)
|
||||
if (c == '\n')
|
||||
{
|
||||
consume_char ();
|
||||
return (token) { .type = TOK_NEWLINE, .data.none = NULL };
|
||||
return (token) { .type = TOK_NEWLINE, .data.uid = 0 };
|
||||
}
|
||||
|
||||
if (c == '\0')
|
||||
return (token) { .type = TOK_EOF, .data.none = NULL };;
|
||||
return (token) { .type = TOK_EOF, .data.uid = 0 };;
|
||||
|
||||
if (c == '\'' || c == '"')
|
||||
return parse_string ();
|
||||
@@ -708,7 +780,7 @@ lexer_next_token (void)
|
||||
if (c == '/' && LA (1) == '*')
|
||||
{
|
||||
if (replace_comment_by_newline ())
|
||||
return (token) { .type = TOK_NEWLINE, .data.none = NULL };
|
||||
return (token) { .type = TOK_NEWLINE, .data.uid = 0 };
|
||||
else
|
||||
return
|
||||
#ifdef __HOST
|
||||
@@ -803,11 +875,11 @@ lexer_next_token (void)
|
||||
token tok = lexer_next_token_private ();
|
||||
if (tok.type == TOK_NEWLINE)
|
||||
return tok;
|
||||
// if (tok.type == TOK_CLOSE_BRACE)
|
||||
if (tok.type == TOK_CLOSE_PAREN)
|
||||
{
|
||||
// if (i == 300)
|
||||
__fprintf (lexer_debug_log, "lexer_next_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none);
|
||||
i++;
|
||||
__fprintf (lexer_debug_log, "lexer_next_token(%d): type=%d, data=%d\n", i, tok.type, tok.data.uid);
|
||||
i++;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
@@ -816,10 +888,10 @@ lexer_next_token (void)
|
||||
void
|
||||
lexer_save_token (token tok)
|
||||
{
|
||||
#ifdef __HOST
|
||||
// if (tok.type == TOK_CLOSE_BRACE)
|
||||
__fprintf (lexer_debug_log, "lexer_save_token(%d): type=0x%x, data=%p\n", i, tok.type, tok.data.none);
|
||||
#endif
|
||||
#ifdef __HOST
|
||||
if (tok.type == TOK_CLOSE_PAREN)
|
||||
__fprintf (lexer_debug_log, "lexer_save_token(%d): type=%d, data=%d\n", i, tok.type, tok.data.uid);
|
||||
#endif
|
||||
saved_token = tok;
|
||||
}
|
||||
|
||||
|
||||
+104
-112
@@ -18,121 +18,120 @@
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
typedef uint8_t string_id;
|
||||
|
||||
/* Keywords. */
|
||||
typedef enum
|
||||
{
|
||||
/* Not a keyword. */
|
||||
KW_NONE = 0,
|
||||
/* Future reserved keyword. */
|
||||
KW_RESERVED,
|
||||
typedef uint8_t keyword;
|
||||
|
||||
KW_BREAK,
|
||||
KW_CASE,
|
||||
KW_CATCH,
|
||||
KW_CONTINUE,
|
||||
KW_DEBUGGER,
|
||||
KW_DEFAULT,
|
||||
KW_DELETE,
|
||||
/* Not a keyword. */
|
||||
#define KW_NONE 0
|
||||
/* Future reserved keyword. */
|
||||
#define KW_RESERVED 1
|
||||
#define KW_BREAK 2
|
||||
#define KW_CASE 3
|
||||
#define KW_CATCH 4
|
||||
|
||||
KW_DO,
|
||||
KW_ELSE,
|
||||
KW_FINALLY,
|
||||
KW_FOR,
|
||||
KW_FUNCTION,
|
||||
KW_IF,
|
||||
KW_IN,
|
||||
#define KW_CONTINUE 5
|
||||
#define KW_DEBUGGER 6
|
||||
#define KW_DEFAULT 7
|
||||
#define KW_DELETE 8
|
||||
#define KW_DO 9
|
||||
|
||||
KW_INSTANCEOF,
|
||||
KW_NEW,
|
||||
KW_RETURN,
|
||||
KW_SWITCH,
|
||||
KW_THIS,
|
||||
KW_THROW,
|
||||
KW_TRY,
|
||||
#define KW_ELSE 10
|
||||
#define KW_FINALLY 11
|
||||
#define KW_FOR 12
|
||||
#define KW_FUNCTION 13
|
||||
#define KW_IF 14
|
||||
|
||||
#define KW_IN 15
|
||||
#define KW_INSTANCEOF 16
|
||||
#define KW_NEW 17
|
||||
#define KW_RETURN 18
|
||||
#define KW_SWITCH 19
|
||||
|
||||
#define KW_THIS 20
|
||||
#define KW_THROW 21
|
||||
#define KW_TRY 22
|
||||
#define KW_TYPEOF 23
|
||||
#define KW_VAR 24
|
||||
|
||||
#define KW_VOID 25
|
||||
#define KW_WHILE 26
|
||||
#define KW_WITH 27
|
||||
|
||||
KW_TYPEOF,
|
||||
KW_VAR,
|
||||
KW_VOID,
|
||||
KW_WHILE,
|
||||
KW_WITH
|
||||
}
|
||||
keyword;
|
||||
|
||||
/* Type of tokens. */
|
||||
typedef enum
|
||||
{
|
||||
TOK_EOF = 0x0, // End of file
|
||||
TOK_NAME = 0x1, // Identifier
|
||||
TOK_KEYWORD = 0x2, // Keyword
|
||||
TOK_INT = 0x3,
|
||||
TOK_FLOAT = 0x4,
|
||||
TOK_NULL = 0x5,
|
||||
TOK_BOOL = 0x6,
|
||||
TOK_NEWLINE = 0x7,
|
||||
TOK_STRING = 0x8,
|
||||
typedef uint8_t token_type;
|
||||
|
||||
/* Punctuators. */
|
||||
TOK_OPEN_BRACE = 0x9, // {
|
||||
TOK_CLOSE_BRACE = 0xa, // }
|
||||
TOK_OPEN_PAREN = 0xb, // (
|
||||
TOK_CLOSE_PAREN = 0xc, // )
|
||||
TOK_OPEN_SQUARE, // [
|
||||
TOK_CLOSE_SQUARE, // [
|
||||
#define TOK_EOF 0 // End of file
|
||||
#define TOK_NAME 1 // Identifier
|
||||
#define TOK_KEYWORD 2 // Keyword
|
||||
#define TOK_INT 3
|
||||
#define TOK_FLOAT 4
|
||||
|
||||
TOK_DOT, // .
|
||||
TOK_SEMICOLON, // ;
|
||||
TOK_COMMA, // ,
|
||||
TOK_LESS, // <
|
||||
TOK_GREATER, // >
|
||||
TOK_LESS_EQ, // <=
|
||||
#define TOK_NULL 5
|
||||
#define TOK_BOOL 6
|
||||
#define TOK_NEWLINE 7
|
||||
#define TOK_STRING 8
|
||||
#define TOK_OPEN_BRACE 9 // {
|
||||
|
||||
TOK_GREATER_EQ, // <=
|
||||
TOK_DOUBLE_EQ, // ==
|
||||
TOK_NOT_EQ, // !=
|
||||
TOK_TRIPLE_EQ, // ===
|
||||
TOK_NOT_DOUBLE_EQ, // !==
|
||||
#define TOK_CLOSE_BRACE 10 // }
|
||||
#define TOK_OPEN_PAREN 11 // (
|
||||
#define TOK_CLOSE_PAREN 12 // )
|
||||
#define TOK_OPEN_SQUARE 13 // [
|
||||
#define TOK_CLOSE_SQUARE 14 // [
|
||||
|
||||
TOK_PLUS, // +
|
||||
TOK_MINUS, // -
|
||||
TOK_MULT, // *
|
||||
TOK_MOD, // %
|
||||
TOK_DOUBLE_PLUS, // ++
|
||||
TOK_DOUBLE_MINUS, // --
|
||||
#define TOK_DOT 15 // .
|
||||
#define TOK_SEMICOLON 16 // ;
|
||||
#define TOK_COMMA 17 // ,
|
||||
#define TOK_LESS 18 // <
|
||||
#define TOK_GREATER 19 // >
|
||||
|
||||
TOK_LSHIFT, // <<
|
||||
TOK_RSHIFT, // >>
|
||||
TOK_RSHIFT_EX, // >>>
|
||||
TOK_AND, // &
|
||||
TOK_OR, // |
|
||||
TOK_XOR, // ^
|
||||
#define TOK_LESS_EQ 20 // <=
|
||||
#define TOK_GREATER_EQ 21 // <=
|
||||
#define TOK_DOUBLE_EQ 22 // ==
|
||||
#define TOK_NOT_EQ 23 // !=
|
||||
#define TOK_TRIPLE_EQ 24 // ===
|
||||
|
||||
TOK_NOT, // !
|
||||
TOK_COMPL, // ~
|
||||
TOK_DOUBLE_AND, // &&
|
||||
TOK_DOUBLE_OR, // ||
|
||||
TOK_QUERY, // ?
|
||||
TOK_COLON, // :
|
||||
#define TOK_NOT_DOUBLE_EQ 25 // !==
|
||||
#define TOK_PLUS 26 // +
|
||||
#define TOK_MINUS 27 // -
|
||||
#define TOK_MULT 28 // *
|
||||
#define TOK_MOD 29 // %
|
||||
|
||||
TOK_EQ, // =
|
||||
TOK_PLUS_EQ, // +=
|
||||
TOK_MINUS_EQ, // -=
|
||||
TOK_MULT_EQ, // *=
|
||||
TOK_MOD_EQ, // %=
|
||||
TOK_LSHIFT_EQ, // <<=
|
||||
#define TOK_DOUBLE_PLUS 30 // ++
|
||||
#define TOK_DOUBLE_MINUS 31 // --
|
||||
#define TOK_LSHIFT 32 // <<
|
||||
#define TOK_RSHIFT 33 // >>
|
||||
#define TOK_RSHIFT_EX 34 // >>>
|
||||
|
||||
TOK_RSHIFT_EQ, // >>=
|
||||
TOK_RSHIFT_EX_EQ, // >>>=
|
||||
TOK_AND_EQ, // &=
|
||||
TOK_OR_EQ, // |=
|
||||
TOK_XOR_EQ, // ^=
|
||||
#define TOK_AND 35 // &
|
||||
#define TOK_OR 36 // |
|
||||
#define TOK_XOR 37 // ^
|
||||
#define TOK_NOT 38 // !
|
||||
#define TOK_COMPL 39 // ~
|
||||
|
||||
#define TOK_DOUBLE_AND 40 // &&
|
||||
#define TOK_DOUBLE_OR 41 // ||
|
||||
#define TOK_QUERY 42 // ?
|
||||
#define TOK_COLON 43 // :
|
||||
#define TOK_EQ 44 // =
|
||||
|
||||
#define TOK_PLUS_EQ 45 // +=
|
||||
#define TOK_MINUS_EQ 46 // -=
|
||||
#define TOK_MULT_EQ 47 // *=
|
||||
#define TOK_MOD_EQ 48 // %=
|
||||
#define TOK_LSHIFT_EQ 49 // <<=
|
||||
|
||||
#define TOK_RSHIFT_EQ 50 // >>=
|
||||
#define TOK_RSHIFT_EX_EQ 51 // >>>=
|
||||
#define TOK_AND_EQ 52 // &=
|
||||
#define TOK_OR_EQ 53 // |=
|
||||
#define TOK_XOR_EQ 54 // ^=
|
||||
|
||||
#define TOK_DIV 55 // /
|
||||
#define TOK_DIV_EQ 56 // /=
|
||||
#define TOK_EMPTY 57
|
||||
|
||||
TOK_DIV, // /
|
||||
TOK_DIV_EQ, // /=
|
||||
TOK_EMPTY
|
||||
}
|
||||
token_type;
|
||||
|
||||
/* Represents the contents of a token. */
|
||||
typedef struct
|
||||
@@ -140,17 +139,12 @@ typedef struct
|
||||
token_type type;
|
||||
|
||||
union
|
||||
{
|
||||
void *none;
|
||||
keyword kw;
|
||||
string_id name;
|
||||
bool is_true;
|
||||
int num;
|
||||
float fp_num;
|
||||
string_id str;
|
||||
}
|
||||
{
|
||||
keyword kw;
|
||||
uint8_t uid;
|
||||
}
|
||||
data;
|
||||
}
|
||||
} __packed
|
||||
token;
|
||||
|
||||
#ifdef __HOST
|
||||
@@ -160,11 +154,9 @@ void lexer_set_source (const char *);
|
||||
#endif
|
||||
token lexer_next_token (void);
|
||||
void lexer_save_token (token);
|
||||
|
||||
void lexer_dump_buffer_state (void);
|
||||
|
||||
uint8_t lexer_get_strings (const char **);
|
||||
|
||||
const char *lexer_get_string_by_id (string_id id);
|
||||
const char *lexer_get_string_by_id (uint8_t);
|
||||
uint8_t lexer_get_nums (int *);
|
||||
|
||||
#endif
|
||||
|
||||
+1367
-964
File diff suppressed because it is too large
Load Diff
+1
-420
@@ -18,427 +18,8 @@
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#define null_string 255
|
||||
#define MAX_PARAMS 5
|
||||
#define MAX_EXPRS 2
|
||||
#define MAX_PROPERTIES 5
|
||||
#define MAX_DECLS 5
|
||||
#define MAX_SUFFIXES 2
|
||||
|
||||
/** Represents list of parameters. */
|
||||
typedef struct formal_parameter_list
|
||||
{
|
||||
/** Identifiers of a parameter. Next after last parameter is NULL. */
|
||||
uint8_t names[MAX_PARAMS];
|
||||
}
|
||||
formal_parameter_list;
|
||||
|
||||
static const formal_parameter_list
|
||||
empty_formal_parameter_list =
|
||||
{
|
||||
.names = { [0] = null_string }
|
||||
};
|
||||
|
||||
bool is_formal_parameter_list_empty (formal_parameter_list);
|
||||
|
||||
/** @function_declaration represents both declaration and expression of a function.
|
||||
After this parser must return a block of statements. */
|
||||
typedef struct
|
||||
{
|
||||
/** Identifier: name of a function. Can be NULL for anonimous functions. */
|
||||
uint8_t name;
|
||||
/** List of parameter of a function. Can be NULL. */
|
||||
formal_parameter_list params;
|
||||
}
|
||||
function_declaration;
|
||||
|
||||
typedef function_declaration function_expression;
|
||||
|
||||
/** Types of literals: null, bool, decimal and string.
|
||||
Decimal type is represented by LIT_INT and supports only double-word sized integers. */
|
||||
typedef enum
|
||||
{
|
||||
LIT_NULL,
|
||||
LIT_BOOL,
|
||||
LIT_INT,
|
||||
LIT_STR
|
||||
}
|
||||
literal_type;
|
||||
|
||||
/** Represents different literals, contains a data of them. */
|
||||
typedef struct
|
||||
{
|
||||
/** Type of a literal. */
|
||||
literal_type type;
|
||||
|
||||
/** Value of a literal. */
|
||||
union
|
||||
{
|
||||
/** Used by null literal, always NULL. */
|
||||
void *none;
|
||||
/** String literal value. */
|
||||
uint8_t str;
|
||||
/** Number value. */
|
||||
int num;
|
||||
/** Boolean value. */
|
||||
bool is_true;
|
||||
}
|
||||
data;
|
||||
}
|
||||
literal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool is_literal;
|
||||
|
||||
union
|
||||
{
|
||||
void *none;
|
||||
literal lit;
|
||||
uint8_t name;
|
||||
}
|
||||
data;
|
||||
}
|
||||
operand;
|
||||
|
||||
typedef operand property_name;
|
||||
|
||||
static const operand
|
||||
empty_operand =
|
||||
{
|
||||
.is_literal = false,
|
||||
.data.none = NULL
|
||||
};
|
||||
|
||||
bool is_operand_empty (operand);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
operand op1, op2;
|
||||
}
|
||||
operand_pair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
operand ops[MAX_PARAMS];
|
||||
}
|
||||
operand_list;
|
||||
|
||||
static const operand_list
|
||||
empty_operand_list =
|
||||
{
|
||||
.ops = { [0] = { .is_literal = false, .data.none = NULL } }
|
||||
};
|
||||
|
||||
bool is_operand_list_empty (operand_list);
|
||||
|
||||
typedef operand_list array_literal;
|
||||
typedef operand_list argument_list;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t name;
|
||||
argument_list args;
|
||||
}
|
||||
call_expression;
|
||||
|
||||
/** Represents a single property. */
|
||||
typedef struct
|
||||
{
|
||||
/** Name of property. */
|
||||
property_name name;
|
||||
/** Value of property. */
|
||||
operand value;
|
||||
}
|
||||
property;
|
||||
|
||||
static const property empty_property =
|
||||
{
|
||||
.name = { .is_literal = false, .data.none = NULL },
|
||||
.value = { .is_literal = false, .data.none = NULL }
|
||||
};
|
||||
|
||||
bool is_property_empty (property);
|
||||
|
||||
/** List of properties. Represents ObjectLiteral. */
|
||||
typedef struct
|
||||
{
|
||||
/** Properties. */
|
||||
property props[MAX_PROPERTIES];
|
||||
}
|
||||
property_list;
|
||||
|
||||
static const property_list
|
||||
empty_property_list =
|
||||
{
|
||||
.props =
|
||||
{ [0] =
|
||||
{ .name =
|
||||
{ .is_literal = false, .data.none = NULL },
|
||||
.value =
|
||||
{ .is_literal = false, .data.none = NULL }}}
|
||||
};
|
||||
|
||||
bool is_property_list_empty (property_list);
|
||||
|
||||
typedef property_list object_literal;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AO_NONE,
|
||||
AO_EQ,
|
||||
AO_MULT_EQ,
|
||||
AO_DIV_EQ,
|
||||
AO_MOD_EQ,
|
||||
AO_PLUS_EQ,
|
||||
AO_MINUS_EQ,
|
||||
AO_LSHIFT_EQ,
|
||||
AO_RSHIFT_EQ,
|
||||
AO_RSHIFT_EX_EQ,
|
||||
AO_AND_EQ,
|
||||
AO_XOR_EQ,
|
||||
AO_OR_EQ
|
||||
}
|
||||
assignment_operator;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ET_NONE,
|
||||
ET_LOGICAL_OR,
|
||||
ET_LOGICAL_AND,
|
||||
ET_BITWISE_OR,
|
||||
ET_BITWISE_XOR,
|
||||
ET_BITWISE_AND,
|
||||
ET_DOUBLE_EQ,
|
||||
ET_NOT_EQ,
|
||||
ET_TRIPLE_EQ,
|
||||
ET_NOT_DOUBLE_EQ,
|
||||
ET_LESS,
|
||||
ET_GREATER,
|
||||
ET_LESS_EQ,
|
||||
ET_GREATER_EQ,
|
||||
ET_INSTANCEOF,
|
||||
ET_IN,
|
||||
ET_LSHIFT,
|
||||
ET_RSHIFT,
|
||||
ET_RSHIFT_EX,
|
||||
ET_PLUS,
|
||||
ET_MINUS,
|
||||
ET_MULT,
|
||||
ET_DIV,
|
||||
ET_MOD,
|
||||
ET_UNARY_DELETE,
|
||||
ET_UNARY_VOID,
|
||||
ET_UNARY_TYPEOF,
|
||||
ET_UNARY_INCREMENT,
|
||||
ET_UNARY_DECREMENT,
|
||||
ET_UNARY_PLUS,
|
||||
ET_UNARY_MINUS,
|
||||
ET_UNARY_COMPL,
|
||||
ET_UNARY_NOT,
|
||||
ET_POSTFIX_INCREMENT,
|
||||
ET_POSTFIX_DECREMENT,
|
||||
ET_CALL,
|
||||
ET_NEW,
|
||||
ET_INDEX,
|
||||
ET_PROP_REF,
|
||||
ET_OBJECT,
|
||||
ET_FUNCTION,
|
||||
ET_ARRAY,
|
||||
ET_SUBEXPRESSION,
|
||||
ET_LITERAL,
|
||||
ET_IDENTIFIER
|
||||
}
|
||||
expression_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
assignment_operator oper;
|
||||
expression_type type;
|
||||
|
||||
/** NUllable. */
|
||||
uint8_t var;
|
||||
|
||||
union
|
||||
{
|
||||
void *none;
|
||||
operand_pair ops;
|
||||
call_expression call_expr;
|
||||
array_literal arr_lit;
|
||||
object_literal obj_lit;
|
||||
function_expression func_expr;
|
||||
}
|
||||
data;
|
||||
}
|
||||
assignment_expression;
|
||||
|
||||
static const assignment_expression
|
||||
empty_expression =
|
||||
{
|
||||
.oper = AO_NONE,
|
||||
.type = ET_NONE,
|
||||
.data.none = NULL
|
||||
};
|
||||
|
||||
bool is_expression_empty (assignment_expression);
|
||||
|
||||
/** Represents expression, array literal and list of argument. */
|
||||
typedef struct
|
||||
{
|
||||
/** Single assignment expression. Cannot be NULL for expression and list of arguments.
|
||||
But can be NULL for array literal. */
|
||||
assignment_expression exprs[MAX_EXPRS];
|
||||
}
|
||||
expression_list;
|
||||
|
||||
typedef expression_list expression;
|
||||
|
||||
/* Statements. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t name;
|
||||
assignment_expression assign_expr;
|
||||
}
|
||||
variable_declaration;
|
||||
|
||||
static const variable_declaration
|
||||
empty_variable_declaration =
|
||||
{
|
||||
.name = null_string,
|
||||
.assign_expr = { .oper = AO_NONE, .type = ET_NONE, .data.none = NULL }
|
||||
};
|
||||
|
||||
bool is_variable_declaration_empty (variable_declaration);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
variable_declaration decls[MAX_DECLS];
|
||||
}
|
||||
variable_declaration_list;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool is_decl;
|
||||
|
||||
union
|
||||
{
|
||||
expression expr;
|
||||
variable_declaration_list decl_list;
|
||||
}
|
||||
data;
|
||||
}
|
||||
for_statement_initialiser_part;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
for_statement_initialiser_part init;
|
||||
assignment_expression limit, incr;
|
||||
}
|
||||
for_statement;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool is_decl;
|
||||
|
||||
union
|
||||
{
|
||||
assignment_expression left_hand_expr;
|
||||
variable_declaration decl;
|
||||
}
|
||||
data;
|
||||
}
|
||||
for_in_statement_initializer_part;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
for_in_statement_initializer_part init;
|
||||
expression list_expr;
|
||||
}
|
||||
for_in_statement;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool is_for_in;
|
||||
|
||||
union
|
||||
{
|
||||
for_statement for_stmt;
|
||||
for_in_statement for_in_stmt;
|
||||
}
|
||||
data;
|
||||
}
|
||||
for_or_for_in_statement;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STMT_NULL,
|
||||
STMT_VARIABLE,
|
||||
STMT_EMPTY,
|
||||
STMT_IF,
|
||||
STMT_ELSE,
|
||||
STMT_ELSE_IF,
|
||||
STMT_END_IF,
|
||||
STMT_DO_WHILE,
|
||||
STMT_END_DO_WHILE,
|
||||
STMT_WHILE,
|
||||
|
||||
STMT_END_WHILE,
|
||||
STMT_FOR_OR_FOR_IN,
|
||||
STMT_END_FOR_OR_FOR_IN,
|
||||
STMT_CONTINUE,
|
||||
STMT_BREAK,
|
||||
STMT_RETURN,
|
||||
STMT_WITH,
|
||||
STMT_END_WITH,
|
||||
STMT_LABELLED,
|
||||
STMT_SWITCH,
|
||||
|
||||
STMT_END_SWITCH,
|
||||
STMT_CASE,
|
||||
STMT_THROW,
|
||||
STMT_TRY,
|
||||
STMT_CATCH,
|
||||
STMT_END_CATCH,
|
||||
STMT_FINALLY,
|
||||
STMT_END_FINALLY,
|
||||
STMT_EXPRESSION,
|
||||
STMT_END_SUBEXPRESSION,
|
||||
|
||||
STMT_FUNCTION,
|
||||
STMT_END_FUNCTION,
|
||||
STMT_EOF
|
||||
}
|
||||
statement_type;
|
||||
|
||||
typedef struct statement
|
||||
{
|
||||
statement_type type;
|
||||
|
||||
union
|
||||
{
|
||||
void *none;
|
||||
variable_declaration_list var_stmt;
|
||||
assignment_expression expr;
|
||||
for_or_for_in_statement for_stmt;
|
||||
uint8_t name;
|
||||
function_declaration fun_decl;
|
||||
}
|
||||
data;
|
||||
}
|
||||
statement;
|
||||
|
||||
static const statement
|
||||
null_statement =
|
||||
{
|
||||
.type = STMT_NULL,
|
||||
.data.none = NULL
|
||||
};
|
||||
|
||||
bool is_statement_null (statement);
|
||||
|
||||
void parser_init (void);
|
||||
statement parser_parse_statement (void);
|
||||
void parser_parse_program (void);
|
||||
|
||||
void parser_fatal (jerry_Status_t code);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user