[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-smalltalk] scripting syntax part 3
From: |
Paolo Bonzini |
Subject: |
[Help-smalltalk] scripting syntax part 3 |
Date: |
Wed, 11 Apr 2007 15:06:44 +0200 |
User-agent: |
Thunderbird 1.5.0.10 (Macintosh/20070221) |
Here's the bulk of the new syntax. The regression tests need to use it
for simplicity, I will send the patch for that soon.
There are still some bugs, mostly infinite loops caused by error
recovery, but they will be addressed soon.
Paolo (and Daniele)
--- orig/kernel/ClassDesc.st
+++ mod/kernel/ClassDesc.st
@@ -405,6 +405,16 @@ asMetaclass
!ClassDescription methodsFor: 'parsing class declarations'!
+addSharedPool: aDictionary
+ "Add the given shared pool to the list of the class' pool dictionaries"
+ self subclassResponsibility
+!
+
+import: aDictionary
+ "Add the given shared pool to the list of the class' pool dictionaries"
+ self addSharedPool: aDictionary
+!
+
instanceVariableNames: instVarNames
"Set the instance variables for the receiver to be those
--- orig/libgst/comp.c
+++ mod/libgst/comp.c
@@ -215,10 +215,6 @@ static mst_Boolean compile_statements (t
them into a symbol OOP and returns that symbol. */
static OOP compute_selector (tree_node selectorExpr);
-/* Given a tree_node of type TREE_KEYWORD_LIST, pick out and concatenate
- the keywords, turn them into a symbol OOP and return that symbol. */
-static OOP compute_keyword_selector (tree_node selectorExpr);
-
/* Given CONSTEXPR, a section of the syntax tree that represents a
Smalltalk constant, this routine creates and returns an OOP to be
stored as a method literal in the method that's currently being
@@ -2252,11 +2248,11 @@ compute_selector (tree_node selectorExpr
|| selectorExpr->nodeType == TREE_BINARY_EXPR)
return (selectorExpr->v_expr.selector);
else
- return (compute_keyword_selector (selectorExpr->v_expr.expression));
+ return (_gst_compute_keyword_selector (selectorExpr->v_expr.expression));
}
OOP
-compute_keyword_selector (tree_node keywordList)
+_gst_compute_keyword_selector (tree_node keywordList)
{
tree_node keyword;
int len;
@@ -2296,7 +2292,7 @@ _gst_make_attribute (tree_node attribute
if (_gst_had_error)
return _gst_nil_oop;
- selectorOOP = compute_keyword_selector (attribute_keywords);
+ selectorOOP = _gst_compute_keyword_selector (attribute_keywords);
numArgs = list_length (attribute_keywords);
argsArray = new_instance_with (_gst_array_class, numArgs, &argsArrayOOP);
INC_ADD_OOP (argsArrayOOP);
--- orig/libgst/comp.h
+++ mod/libgst/comp.h
@@ -264,6 +264,11 @@ extern mst_Boolean _gst_had_error
extern mst_Boolean _gst_untrusted_methods
ATTRIBUTE_HIDDEN;
+/* Given a tree_node of type TREE_KEYWORD_LIST, pick out and concatenate
+ the keywords, turn them into a symbol OOP and return that symbol. */
+extern OOP _gst_compute_keyword_selector (tree_node selectorExpr)
+ ATTRIBUTE_HIDDEN;
+
/* Called to compile and execute an "immediate expression"; i.e. a Smalltalk
statement that is not part of a method definition and where temporaries are
declared automatically. The parse trees are in TEMPS and STATEMENTS.
--- orig/libgst/gst-parse.c
+++ mod/libgst/gst-parse.c
@@ -64,7 +64,7 @@ typedef enum expr_kinds {
EXPR_CASCADED = EXPR_GREATER | EXPR_BINOP | EXPR_KEYWORD,
EXPR_ANY = 31
} expr_kinds;
-
+
/* Used to communicate with the #methodsFor: primitive. */
gst_parser *_gst_current_parser;
@@ -73,14 +73,16 @@ static inline mst_Boolean is_unlikely_se
/* Lexer interface. */
+static inline void lex_init (gst_parser *p);
+static inline void lex_lookahead (gst_parser *p, int n);
+static inline void lex_consume (gst_parser *p, int n);
static inline void lex (gst_parser *p);
-static inline void lex_must_be (gst_parser *p,
- int req_token);
-static inline void lex_skip_mandatory (gst_parser *p,
- int req_token);
-static inline mst_Boolean lex_skip_if (gst_parser *p,
- int req_token,
- mst_Boolean fail_at_eof);
+static inline int token (gst_parser *p, int n);
+static inline YYSTYPE *val (gst_parser *p, int n);
+static inline YYLTYPE *loc (gst_parser *p, int n);
+static inline void lex_must_be (gst_parser *p, int req_token);
+static inline void lex_skip_mandatory (gst_parser *p, int req_token);
+static inline mst_Boolean lex_skip_if (gst_parser *p, int req_token,
mst_Boolean fail_at_eof);
/* Error recovery. */
@@ -94,16 +96,37 @@ static int filprintf (Filament *fil,
/* Grammar productions. */
+static void parse_chunks (gst_parser *p);
static void parse_doit (gst_parser *p);
+static mst_Boolean parse_scoped_definition (gst_parser *p,
+ tree_node first_stmt);
+
+
+static void parse_eval_definition (gst_parser *p);
+
+static mst_Boolean parse_namespace_definition (gst_parser *p,
+ tree_node first_stmt);
+static mst_Boolean parse_class_definition (gst_parser *p,
+ OOP classOOP);
+static OOP parse_namespace (tree_node name);
+static OOP parse_class (tree_node list);
+static void parse_scoped_method (gst_parser *p,
+ OOP classOOP);
+static void parse_instance_variables (gst_parser *p,
+ OOP classOOP);
+
static void parse_method_list (gst_parser *p);
-static void parse_method (gst_parser *p);
+static void parse_method (gst_parser *p,
+ int at_end);
static tree_node parse_message_pattern (gst_parser *p);
static tree_node parse_keyword_variable_list (gst_parser *p);
static tree_node parse_variable (gst_parser *p);
static tree_node parse_attributes (gst_parser *p);
+static tree_node parse_attribute (gst_parser *p);
static tree_node parse_temporaries (gst_parser *p,
mst_Boolean implied_pipe);
static tree_node parse_statements (gst_parser *p,
+ tree_node first_stmt,
mst_Boolean accept_caret);
static tree_node parse_expression (gst_parser *p,
enum expr_kinds kind);
@@ -134,9 +157,10 @@ static tree_node parse_keyword_expressio
enum expr_kinds kind);
static tree_node parse_keyword_list (gst_parser *p,
enum expr_kinds kind);
-
-static int
+
+
+static int
filprintf (Filament *fil, const char *format, ...)
{
va_list ap;
@@ -149,13 +173,74 @@ filprintf (Filament *fil, const char *fo
return result;
}
+/* Lexer interface. Intialize the parser before using it. */
-/* Lexer interface. Get a token out of the stream. */
+static inline void
+lex_init (gst_parser *p)
+{
+ p->la_first = 0;
+ p->la_size = 0;
+ lex_lookahead (p, 1);
+}
+
+/* Lexer interface. Get N tokens out of the stream. */
+
+static inline void
+lex_lookahead (gst_parser *p, int n)
+{
+ while (p->la_size < n)
+ {
+ int i = (p->la_first + p->la_size) % 4;
+ assert (p->la_size == 0 || token (p, p->la_size - 1) != EOF);
+ p->la[i].token = _gst_yylex (&p->la[i].val, &p->la[i].loc);
+ p->la_size++;
+ }
+}
+
+/* Lexer interface. Eat the first N lookahead tokens. */
+
+static inline void
+lex_consume (gst_parser *p, int n)
+{
+ p->la_first = (p->la_first + n) % 4;
+ p->la_size -= n;
+}
+
+/* Lexer interface. Eat the last lookahead token and lex the next one */
static inline void
lex (gst_parser *p)
{
- p->token = _gst_yylex (&p->val, &p->loc);
+ lex_consume (p, 1);
+ lex_lookahead (p, 1);
+}
+
+/* Lexer interface. Return the N-th lookahead token. */
+
+static inline int
+token (gst_parser *p, int n)
+{
+ int i = (p->la_first + n) % 4;
+ return p->la[i].token;
+}
+
+/* Lexer interface. Return the value of the N-th lookahead token. */
+
+static inline YYSTYPE*
+val (gst_parser *p, int n)
+{
+ int i = (p->la_first + n) % 4;
+ return &p->la[i].val;
+}
+
+
+/* Lexer interface. Return the location of the N-th lookahead token. */
+
+static inline YYLTYPE*
+loc (gst_parser *p, int n)
+{
+ int i = (p->la_first + n) % 4;
+ return &p->la[i].loc;
}
/* Lexer interface. Check that the next token is REQ_TOKEN and fail if
@@ -164,7 +249,7 @@ lex (gst_parser *p)
static inline void
lex_must_be (gst_parser *p, int req_token)
{
- if (p->token != req_token)
+ if (token (p, 0) != req_token)
expected (p, req_token, -1);
}
@@ -174,7 +259,7 @@ lex_must_be (gst_parser *p, int req_toke
static inline void
lex_skip_mandatory (gst_parser *p, int req_token)
{
- if (p->token != req_token)
+ if (token (p, 0) != req_token)
expected (p, req_token, -1);
else
lex (p);
@@ -186,9 +271,9 @@ lex_skip_mandatory (gst_parser *p, int r
static inline mst_Boolean
lex_skip_if (gst_parser *p, int req_token, mst_Boolean fail_at_eof)
{
- if (p->token != req_token)
+ if (token (p, 0) != req_token)
{
- if (p->token == EOF && fail_at_eof)
+ if (token (p, 0) == EOF && fail_at_eof)
expected (p, req_token, -1);
return false;
}
@@ -199,6 +284,21 @@ lex_skip_if (gst_parser *p, int req_toke
}
}
+
+void
+_gst_print_tokens (gst_parser *p)
+{
+ int i;
+ printf ("size: %i\n", p->la_size);
+ for (i = 0; i < p->la_size; i++) {
+ if (token (p, i) == 264)
+ printf ("%i - %i - %s\n", i, token (p, i), val (p, i)->sval);
+ else
+ printf ("%i - %i\n", i, token (p, i));
+ }
+ printf ("\n");
+}
+
/* Top of the descent. */
void
@@ -207,9 +307,9 @@ _gst_parse_method ()
gst_parser p, *prev_parser = _gst_current_parser;
_gst_current_parser = &p;
p.state = PARSE_METHOD;
- lex (&p);
+ lex_init (&p);
if (setjmp (p.recover) == 0)
- parse_method (&p);
+ parse_method (&p, EOF);
else
_gst_had_error = false;
@@ -222,26 +322,41 @@ _gst_parse_chunks ()
gst_parser p, *prev_parser = _gst_current_parser;
_gst_current_parser = &p;
- p.state = PARSE_DOIT;
- lex (&p);
- if (p.token == SHEBANG)
+
+ lex_init (&p);
+ if (token (&p, 0) == SHEBANG)
lex (&p);
+ p.state = PARSE_DOIT;
setjmp (p.recover);
_gst_had_error = false;
- while (p.token != EOF)
- {
- /* Pick the production here, so that subsequent methods are compiled
- when we come back from an error above. */
- if (p.state == PARSE_METHOD_LIST)
- parse_method_list (&p);
- else
- parse_doit (&p);
- }
+ while (token (&p, 0) != EOF)
+ parse_chunks (&p);
_gst_current_parser = prev_parser;
}
-
+
+static void
+parse_chunks (gst_parser *p)
+{
+ if (lex_skip_if (p, '!', false))
+ p->state = PARSE_DOIT;
+ else
+ {
+ OOP oldTemporaries = _gst_push_temporaries_dictionary ();
+ while (token (p, 0) != EOF && token (p, 0) != ']' && token (p, 0) != '!')
+ {
+ /* Pick the production here, so that subsequent
+ methods are compiled when we come back from an error above. */
+ if (p->state == PARSE_METHOD_LIST)
+ parse_method_list (p);
+ else
+ parse_doit (p);
+ }
+ _gst_pop_temporaries_dictionary (oldTemporaries);
+ }
+}
+
/* Print an error message and attempt error recovery. All the parameters
after P (terminated by -1) are tokens that were expected (possibly a
@@ -263,7 +378,7 @@ expected (gst_parser *p, int token, ...)
{
if (token < 256)
{
- filprintf (out_fil, "%s '%c'", sep, token);
+ filprintf (out_fil, "%s '%c'", sep, token);
sep = " or";
}
else
@@ -285,7 +400,7 @@ expected (gst_parser *p, int token, ...)
#undef TOKEN_DEF
#undef TOKEN_SEP
- msg = fildelete (out_fil);
+ msg = fildelete (out_fil);
_gst_errorf ("%s", msg);
free (msg);
recover_error (p);
@@ -301,86 +416,541 @@ recover_error (gst_parser *p)
for (;;)
{
/* Find the final bang. */
- if (p->token == EOF)
- break;
- if (p->token == '!')
+ if (token (p, 0) == EOF)
+ break;
+ if (token (p, 0) == '!')
{
_gst_free_tree ();
- lex (p);
+ lex (p);
break;
}
- lex (p);
+ lex (p);
}
longjmp (p->recover, 1);
}
-
/* doit: temporaries statements '!' [ method_list '!' ]
- | empty */
+ | empty */
static void
parse_doit (gst_parser *p)
{
- mst_Boolean first = true;
- OOP oldTemporaries = _gst_push_temporaries_dictionary ();
- tree_node temps, statement;
+ tree_node statement = NULL;
+ mst_Boolean caret;
- do
- {
- temps = parse_temporaries (p, false);
- lex_skip_if (p, '^', false);
- statement = parse_expression (p, EXPR_ANY);
+ if (token (p, 0) == '|')
+ parse_temporaries (p, false);
- if (p->token != '.' && p->token != EOF && p->token != '!')
- expected (p, '.', '!', -1);
+ if (token (p, 0) == EOF)
+ return;
- /* When regression testing, don't print intermediate values. */
- if (statement && !_gst_had_error)
+ caret = lex_skip_if (p, '^', false);
+ statement = parse_expression (p, EXPR_ANY);
+ if (!caret && lex_skip_if (p, '[', false))
+ {
+ if (parse_scoped_definition (p, statement))
+ lex_skip_mandatory (p, ']');
+ else
{
- if (first
- && _gst_kernel_initialized
- && (_gst_regression_testing
- || (_gst_get_cur_stream_prompt () && _gst_verbosity >= 3)))
- {
- printf ("\nExecution begins...\n");
- first = false;
- }
+ while (!lex_skip_if (p, ']', true))
+ lex (p);
+ }
+ }
+ else
+ {
+ _gst_execute_statements (NULL, statement, UNDECLARED_TEMPORARIES, false);
+ _gst_free_tree ();
+ }
+
+ _gst_had_error = false;
+
+ /* Do not lex until after _gst_free_tree, or we lose a token! */
+ lex_skip_if (p, '.', false);
+ lex_skip_if (p, '!', false);
+}
+
- _gst_execute_statements (NULL, statement, UNDECLARED_TEMPORARIES,
- _gst_regression_testing);
+/* scoped_definition: eval_definition
+ | class_definition
+ | namespace_definition */
+
+static mst_Boolean
+parse_scoped_definition (gst_parser *p, tree_node first_stmt)
+{
+ OOP classOOP = NULL;
+ tree_node receiver = first_stmt->v_expr.receiver;
+ tree_node expression = first_stmt->v_expr.expression;
+
+#if 0
+ _gst_print_tree (first_stmt, 0);
+#endif
+
+ if (first_stmt->nodeType == TREE_VARIABLE_NODE
+ && strcmp (first_stmt->v_list.name, "Eval") == 0)
+ {
+ parse_eval_definition (p);
+ return true;
+ }
+
+ if (first_stmt->nodeType == TREE_KEYWORD_EXPR
+ && receiver->nodeType == TREE_VARIABLE_NODE
+ && expression->v_list.value->nodeType == TREE_VARIABLE_NODE
+ && expression->v_list.next == NULL)
+ {
+ if (strcmp (receiver->v_list.name, "Namespace") == 0
+ && strcmp (expression->v_list.name, "current:") == 0)
+ return parse_namespace_definition (p, first_stmt);
+
+ if (strcmp (expression->v_list.name, "subclass:") == 0
+ && (classOOP = parse_class (receiver)) != NULL)
+ {
+ const char * name = expression->v_list.value->v_list.name;
+ _gst_msg_sendf (&classOOP, "%o %o subclass: %S", classOOP, name);
+
+ if (IS_NIL (classOOP))
+ _gst_had_error = true;
+ else
+ return parse_class_definition (p, classOOP);
}
+ }
- _gst_free_tree ();
- _gst_had_error = false;
+ else if (first_stmt->nodeType == TREE_UNARY_EXPR
+ && first_stmt->v_expr.selector == _gst_intern_string ("extend"))
+ {
+
+ if (receiver->nodeType == TREE_VARIABLE_NODE)
+ classOOP = parse_class (receiver);
+
+ else if (receiver->nodeType == TREE_UNARY_EXPR
+ && receiver->v_expr.selector == _gst_intern_string ("class"))
+ {
+ classOOP = parse_class (receiver->v_expr.receiver);
+ classOOP = OOP_CLASS (classOOP);
+ }
- /* Do not lex until after _gst_free_tree, or we lose a token! */
- lex_skip_if (p, '.', false);
+ if (classOOP != NULL)
+ return parse_class_definition (p, classOOP);
}
- while (p->token != '!' && p->token != EOF);
- if (_gst_regression_testing && !first)
- printf ("returned value is %O\n", _gst_last_returned_value);
+ _gst_errorf ("expected Eval, Namespace or class definition");
+ return false;
+}
- while (p->token == '!')
- lex (p);
+static void
+parse_eval_definition (gst_parser *p)
+{
+ tree_node tmps = NULL, stmts;
+ tree_node first_stmt = NULL;
+ OOP oldDictionary = _gst_push_temporaries_dictionary ();
+
+ tmps = parse_temporaries (p, false);
+ stmts = parse_statements (p, first_stmt, true);
+ if (stmts && !_gst_had_error)
+ {
+ if (_gst_regression_testing)
+ printf ("\nExecution begins...\n");
+
+ _gst_execute_statements (tmps, stmts, UNDECLARED_TEMPORARIES,
+ _gst_regression_testing);
- _gst_pop_temporaries_dictionary (oldTemporaries);
+ if (_gst_regression_testing && !_gst_had_error)
+ printf ("returned value is %O\n", _gst_last_returned_value);
+ }
+
+ _gst_pop_temporaries_dictionary (oldDictionary);
+ _gst_free_tree ();
+ _gst_had_error = false;
}
+static mst_Boolean
+parse_namespace_definition (gst_parser *p, tree_node first_stmt)
+{
+ tree_node expr = first_stmt->v_expr.expression;
+ OOP new_namespace = parse_namespace (expr->v_list.value);
+
+ if (new_namespace)
+ {
+ OOP old_namespace = _gst_current_namespace;
+ _gst_register_oop (old_namespace);
+
+ _gst_msg_sendf (NULL, "%v %o current: %o",
+ _gst_namespace_class, new_namespace);
+
+ parse_eval_definition (p);
+
+ _gst_msg_sendf (NULL, "%v %o current: %o",
+ _gst_namespace_class, old_namespace);
+
+ _gst_unregister_oop (old_namespace);
+ return true;
+ }
+
+ return false;
+}
+
+static mst_Boolean
+parse_class_definition (gst_parser *p, OOP classOOP)
+{
+ int t1, t2, t3;
+
+ for (;;)
+ {
+ if (_gst_had_error)
+ break;
+
+ lex_lookahead (p, 1);
+ if (token (p, 0) == ']' || token (p, 0) == EOF)
+ break;
+
+ lex_lookahead (p, 3);
+#if 0
+ print_tokens (p);
+#endif
+
+ t1 = token (p, 0);
+ t2 = token (p, 1);
+ t3 = token (p, 2);
+
+ switch (t1)
+ {
+ case '>':
+ case BINOP:
+ case KEYWORD:
+#if 0
+ printf ("parse method\n");
+#endif
+
+ _gst_set_compilation_class (classOOP);
+ parse_method (p, ']');
+ _gst_reset_compilation_category ();
+ break;
+
+ case '<':
+ if (t2 == IDENTIFIER)
+ {
+#if 0
+ printf ("parse method\n");
+#endif
+
+ _gst_set_compilation_class (classOOP);
+ parse_method (p, ']');
+ _gst_reset_compilation_category ();
+ }
+ else if (t2 == KEYWORD)
+ {
+ OOP selectorOOP, args[1];
+ tree_node keyword, value;
+
+#if 0
+ printf ("parse attribute\n");
+#endif
+ lex_skip_mandatory (p, '<');
+ keyword = parse_keyword_expression (p, NULL, EXPR_KEYWORD);
+ if (keyword->v_expr.expression->v_list.next != NULL)
+ _gst_errorf ("expected one keyword only");
+ else
+ {
+ value = keyword->v_expr.expression->v_list.value;
+ selectorOOP = _gst_compute_keyword_selector
(keyword->v_expr.expression);
+ value = _gst_make_statement_list (&value->location, value);
+ args[0] = _gst_execute_statements (NULL, value,
+ UNDECLARED_NONE, true);
+
+ if (!args[0])
+ _gst_had_error = true;
+
+ if (!_gst_had_error)
+ _gst_nvmsg_send (classOOP, selectorOOP, args, 1);
+ }
+
+ lex_skip_mandatory (p, '>');
+ }
+ else
+ _gst_errorf ("invalid class body element");
+ break;
+
+ case IDENTIFIER:
+ if (t2 == ASSIGNMENT)
+ {
+#if 0
+ printf ("parse class variable\n");
+#endif
+
+ OOP name, class_var_dict, result;
+ tree_node stmt;
+
+ name = _gst_intern_string (val (p, 0)->sval);
+
+ lex_skip_mandatory (p, IDENTIFIER);
+ lex_skip_mandatory (p, ASSIGNMENT);
+
+ class_var_dict = _gst_class_variable_dictionary (classOOP);
+
+ stmt = parse_expression (p, EXPR_ANY);
+ stmt = _gst_make_statement_list (&stmt->location, stmt);
+ result = _gst_execute_statements (NULL, stmt, UNDECLARED_NONE,
+ true);
+
+ assert (result || _gst_had_error);
+ if (!_gst_had_error)
+ DICTIONARY_AT_PUT (class_var_dict, name, result);
+
+ if (token (p, 0) != ']')
+ lex_skip_mandatory(p, '.');
+ }
+ else if (t2 == BINOP)
+ {
+#if 0
+ printf ("parse method\n");
+#endif
+ parse_scoped_method (p, classOOP);
+ }
+ else if (t2 == '[')
+ {
+#if 0
+ printf ("parse method\n");
+#endif
+
+ _gst_set_compilation_class (classOOP);
+ parse_method (p, ']');
+ _gst_reset_compilation_category ();
+ }
+ else if (t2 == SCOPE_SEPARATOR)
+ {
+#if 0
+ printf ("parse method qualified name\n");
+#endif
+
+ parse_scoped_method (p, classOOP);
+ }
+ else if (t2 == IDENTIFIER)
+ {
+ if (t3 == BINOP)
+ {
+#if 0
+ printf ("parse class method\n");
+#endif
+ parse_scoped_method (p, classOOP);
+ }
+ else if (t3 == '['
+ && strcmp (val (p, 0)->sval, "Class") == 0
+ && strcmp (val (p, 1)->sval, "protocol") == 0)
+ {
+#if 0
+ printf ("parse class protocol\n");
+#endif
+ if (_gst_object_is_kind_of (classOOP, _gst_metaclass_class))
+ _gst_errorf ("already on class side, Class protocol
invalid");
+ else
+ {
+ lex_consume (p, 3);
+ parse_class_definition (p, OOP_CLASS (classOOP));
+ lex_skip_mandatory (p, ']');
+ }
+ }
+ else
+ {
+ _gst_errorf("invalid class body element");
+ lex_consume (p, p->la_size);
+ return false;
+ }
+ }
+ break;
+
+ case '|':
+ if (t2 == '|')
+ {
+#if 0
+ printf ("parse instance variables - ignore\n");
+#endif
+ lex_consume (p, 2);
+ }
+ else if (t2 == IDENTIFIER)
+ {
+ if (t3 == IDENTIFIER || t3 == '|')
+ {
+#if 0
+ printf ("parse instance variables\n");
+#endif
+ parse_instance_variables (p, classOOP);
+ }
+ else if (t3 == '[')
+ {
+#if 0
+ printf ("parse method\n");
+#endif
+ _gst_set_compilation_class (classOOP);
+ parse_method (p, ']');
+ _gst_reset_compilation_category ();
+ }
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+static void
+parse_scoped_method (gst_parser *p, OOP classOOP)
+{
+ OOP class;
+ tree_node class_node;
+ mst_Boolean class_method = false;
+
+ class_node = parse_variable_primary (p);
+ class = parse_class (class_node);
+
+ if (token (p, 0) == IDENTIFIER)
+ {
+ if ((strcmp (val (p, 0)->sval, "class") == 0))
+ {
+ class_method = true;
+ lex_skip_mandatory (p, IDENTIFIER);
+ }
+ else
+ _gst_errorf("expected `class' or `>>'");
+ }
+
+ lex_must_be (p, BINOP);
+ if (strcmp (val (p, 0)->sval, ">>") == 0)
+ lex_skip_mandatory (p, BINOP);
+ else
+ _gst_errorf ("expected `>>'");
+
+ if (_gst_class_is_kind_of (classOOP, class))
+ {
+ if (class_method)
+ class = OOP_CLASS (class);
+
+ _gst_set_compilation_class (class);
+ parse_method (p, ']');
+ _gst_reset_compilation_category ();
+ }
+ else
+ _gst_errorf ("%O is not %O or one of its superclasses",
+ ((gst_class) OOP_TO_OBJ (class))->name,
+ ((gst_class) OOP_TO_OBJ (classOOP))->name);
+}
+
+static OOP
+parse_class (tree_node list)
+{
+ const char* name;
+ OOP currentOOP = _gst_current_namespace;
+
+ do
+ {
+ name = list->v_list.name;
+ currentOOP = dictionary_at (currentOOP, _gst_intern_string (name));
+
+ if (currentOOP == _gst_nil_oop)
+ {
+ _gst_errorf ("key %s not found", name);
+ return NULL;
+ }
+
+ list = list->v_list.next;
+
+ if (list == NULL)
+ {
+ if (!_gst_object_is_kind_of (currentOOP, _gst_class_class))
+ {
+ _gst_errorf ("expected class named %s, found %O",
+ name, OOP_INT_CLASS (currentOOP));
+ return NULL;
+ }
+ }
+ else
+ {
+ if (!_gst_object_is_kind_of (currentOOP, _gst_dictionary_class))
+ {
+ _gst_errorf ("expected namespace named %s, found %O",
+ name, OOP_INT_CLASS (currentOOP));
+ return NULL;
+ }
+ }
+ }
+ while (list != NULL);
+
+ return currentOOP;
+}
+
+static OOP
+parse_namespace (tree_node list)
+{
+ OOP name, new_namespace, current_namespace;
+ const char *namespc;
+
+ current_namespace = _gst_current_namespace;
+ while (list->v_list.next != NULL)
+ {
+ name = _gst_intern_string (list->v_list.name);
+ current_namespace = dictionary_at (current_namespace, name);
+
+ if (current_namespace == _gst_nil_oop)
+ {
+ _gst_errorf ("key %s not found", list->v_list.name);
+ return NULL;
+ }
+
+ if (!_gst_object_is_kind_of (current_namespace, _gst_dictionary_class))
+ {
+ _gst_errorf ("expected namespace named %s, found %O",
+ list->v_list.name, OOP_INT_CLASS (current_namespace));
+ return NULL;
+ }
+
+ list = list->v_list.next;
+ }
+
+ namespc = list->v_list.name;
+ name = _gst_intern_string (namespc);
+ new_namespace = dictionary_at (current_namespace, name);
+
+ if (new_namespace == _gst_nil_oop)
+ _gst_msg_sendf (¤t_namespace, "%o %o addSubspace: %o",
+ current_namespace, name);
+
+ else if (_gst_object_is_kind_of (new_namespace, _gst_dictionary_class))
+ current_namespace = new_namespace;
+
+ else
+ _gst_errorf ("expected namespace named %s, found %o", namespc,
+ OOP_INT_CLASS (new_namespace));
+
+ return current_namespace;
+}
/* method_list: method_list method '!'
- | empty */
+ | empty */
static void
-parse_method_list (gst_parser *p)
+parse_instance_variables (gst_parser *p, OOP classOOP)
{
- while (p->token != '!')
+ char *vars;
+ Filament *fil = filnew (NULL, 0);
+
+ lex_skip_mandatory (p, '|');
+ while (!lex_skip_if (p, '|', true))
{
- parse_method (p);
- lex_skip_mandatory (p, '!');
+ lex_must_be (p, IDENTIFIER);
+ filprintf (fil, "%s ", val (p, 0)->sval);
+ lex (p);
}
+ vars = fildelete (fil);
+ _gst_msg_sendf (NULL, "%v %o instanceVariableNames: %S", classOOP, vars);
+ free (vars);
+}
+
+static void
+parse_method_list (gst_parser *p)
+{
+ while (token (p, 0) != '!')
+ parse_method (p, '!');
+
lex (p);
_gst_skip_compilation = false;
_gst_reset_compilation_category ();
@@ -391,15 +961,27 @@ parse_method_list (gst_parser *p)
/* method: message_pattern temporaries attributes statements */
static void
-parse_method (gst_parser *p)
+parse_method (gst_parser *p, int at_end)
{
- tree_node pat = parse_message_pattern (p);
- tree_node temps = parse_temporaries (p, false);
- tree_node attrs = parse_attributes (p);
- tree_node stmts = parse_statements (p, true);
- YYLTYPE current_pos = _gst_get_location ();
- tree_node method = _gst_make_method (&pat->location, ¤t_pos,
- pat, temps, attrs, stmts);
+ tree_node pat, temps, attrs, stmts;
+ YYLTYPE current_pos;
+ tree_node method;
+
+ pat = parse_message_pattern (p);
+
+ if (at_end == ']')
+ lex_skip_mandatory (p, '[');
+
+ temps = parse_temporaries (p, false);
+ attrs = parse_attributes (p);
+ stmts = parse_statements (p, NULL, true);
+
+ /* Don't lex until _gst_free_tree, or we lose a token. */
+ lex_must_be (p, at_end);
+
+ current_pos = _gst_get_location ();
+ method = _gst_make_method (&pat->location, ¤t_pos,
+ pat, temps, attrs, stmts);
if (!_gst_had_error && !_gst_skip_compilation)
{
@@ -411,31 +993,33 @@ parse_method (gst_parser *p)
_gst_free_tree ();
_gst_had_error = false;
+ if (at_end != EOF)
+ lex (p);
}
/* message_pattern: unary_pattern
- | binary_pattern
- | keyword_pattern
+ | binary_pattern
+ | keyword_pattern
unary_pattern: IDENTIFIER
binary_pattern: binop IDENTIFIER
keyword_pattern: keyword_pattern KEYWORD IDENTIFIER
- | KEYWORD IDENTIFIER
+ | KEYWORD IDENTIFIER
binop : BINOP | '<' | '>' | '|' */
static tree_node
parse_message_pattern (gst_parser *p)
{
- YYLTYPE loc = p->loc;
+ YYLTYPE location = *loc (p, 0);
tree_node pat, arg;
- char *sval = p->val.sval;
+ char *sval = val(p, 0)->sval;
- switch (p->token)
+ switch (token (p, 0))
{
case IDENTIFIER:
lex (p);
- pat = _gst_make_unary_expr (&loc, NULL, sval);
+ pat = _gst_make_unary_expr (&location, NULL, sval);
break;
case BINOP:
@@ -444,12 +1028,12 @@ parse_message_pattern (gst_parser *p)
case '|':
lex (p);
arg = parse_variable (p);
- pat = _gst_make_binary_expr (&loc, NULL, sval, arg);
+ pat = _gst_make_binary_expr (&location, NULL, sval, arg);
break;
case KEYWORD:
pat = parse_keyword_variable_list (p);
- pat = _gst_make_keyword_expr (&loc, NULL, pat);
+ pat = _gst_make_keyword_expr (&location, NULL, pat);
break;
default:
@@ -462,17 +1046,17 @@ parse_message_pattern (gst_parser *p)
static tree_node
parse_keyword_variable_list (gst_parser *p)
{
- YYLTYPE loc = p->loc;
+ YYLTYPE location = *loc (p, 0);
tree_node pat = NULL, arg;
do
{
- char *sval = p->val.sval;
+ char *sval = val(p, 0)->sval;
lex (p);
arg = parse_variable (p);
- pat = _gst_add_node (pat, _gst_make_keyword_list (&loc, sval, arg));
+ pat = _gst_add_node (pat, _gst_make_keyword_list (&location, sval, arg));
}
- while (p->token == KEYWORD);
+ while (token (p, 0) == KEYWORD);
return pat;
}
@@ -486,30 +1070,26 @@ parse_variable (gst_parser *p)
tree_node var;
lex_must_be (p, IDENTIFIER);
- var = _gst_make_variable (&p->loc, p->val.sval);
+ var = _gst_make_variable (loc (p, 0), val(p, 0)->sval);
lex (p);
return var;
}
/* attributes: attributes '<' attribute_keywords '>'
- | empty
+ | empty
attribute_keywords: attribute KEYWORD binary_expr
- | KEYWORD binary_expr */
+ | KEYWORD binary_expr */
static tree_node
parse_attributes (gst_parser *p)
{
tree_node attrs = NULL;
- while (lex_skip_if (p, '<', false))
+ while (token (p, 0) == '<')
{
- tree_node attr;
- lex_must_be (p, KEYWORD);
- attr = parse_keyword_list (p, EXPR_BINOP);
- attr = _gst_make_attribute_list (&attr->location, attr);
- lex_skip_mandatory (p, '>');
+ tree_node attr = parse_attribute (p);
if (attr)
attrs = _gst_add_node (attrs, attr);
}
@@ -517,12 +1097,24 @@ parse_attributes (gst_parser *p)
return attrs;
}
+static tree_node
+parse_attribute (gst_parser *p)
+{
+ tree_node attr;
+ lex_skip_mandatory (p, '<');
+ lex_must_be (p, KEYWORD);
+ attr = parse_keyword_list (p, EXPR_BINOP);
+ attr = _gst_make_attribute_list (&attr->location, attr);
+ lex_skip_mandatory (p, '>');
+ return attr;
+}
+
/* temporaries: '|' variables '|'
- | empty
+ | empty
temp_no_pipe: variables '|'
variables: variables variable
- | empty */
+ | empty */
static tree_node
parse_temporaries (gst_parser *p, mst_Boolean implied_pipe)
@@ -534,7 +1126,7 @@ parse_temporaries (gst_parser *p, mst_Bo
while (!lex_skip_if (p, '|', true))
{
tree_node temp;
- if (p->token != IDENTIFIER)
+ if (token (p, 0) != IDENTIFIER)
expected (p, '|', IDENTIFIER, -1);
temp = parse_variable (p);
temp = _gst_make_variable_list (&temp->location, temp);
@@ -546,25 +1138,34 @@ parse_temporaries (gst_parser *p, mst_Bo
/* statements: statements_no_ret return_statement opt_dot
- | statements_no_ret opt_dot
+ | statements_no_ret opt_dot
statements_no_ret: statements_no_ret '.' statement
- | empty
+ | empty
opt_dot: '.'
- | empty */
+ | empty */
static tree_node
-parse_statements (gst_parser *p, mst_Boolean accept_caret)
+parse_statements (gst_parser *p, tree_node first_stmt, mst_Boolean
accept_caret)
{
- tree_node stmts = NULL, stmt;
+ tree_node stmts, stmt;
mst_Boolean caret;
+ if (first_stmt)
+ {
+ stmts = _gst_make_statement_list (&first_stmt->location, first_stmt);
+ if (!lex_skip_if (p, '.', false))
+ return stmts;
+ }
+ else
+ stmts = NULL;
+
do
{
caret = accept_caret && lex_skip_if (p, '^', false);
stmt = parse_expression (p, EXPR_ANY);
if (caret)
{
- if (stmt == NULL)
+ if (stmt == NULL)
{
_gst_errorf ("expected statement after '^'");
recover_error (p);
@@ -587,8 +1188,8 @@ parse_statements (gst_parser *p, mst_Boo
/* expression: primary
- | variable ':=' expression
- | message_expression cascaded_messages */
+ | variable ':=' expression
+ | message_expression cascaded_messages */
static tree_node
parse_expression (gst_parser *p, enum expr_kinds kind)
@@ -596,9 +1197,9 @@ parse_expression (gst_parser *p, enum ex
tree_node node, assigns = NULL;
for (;;)
{
- if (p->token != IDENTIFIER)
+ if (token (p, 0) != IDENTIFIER)
{
- node = parse_primary (p);
+ node = parse_primary(p);
break;
}
else
@@ -627,17 +1228,17 @@ parse_expression (gst_parser *p, enum ex
/* primary: variable_primary
- | '(' expression ')'
- | literal
- | block
- | array_constructor */
+ | '(' expression ')'
+ | literal
+ | block
+ | array_constructor */
static tree_node
parse_primary (gst_parser *p)
{
tree_node node;
- switch (p->token)
+ switch (token (p, 0))
{
case IDENTIFIER:
node = parse_variable_primary (p);
@@ -672,21 +1273,21 @@ parse_primary (gst_parser *p)
default:
return NULL;
- }
+ }
return node;
}
/* variable_primary: variable_primary SCOPE_SEPARATOR IDENTIFIER
- | IDENTIFIER */
+ | IDENTIFIER */
static tree_node
parse_variable_primary_1 (gst_parser *p, YYLTYPE *first_loc,
const char *first_val)
{
tree_node node;
- assert (p->token == IDENTIFIER);
+ assert (token (p, 0) == IDENTIFIER);
node = _gst_make_variable (first_loc, first_val);
for (;;)
{
@@ -695,7 +1296,7 @@ parse_variable_primary_1 (gst_parser *p,
break;
lex_must_be (p, IDENTIFIER);
- node = _gst_add_node (node, _gst_make_variable (&p->loc, p->val.sval));
+ node = _gst_add_node (node, _gst_make_variable (loc (p, 0), val(p,
0)->sval));
}
return node;
@@ -704,20 +1305,20 @@ parse_variable_primary_1 (gst_parser *p,
static tree_node
parse_variable_primary (gst_parser *p)
{
- return parse_variable_primary_1 (p, &p->loc, p->val.sval);
+ return parse_variable_primary_1 (p, loc (p, 0), val(p, 0)->sval);
}
/* array_literal_elt: array_literal
- | byte_array_literal
- | literal
- | builtin_identifier
+ | byte_array_literal
+ | literal
+ | builtin_identifier
literal: <any literal token>
- | '#' array_literal
- | '#' byte_array_literal
- | '#' binding_constant
- | '#' '#' compile_time_constant */
+ | '#' array_literal
+ | '#' byte_array_literal
+ | '#' binding_constant
+ | '#' '#' compile_time_constant */
static tree_node
parse_literal (gst_parser *p, mst_Boolean array)
@@ -725,7 +1326,7 @@ parse_literal (gst_parser *p, mst_Boolea
tree_node node;
int ival;
- switch (p->token)
+ switch (token (p, 0))
{
case '(':
assert (array);
@@ -742,47 +1343,47 @@ parse_literal (gst_parser *p, mst_Boolea
return node;
case STRING_LITERAL:
- node = _gst_make_string_constant (&p->loc, p->val.sval);
+ node = _gst_make_string_constant (loc (p, 0), val(p, 0)->sval);
break;
case SYMBOL_LITERAL:
- node = _gst_intern_ident (&p->loc, p->val.sval);
- node = _gst_make_symbol_constant (&p->loc, node);
+ node = _gst_intern_ident (loc (p, 0), val(p, 0)->sval);
+ node = _gst_make_symbol_constant (loc (p, 0), node);
break;
case INTEGER_LITERAL:
- node = _gst_make_int_constant (&p->loc, p->val.ival);
+ node = _gst_make_int_constant (loc (p, 0), val(p, 0)->ival);
break;
case LARGE_INTEGER_LITERAL:
- node = _gst_make_byte_object_constant (&p->loc, p->val.boval);
+ node = _gst_make_byte_object_constant (loc (p, 0), val(p, 0)->boval);
break;
case FLOATD_LITERAL:
- node = _gst_make_float_constant (&p->loc, p->val.fval, CONST_FLOATD);
+ node = _gst_make_float_constant (loc (p, 0), val(p, 0)->fval,
CONST_FLOATD);
break;
case FLOATE_LITERAL:
- node = _gst_make_float_constant (&p->loc, p->val.fval, CONST_FLOATE);
+ node = _gst_make_float_constant (loc (p, 0), val(p, 0)->fval,
CONST_FLOATE);
break;
case FLOATQ_LITERAL:
- node = _gst_make_float_constant (&p->loc, p->val.fval, CONST_FLOATQ);
+ node = _gst_make_float_constant (loc (p, 0), val(p, 0)->fval,
CONST_FLOATQ);
break;
case SCALED_DECIMAL_LITERAL:
- node = _gst_make_oop_constant (&p->loc, p->val.oval);
+ node = _gst_make_oop_constant (loc (p, 0), val(p, 0)->oval);
break;
case CHAR_LITERAL:
- ival = p->val.ival;
+ ival = val(p, 0)->ival;
lex (p);
/* Special case $< INTEGER_LITERAL > where the integer literal
is positive. */
- if (ival == '<' && p->token == INTEGER_LITERAL && p->val.ival >= 0)
+ if (ival == '<' && token (p, 0) == INTEGER_LITERAL && val(p, 0)->ival >=
0)
{
- ival = p->val.ival;
+ ival = val(p, 0)->ival;
lex (p);
lex_skip_mandatory (p, '>');
@@ -793,11 +1394,11 @@ parse_literal (gst_parser *p, mst_Boolea
}
}
- return _gst_make_char_constant (&p->loc, ival);
+ return _gst_make_char_constant (loc (p, 0), ival);
case '#':
lex (p);
- switch (p->token)
+ switch (token (p, 0))
{
case '(':
case '[':
@@ -825,13 +1426,13 @@ parse_literal (gst_parser *p, mst_Boolea
/* array_literal: '(' array_literal_elts ')'
array_literal_elts: array_literal_elts array_literal_elt
- | empty */
+ | empty */
static tree_node
parse_array_literal (gst_parser *p)
{
tree_node elts = NULL;
- assert (p->token == '(');
+ assert (token (p, 0) == '(');
lex (p);
while (!lex_skip_if (p, ')', true))
@@ -842,7 +1443,7 @@ parse_array_literal (gst_parser *p)
elts = _gst_add_node (elts, _gst_make_array_elt (&lit->location, lit));
}
- return _gst_make_array_constant (elts ? &elts->location : &p->loc, elts);
+ return _gst_make_array_constant (elts ? &elts->location : loc (p, 0), elts);
}
@@ -853,18 +1454,18 @@ parse_builtin_identifier (gst_parser *p)
{
OOP symbolOOP;
tree_node node;
- YYLTYPE loc = p->loc;
+ YYLTYPE location = *loc(p,0);
- assert (p->token == IDENTIFIER);
- symbolOOP = _gst_intern_string (p->val.sval);
+ assert (token (p, 0) == IDENTIFIER);
+ symbolOOP = _gst_intern_string (val(p, 0)->sval);
if (symbolOOP == _gst_true_symbol)
- node = _gst_make_oop_constant (&loc, _gst_true_oop);
+ node = _gst_make_oop_constant (&location, _gst_true_oop);
else if (symbolOOP == _gst_false_symbol)
- node = _gst_make_oop_constant (&loc, _gst_false_oop);
+ node = _gst_make_oop_constant (&location, _gst_false_oop);
else if (symbolOOP == _gst_nil_symbol)
- node = _gst_make_oop_constant (&loc, _gst_nil_oop);
+ node = _gst_make_oop_constant (&location, _gst_nil_oop);
else
{
@@ -879,30 +1480,30 @@ parse_builtin_identifier (gst_parser *p)
/* byte_array_literal: '[' byte_array_literal_elts ']'
byte_array_literal_elts: byte_array_literal_elts INTEGER_LITERAL
- | empty */
+ | empty */
static tree_node
parse_byte_array_literal (gst_parser *p)
{
tree_node elts = NULL;
- assert (p->token == '[');
+ assert (token (p, 0) == '[');
lex (p);
while (!lex_skip_if (p, ']', true))
{
tree_node lit;
lex_must_be (p, INTEGER_LITERAL);
- if (p->val.ival < 0 || p->val.ival > 255)
+ if (val(p, 0)->ival < 0 || val(p, 0)->ival > 255)
{
_gst_errorf ("byte constant out of range");
recover_error (p);
}
- lit = _gst_make_int_constant (&p->loc, p->val.ival);
+ lit = _gst_make_int_constant (loc (p, 0), val(p, 0)->ival);
lex (p);
elts = _gst_add_node (elts, _gst_make_array_elt (&lit->location, lit));
}
- return _gst_make_byte_array_constant (elts ? &elts->location : &p->loc,
elts);
+ return _gst_make_byte_array_constant (elts ? &elts->location : loc (p, 0),
elts);
}
@@ -912,14 +1513,14 @@ static tree_node
parse_compile_time_constant (gst_parser *p)
{
tree_node temps, statements;
- YYLTYPE loc = p->loc;
+ YYLTYPE location = *loc(p,0);
OOP result = NULL;
- assert (p->token == '#');
+ assert (token (p, 0) == '#');
lex (p);
lex_skip_mandatory (p, '(');
temps = parse_temporaries (p, false);
- statements = parse_statements (p, true);
+ statements = parse_statements (p, NULL, true);
lex_skip_mandatory (p, ')');
if (statements && !_gst_had_error)
@@ -930,7 +1531,7 @@ parse_compile_time_constant (gst_parser
_gst_pop_temporaries_dictionary (oldDictionary);
}
- return _gst_make_oop_constant (&loc, result ? result : _gst_nil_oop);
+ return _gst_make_oop_constant (&location, result ? result : _gst_nil_oop);
}
@@ -941,7 +1542,7 @@ parse_binding_constant (gst_parser *p)
{
tree_node node;
- assert (p->token == '{');
+ assert (token (p, 0) == '{');
lex (p);
lex_must_be (p, IDENTIFIER);
node = parse_variable_primary (p);
@@ -957,38 +1558,38 @@ static tree_node
parse_array_constructor (gst_parser *p)
{
tree_node stmts;
- YYLTYPE loc = p->loc;
+ YYLTYPE location = *loc(p,0);
- assert (p->token == '{');
+ assert (token (p, 0) == '{');
lex (p);
- stmts = parse_statements (p, false);
+ stmts = parse_statements (p, NULL, false);
lex_skip_mandatory (p, '}');
- return _gst_make_array_constructor (&loc, stmts);
+ return _gst_make_array_constructor (&location, stmts);
}
/* block: block_vars '||' temps_no_pipe statements
- | block_vars '|' temporaries statements
- | temporaries statements */
+ | block_vars '|' temporaries statements
+ | temporaries statements */
static tree_node
parse_block (gst_parser *p)
{
- YYLTYPE loc = p->loc;
+ YYLTYPE location = *loc(p,0);
tree_node vars, temps, stmts;
mst_Boolean implied_pipe;
- assert (p->token == '[');
+ assert (token (p, 0) == '[');
lex (p);
- if (p->token == ':')
+ if (token (p, 0) == ':')
{
vars = parse_block_variables (p);
if (lex_skip_if (p, '|', true))
implied_pipe = false;
- else if (p->token == BINOP
- && p->val.sval[0] == '|' && p->val.sval[1] == '|')
+ else if (token (p, 0) == BINOP
+ && val(p, 0)->sval[0] == '|' && val(p, 0)->sval[1] == '|')
{
implied_pipe = true;
lex (p);
@@ -1003,21 +1604,21 @@ parse_block (gst_parser *p)
}
temps = parse_temporaries (p, implied_pipe);
- stmts = parse_statements (p, true);
+ stmts = parse_statements (p, NULL, true);
lex_skip_mandatory (p, ']');
- return _gst_make_block (&loc, vars, temps, stmts);
+ return _gst_make_block (&location, vars, temps, stmts);
}
/* block_vars: ':' IDENTIFIER
- | block_vars ':' IDENTIFIER */
+ | block_vars ':' IDENTIFIER */
static tree_node
parse_block_variables (gst_parser *p)
{
tree_node vars = NULL;
- assert (p->token == ':');
+ assert (token (p, 0) == ':');
while (lex_skip_if (p, ':', false))
vars = _gst_add_node (vars, parse_variable (p));
@@ -1027,18 +1628,18 @@ parse_block_variables (gst_parser *p)
/* message_expression: unary_expression
- | binary_expression
- | keyword_expression
+ | binary_expression
+ | keyword_expression
unary_expression: primary unary_message
- | unary_expression unary_message
+ | unary_expression unary_message
unary_message: IDENTIFIER
binary_expression: unary_expression binop unary_expression
- | binary_expression binop unary_expression
+ | binary_expression binop unary_expression
keyword_expression: binary_expression KEYWORD binary_expression
- | keyword_expression KEYWORD binary_expression */
+ | keyword_expression KEYWORD binary_expression */
static tree_node
parse_message_expression (gst_parser *p, tree_node receiver, enum expr_kinds
kind)
@@ -1047,29 +1648,29 @@ parse_message_expression (gst_parser *p,
int n;
for (n = 0; ; n++)
{
- switch (p->token)
- {
- case IDENTIFIER:
- node = parse_unary_expression (p, node, kind & ~EXPR_CASCADE);
- break;
-
- case '>':
+ switch (token (p, 0))
+ {
+ case IDENTIFIER:
+ node = parse_unary_expression (p, node, kind & ~EXPR_CASCADE);
+ break;
+
+ case '>':
if ((kind & EXPR_GREATER) == 0)
return node;
- case BINOP:
- case '<':
- case '|':
+ case BINOP:
+ case '<':
+ case '|':
if ((kind & EXPR_BINOP) == 0)
return node;
- node = parse_binary_expression (p, node, kind & ~EXPR_CASCADE);
- break;
+ node = parse_binary_expression (p, node, kind & ~EXPR_CASCADE);
+ break;
- case KEYWORD:
+ case KEYWORD:
if ((kind & EXPR_KEYWORD) == 0)
return node;
- node = parse_keyword_expression (p, node, kind & ~EXPR_CASCADE);
- break;
+ node = parse_keyword_expression (p, node, kind & ~EXPR_CASCADE);
+ break;
case ';':
if (n == 0 || (kind & EXPR_CASCADE) == 0)
@@ -1077,9 +1678,9 @@ parse_message_expression (gst_parser *p,
return _gst_make_cascaded_message (&node->location, node,
parse_cascaded_messages (p));
- default:
- return node;
- }
+ default:
+ return node;
+ }
}
abort ();
@@ -1087,7 +1688,7 @@ parse_message_expression (gst_parser *p,
/* cascaded_messages: cascaded_messages ';' message_expression
- | empty */
+ | empty */
static tree_node
parse_cascaded_messages (gst_parser *p)
@@ -1096,27 +1697,27 @@ parse_cascaded_messages (gst_parser *p)
while (lex_skip_if (p, ';', false))
{
tree_node node;
- switch (p->token)
+ switch (token (p, 0))
{
- case IDENTIFIER:
- node = parse_unary_expression (p, NULL, EXPR_CASCADED);
- break;
-
- case '>':
- case BINOP:
- case '<':
- case '|':
- node = parse_binary_expression (p, NULL, EXPR_CASCADED);
- break;
-
- case KEYWORD:
- node = parse_keyword_expression (p, NULL, EXPR_CASCADED);
- break;
+ case IDENTIFIER:
+ node = parse_unary_expression (p, NULL, EXPR_CASCADED);
+ break;
- default:
+ case '>':
+ case BINOP:
+ case '<':
+ case '|':
+ node = parse_binary_expression (p, NULL, EXPR_CASCADED);
+ break;
+
+ case KEYWORD:
+ node = parse_keyword_expression (p, NULL, EXPR_CASCADED);
+ break;
+
+ default:
/* After a semicolon, we can expect a message send. */
- expected (p, IDENTIFIER, BINOP, KEYWORD, -1);
- }
+ expected (p, IDENTIFIER, BINOP, KEYWORD, -1);
+ }
node = _gst_make_message_list (&node->location, node);
cascade = _gst_add_node (cascade, node);
@@ -1131,15 +1732,15 @@ parse_cascaded_messages (gst_parser *p)
static tree_node
parse_unary_expression (gst_parser *p, tree_node receiver, enum expr_kinds
kind)
{
- YYLTYPE loc = receiver ? receiver->location : p->loc;
+ YYLTYPE location = receiver ? receiver->location : *loc(p,0);
char *sel;
- assert (p->token == IDENTIFIER);
- sel = p->val.sval;
+ assert (token (p, 0) == IDENTIFIER);
+ sel = val(p, 0)->sval;
if (is_unlikely_selector (sel))
_gst_warningf ("sending `%s', most likely you forgot a period", sel);
lex (p);
- return _gst_make_unary_expr (&loc, receiver, sel);
+ return _gst_make_unary_expr (&location, receiver, sel);
}
@@ -1148,12 +1749,12 @@ parse_unary_expression (gst_parser *p, t
static tree_node
parse_binary_expression (gst_parser *p, tree_node receiver, enum expr_kinds
kind)
{
- YYLTYPE loc = receiver ? receiver->location : p->loc;
+ YYLTYPE location = receiver ? receiver->location : *loc(p,0);
char *sel;
tree_node arg;
- assert (p->token == BINOP || p->token == '|' || p->token == '<'
- || p->token == '>');
- sel = p->val.sval;
+ assert (token (p, 0) == BINOP || token (p, 0) == '|' || token (p, 0) == '<'
+ || token (p, 0) == '>');
+ sel = val(p, 0)->sval;
lex (p);
arg = parse_expression (p, kind & ~EXPR_KEYWORD & ~EXPR_BINOP);
if (!arg)
@@ -1162,7 +1763,7 @@ parse_binary_expression (gst_parser *p,
recover_error (p);
}
- return _gst_make_binary_expr (&loc, receiver, sel, arg);
+ return _gst_make_binary_expr (&location, receiver, sel, arg);
}
/* See above. This function parses a keyword expression with all its
@@ -1171,21 +1772,21 @@ parse_binary_expression (gst_parser *p,
static tree_node
parse_keyword_expression (gst_parser *p, tree_node receiver, enum expr_kinds
kind)
{
- YYLTYPE loc = receiver ? receiver->location : p->loc;
+ YYLTYPE location = receiver ? receiver->location : *loc(p,0);
tree_node list = parse_keyword_list (p, kind);
- return list ? _gst_make_keyword_expr (&loc, receiver, list) : NULL;
+ return list ? _gst_make_keyword_expr (&location, receiver, list) : NULL;
}
static tree_node
parse_keyword_list (gst_parser *p, enum expr_kinds kind)
{
tree_node expr = NULL;
- assert (p->token == KEYWORD);
+ assert (token (p, 0) == KEYWORD);
do
{
- YYLTYPE loc = p->loc;
- char *sval = p->val.sval;
+ YYLTYPE location = *loc(p,0);
+ char *sval = val(p, 0)->sval;
tree_node arg;
lex (p);
arg = parse_expression (p, kind & ~EXPR_KEYWORD);
@@ -1195,15 +1796,15 @@ parse_keyword_list (gst_parser *p, enum
recover_error (p);
}
- expr = _gst_add_node (expr, _gst_make_keyword_list (&loc, sval, arg));
+ expr = _gst_add_node (expr, _gst_make_keyword_list (&location, sval,
arg));
}
- while (p->token == KEYWORD);
+ while (token (p, 0) == KEYWORD);
return expr;
}
-/* Based on an hash table produced by gperf version 2.7.2
+/* Based on a hash table produced by gperf version 2.7.2
Command-line: gperf -tn -F ', false' -j1 -k1,2
with the following input:
@@ -1220,7 +1821,7 @@ parse_keyword_list (gst_parser *p, enum
A few negatives have been included in the input to avoid that
messages like #new or #size require a strcmp (their hash value is
- in range if only the six keywords were included), and the length
+ in range if only the six keywords are included), and the length
has not been included to make the result depend on selectors
*starting* with two given letters. With this hash table and this
implementation, only selectors starting with "fa", "ni", "se",
@@ -1232,15 +1833,15 @@ parse_keyword_list (gst_parser *p, enum
code like this:
return ((*$1 == 's' &&
- (strcmp ($1+1, "elf") == 0 ||
- strcmp ($1+1, "uper") == 0)) ||
+ (strcmp ($1+1, "elf") == 0 ||
+ strcmp ($1+1, "uper") == 0)) ||
- (*$1 == 't' &&
- (strcmp ($1+1, "rue") == 0 ||
- strcmp ($1+1, "hisContext") == 0)) ||
+ (*$1 == 't' &&
+ (strcmp ($1+1, "rue") == 0 ||
+ strcmp ($1+1, "hisContext") == 0)) ||
- (*$1 == 'f' && strcmp ($1+1, "alse") == 0) ||
- (*$1 == 'n' && strcmp ($1+1, "il") == 0))
+ (*$1 == 'f' && strcmp ($1+1, "alse") == 0) ||
+ (*$1 == 'n' && strcmp ($1+1, "il") == 0))
... but using gperf is more cool :-) */
--- orig/libgst/gst-parse.h
+++ mod/libgst/gst-parse.h
@@ -106,10 +106,16 @@ enum parser_state {
PARSE_DOIT
};
-typedef struct gst_parser {
+typedef struct gst_lookahead {
int token;
YYSTYPE val;
YYLTYPE loc;
+} gst_lookahead;
+
+typedef struct gst_parser {
+ gst_lookahead la [4];
+ int la_size;
+ int la_first;
enum parser_state state;
jmp_buf recover;
} gst_parser;
@@ -125,4 +131,7 @@ extern void _gst_parse_method (void)
extern void _gst_parse_chunks (void)
ATTRIBUTE_HIDDEN;
+extern void _gst_print_tokens (gst_parser *p)
+ ATTRIBUTE_HIDDEN;
+
#endif
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Help-smalltalk] scripting syntax part 3,
Paolo Bonzini <=