2002-05-13 22:13:06 +00:00
|
|
|
/**
|
|
|
|
* STGrammar.y
|
|
|
|
* StepTalk grammar
|
|
|
|
*
|
|
|
|
* Copyright (c) 2000 Stefan Urbanek
|
|
|
|
*
|
|
|
|
* This file is part of the StepTalk project.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02111, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
%{
|
|
|
|
|
|
|
|
#define YYSTYPE id
|
|
|
|
#define YYLTYPE int
|
|
|
|
#undef YYDEBUG
|
|
|
|
|
|
|
|
#import <Foundation/NSException.h>
|
|
|
|
#import "STCompiler.h"
|
|
|
|
#import "STCompilerUtils.h"
|
|
|
|
#import "STSourceReader.h"
|
2002-05-14 23:42:25 +00:00
|
|
|
#import "Externs.h"
|
2002-05-13 22:13:06 +00:00
|
|
|
|
|
|
|
#import <StepTalk/STExterns.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* extern int STCerror(const char *str);
|
|
|
|
extern int STClex (YYSTYPE *lvalp, void *context);
|
|
|
|
*/
|
|
|
|
#define YYPARSE_PARAM context
|
|
|
|
#define YYLEX_PARAM context
|
|
|
|
#define YYERROR_VERBOSE
|
|
|
|
|
|
|
|
#define CONTEXT ((STParserContext *)context)
|
|
|
|
#define COMPILER (CONTEXT->compiler)
|
|
|
|
#define READER (CONTEXT->reader)
|
|
|
|
#define RESULT (CONTEXT->result)
|
|
|
|
|
|
|
|
%}
|
|
|
|
|
|
|
|
%pure_parser
|
|
|
|
|
|
|
|
/* BISON declarations */
|
|
|
|
|
|
|
|
%token TK_SEPARATOR TK_BAR TK_ASSIGNMENT
|
|
|
|
%token TK_LPAREN TK_RPAREN TK_BLOCK_OPEN TK_BLOCK_CLOSE TK_ARRAY_OPEN
|
|
|
|
%token TK_DOT TK_COLON TK_SEMICOLON TK_RETURN
|
|
|
|
%token TK_IDENTIFIER TK_BINARY_SELECTOR TK_KEYWORD
|
|
|
|
%token TK_NUMBER TK_SYMBOL TK_STRING TK_CHARACTER
|
|
|
|
|
|
|
|
/* Grammar */
|
|
|
|
|
|
|
|
%%
|
|
|
|
source: /* empty string */ {
|
|
|
|
[COMPILER compileMethod:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
| single_method {
|
|
|
|
[COMPILER compileMethod:$1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
TK_BLOCK_OPEN TK_BAR
|
|
|
|
methods
|
|
|
|
TK_BLOCK_CLOSE
|
|
|
|
;
|
|
|
|
|
|
|
|
single_method: statements
|
|
|
|
{
|
|
|
|
$$ = [STCMethod methodWithPattern:nil
|
|
|
|
/**/ statements:$1];
|
|
|
|
}
|
|
|
|
| temporaries statements
|
|
|
|
{
|
|
|
|
[$2 setTemporaries:$1];
|
|
|
|
$$ = [STCMethod methodWithPattern:nil
|
|
|
|
/**/ statements:$2];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
methods:
|
|
|
|
block_var_list
|
|
|
|
{
|
|
|
|
[COMPILER setReceiverVariables:$1];
|
|
|
|
}
|
|
|
|
method_list
|
|
|
|
|
|
|
|
| method_list
|
|
|
|
;
|
|
|
|
|
|
|
|
method_list: method
|
|
|
|
{
|
|
|
|
[COMPILER compileMethod:$1];
|
|
|
|
}
|
|
|
|
| method_list TK_SEPARATOR method
|
|
|
|
{
|
|
|
|
[COMPILER compileMethod:$3];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
method: message_pattern statements
|
|
|
|
{
|
|
|
|
$$ = [STCMethod methodWithPattern:$1
|
|
|
|
/**/ statements:$2];
|
|
|
|
}
|
|
|
|
| message_pattern temporaries statements
|
|
|
|
{
|
|
|
|
[$3 setTemporaries:$2];
|
|
|
|
$$ = [STCMethod methodWithPattern:$1
|
|
|
|
/**/ statements:$3];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
message_pattern:
|
|
|
|
unary_selector
|
|
|
|
{
|
|
|
|
$$ = [STCMessage message];
|
|
|
|
[$$ addKeyword:$1 object:nil];
|
|
|
|
}
|
|
|
|
| binary_selector variable_name
|
|
|
|
{
|
|
|
|
$$ = [STCMessage message];
|
|
|
|
[$$ addKeyword:$1 object:$2];
|
|
|
|
}
|
|
|
|
| keyword_list
|
|
|
|
;
|
|
|
|
|
|
|
|
keyword_list: keyword variable_name
|
|
|
|
{
|
|
|
|
$$ = [STCMessage message];
|
|
|
|
[$$ addKeyword:$1 object:$2];
|
|
|
|
}
|
|
|
|
| keyword_list keyword variable_name
|
|
|
|
{
|
|
|
|
[$1 addKeyword:$2 object:$3];
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
temporaries: TK_BAR variable_list TK_BAR
|
|
|
|
{ $$ = $2; }
|
|
|
|
;
|
|
|
|
|
|
|
|
variable_list: variable_name
|
|
|
|
{
|
|
|
|
$$ = [NSMutableArray array];
|
|
|
|
[$$ addObject:$1];
|
|
|
|
}
|
|
|
|
| variable_list variable_name
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
[$$ addObject:$2];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
block: TK_BLOCK_OPEN TK_BLOCK_CLOSE
|
|
|
|
{
|
|
|
|
$$ = [STCStatements statements];
|
|
|
|
}
|
|
|
|
| TK_BLOCK_OPEN statements TK_BLOCK_CLOSE
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
| TK_BLOCK_OPEN block_var_list TK_BAR statements TK_BLOCK_CLOSE
|
|
|
|
{
|
|
|
|
$$ = $4;
|
|
|
|
[$$ setTemporaries:$2];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
block_var_list: TK_COLON variable_name
|
|
|
|
{
|
|
|
|
$$ = [NSMutableArray array];
|
|
|
|
[$$ addObject:$2];
|
|
|
|
}
|
|
|
|
| block_var_list TK_COLON variable_name
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
[$$ addObject:$3];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
statements:
|
|
|
|
TK_RETURN expression
|
|
|
|
{
|
|
|
|
$$ = [STCStatements statements];
|
|
|
|
[$$ setReturnExpression:$2];
|
|
|
|
}
|
|
|
|
| expressions
|
|
|
|
{
|
|
|
|
$$ = [STCStatements statements];
|
|
|
|
[$$ setExpressions:$1];
|
|
|
|
}
|
|
|
|
|
|
|
|
| expressions TK_DOT
|
|
|
|
{
|
|
|
|
$$ = [STCStatements statements];
|
|
|
|
[$$ setExpressions:$1];
|
|
|
|
}
|
|
|
|
| expressions TK_DOT TK_RETURN expression
|
|
|
|
{
|
|
|
|
$$ = [STCStatements statements];
|
|
|
|
[$$ setReturnExpression:$4];
|
|
|
|
[$$ setExpressions:$1];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
expressions:
|
|
|
|
expression {
|
|
|
|
$$ = [NSMutableArray array];
|
|
|
|
[$$ addObject:$1];
|
|
|
|
}
|
|
|
|
|
|
|
|
| expressions TK_DOT expression
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
[$$ addObject:$3];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
expression: primary
|
|
|
|
{
|
|
|
|
$$ = [STCExpression
|
|
|
|
/**/ primaryExpressionWithObject:$1];
|
|
|
|
}
|
|
|
|
| assignments primary
|
|
|
|
{
|
|
|
|
$$ = [STCExpression
|
|
|
|
/**/ primaryExpressionWithObject:$2];
|
|
|
|
[$$ setAssignments:$1];
|
|
|
|
}
|
|
|
|
| message_expression
|
|
|
|
| assignments message_expression
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
[$$ setAssignments:$1];
|
|
|
|
}
|
|
|
|
| cascade
|
|
|
|
| assignments cascade
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
[$$ setAssignments:$1];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
assignments: assignment
|
|
|
|
{
|
|
|
|
$$ = [NSMutableArray array];
|
|
|
|
[$$ addObject:$1];
|
|
|
|
}
|
|
|
|
| assignments assignment
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
[$$ addObject:$2];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
assignment: variable_name TK_ASSIGNMENT
|
|
|
|
{ $$ = $1;}
|
|
|
|
|
|
|
|
cascade: message_expression cascade_list
|
|
|
|
{
|
|
|
|
/* FIXME: check if this is this OK */
|
|
|
|
[$$ setCascade:$2];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
cascade_list: TK_SEMICOLON cascade_item
|
|
|
|
{
|
|
|
|
$$ = [NSMutableArray array];
|
|
|
|
[$$ addObject:$2];
|
|
|
|
}
|
|
|
|
| cascade_list TK_SEMICOLON cascade_item
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
[$$ addObject:$3];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
cascade_item: unary_selector
|
|
|
|
{
|
|
|
|
$$ = [STCMessage message];
|
|
|
|
[$$ addKeyword:$1 object:nil];
|
|
|
|
}
|
|
|
|
| binary_selector unary_object
|
|
|
|
{
|
|
|
|
$$ = [STCMessage message];
|
|
|
|
[$$ addKeyword:$1 object:$2];
|
|
|
|
}
|
|
|
|
| keyword_expr_list
|
|
|
|
;
|
|
|
|
|
|
|
|
message_expression: unary_expression
|
|
|
|
| binary_expression
|
|
|
|
| keyword_expression
|
|
|
|
;
|
|
|
|
unary_expression: unary_object unary_selector
|
|
|
|
{
|
|
|
|
STCMessage *message = [STCMessage message];
|
|
|
|
[message addKeyword:$2 object:nil];
|
|
|
|
$$ = [STCExpression
|
|
|
|
/**/ messageExpressionWithTarget:$1
|
|
|
|
/**/ message:message];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
binary_expression: binary_object binary_selector unary_object
|
|
|
|
{
|
|
|
|
STCMessage *message = [STCMessage message];
|
|
|
|
[message addKeyword:$2 object:$3];
|
|
|
|
$$ = [STCExpression
|
|
|
|
/**/ messageExpressionWithTarget:$1
|
|
|
|
/**/ message:message];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
keyword_expression: binary_object keyword_expr_list
|
|
|
|
{
|
|
|
|
$$ = [STCExpression
|
|
|
|
/**/ messageExpressionWithTarget:$1
|
|
|
|
/**/ message:$2];
|
|
|
|
}
|
|
|
|
keyword_expr_list: keyword binary_object
|
|
|
|
{
|
|
|
|
$$ = [STCMessage message];
|
|
|
|
[$$ addKeyword:$1 object:$2];
|
|
|
|
}
|
|
|
|
| keyword_expr_list keyword binary_object
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
[$$ addKeyword:$2 object:$3];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
unary_object: primary
|
|
|
|
| unary_expression
|
|
|
|
;
|
|
|
|
binary_object: unary_object
|
|
|
|
| binary_expression
|
|
|
|
;
|
|
|
|
primary: variable_name
|
|
|
|
{
|
|
|
|
$$ = [STCPrimary primaryWithVariable:$1];
|
|
|
|
}
|
|
|
|
| literal
|
|
|
|
{
|
|
|
|
$$ = [STCPrimary primaryWithLiteral:$1];
|
|
|
|
}
|
|
|
|
| block
|
|
|
|
{
|
|
|
|
$$ = [STCPrimary primaryWithBlock:$1];
|
|
|
|
}
|
|
|
|
| TK_LPAREN expression TK_RPAREN
|
|
|
|
{
|
|
|
|
$$ = [STCPrimary primaryWithExpression:$2];
|
|
|
|
}
|
|
|
|
;
|
|
|
|
variable_name: TK_IDENTIFIER /* STCheckVariable ... */
|
|
|
|
;
|
|
|
|
unary_selector: TK_IDENTIFIER
|
|
|
|
;
|
|
|
|
binary_selector: TK_BINARY_SELECTOR
|
|
|
|
;
|
|
|
|
keyword: TK_KEYWORD
|
|
|
|
;
|
|
|
|
literal: TK_NUMBER
|
|
|
|
{ $$ = [COMPILER createNumberLiteralFrom:$1]; }
|
|
|
|
| TK_SYMBOL
|
|
|
|
{ $$ = [COMPILER createSymbolLiteralFrom:$1]; }
|
|
|
|
| TK_STRING
|
|
|
|
{ $$ = [COMPILER createStringLiteralFrom:$1]; }
|
|
|
|
| TK_CHARACTER
|
|
|
|
{ $$ = [COMPILER createCharacterLiteralFrom:$1]; }
|
|
|
|
| TK_ARRAY_OPEN array TK_RPAREN
|
|
|
|
{ $$ = [COMPILER createArrayLiteralFrom:$2]; }
|
|
|
|
;
|
|
|
|
array: literal { $$ = [NSMutableArray array];
|
|
|
|
[$$ addObject:$1]; }
|
|
|
|
| symbol { $$ = [NSMutableArray array];
|
|
|
|
[$$ addObject:$1]; }
|
|
|
|
| array literal { $$ = $1; [$$ addObject:$2]; }
|
|
|
|
| array symbol { $$ = $1; [$$ addObject:$2]; }
|
|
|
|
;
|
|
|
|
symbol: TK_IDENTIFIER
|
|
|
|
{ $$ = [COMPILER createSymbolLiteralFrom:$1]; }
|
|
|
|
| binary_selector
|
|
|
|
{ $$ = [COMPILER createSymbolLiteralFrom:$1]; }
|
|
|
|
| TK_KEYWORD
|
|
|
|
{ $$ = [COMPILER createSymbolLiteralFrom:$1]; }
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
int STCerror(const char *str)
|
|
|
|
{
|
|
|
|
[NSException raise:STCompilerSyntaxException
|
|
|
|
format:@"Unknown parse error (%s)", str];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lexer
|
|
|
|
* --------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
int STClex (YYSTYPE *lvalp, void *context)
|
|
|
|
{
|
|
|
|
STTokenType tokenType = [READER nextToken];
|
|
|
|
|
|
|
|
if(tokenType == STEndTokenType)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*lvalp = [READER tokenString];
|
|
|
|
|
|
|
|
switch(tokenType)
|
|
|
|
{
|
|
|
|
case STBarTokenType: return TK_BAR;
|
|
|
|
case STReturnTokenType: return TK_RETURN;
|
|
|
|
case STColonTokenType: return TK_COLON;
|
|
|
|
case STSemicolonTokenType: return TK_SEMICOLON;
|
|
|
|
case STDotTokenType: return TK_DOT;
|
|
|
|
case STLParenTokenType: return TK_LPAREN;
|
|
|
|
case STRParenTokenType: return TK_RPAREN;
|
|
|
|
case STBlockOpenTokenType: return TK_BLOCK_OPEN;
|
|
|
|
case STBlockCloseTokenType: return TK_BLOCK_CLOSE;
|
|
|
|
case STArrayOpenTokenType: return TK_ARRAY_OPEN;
|
|
|
|
case STAssignTokenType: return TK_ASSIGNMENT;
|
|
|
|
case STIdentifierTokenType: return TK_IDENTIFIER;
|
|
|
|
case STKeywordTokenType: return TK_KEYWORD;
|
|
|
|
case STBinarySelectorTokenType: return TK_BINARY_SELECTOR;
|
|
|
|
case STSymbolTokenType: return TK_SYMBOL;
|
|
|
|
case STStringTokenType: return TK_STRING;
|
|
|
|
case STCharacterTokenType: return TK_CHARACTER;
|
|
|
|
case STNumberTokenType: return TK_NUMBER;
|
|
|
|
case STSeparatorTokenType: return TK_SEPARATOR;
|
|
|
|
|
|
|
|
case STEndTokenType: return 0;
|
|
|
|
|
|
|
|
case STSharpTokenType:
|
|
|
|
case STInvalidTokenType:
|
|
|
|
case STErrorTokenType:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|