using namespace std;
-DLLexer::DLLexer(std::istream& in) : LLNLexer(in)
+DLLexer::DLLexer(std::istream& in) : LLNLexer(in), terminator_string("end")
{
}
((lookahead(1) >= 'A') && (lookahead(1) <= 'Z'));
}
-bool DLLexer::isDigit(void)
+bool DLLexer::isDigit(char lach)
{
- return ((lookahead(1) >= '0') && (lookahead(1) <= '9'));
+ return ((lach >= '0') && (lach <= '9'));
}
bool DLLexer::isStringChar(void)
&& (lookahead(1) != '\n'));
}
+void DLLexer::terminator(std::string term)
+{
+ terminator_string = term;
+}
+
+std::string DLLexer::terminator(void)
+{
+ return terminator_string;
+}
+
Token DLLexer::next(void)
{
Token ret;
// If we have non-EOF chars then process them
while ( !eof() && (ret.type() == EOF) )
{
+ // Consume whitespace
if (isWhiteSpace())
{
WS();
}
+
+ // Consume and ignore comments
else if(lookahead(1) == '#')
{
COMMENT();
}
- else if (isDigit())
+
+ // Consume positive or negative numbers
+ else if ( isDigit( lookahead(1) ) )
{
Number(ret,false);
}
- else if(lookahead(1) == '-')
+ else if( (lookahead(1) == '-') && isDigit( lookahead(2) ) )
{
consume();
- if(isDigit())
- {
- Number(ret,true);
- }
- else
- {
- throw Exception(line,column);
- }
+ Number(ret,true);
}
+
+ // Consume character literals
else if(lookahead(1) == '\'')
{
Char(ret);
}
+
+ // Consume string literals
else if(lookahead(1) == '"')
{
String(ret);
}
+
+ // Consume symbol literals
else if(lookahead(1) == '$')
{
Symbol(ret);
}
- //*
+
+ // Consume parentheses
else if (lookahead(1) == '(')
{
consume();
consume();
ret = Token( RPAR, ")", line, column );
}
- // */
+
+ // Everything else (except the unescaped terminator) is considered an ID
else
{
+ bool escaped = false;
+ if ( lookahead(1) == '\\' )
+ {
+ consume();
+ escaped = true;
+ }
+
Id(ret);
+
+ if( escaped && (ret.text().compare( terminator_string ) == 0) )
+ {
+ ret.type( TERM );
+ }
}
}
oss << lookahead(1);
consume();
}
- while(isLetter() || isDigit() || lookahead(1) == '_');
+ while( !isWhiteSpace() &&
+ ('(' != lookahead(1)) &&
+ (')' != lookahead(1)) );
+ //while(isLetter() || isDigit() || lookahead(1) == '_');
tok = Token(ID, oss.str(), line, column);
}
consume();
}
- if( isDigit() )
+ if( isDigit( lookahead(1) ) )
{
// Capture the integer part
do
oss << lookahead(1);
consume();
}
- while(isDigit());
+ while(isDigit( lookahead(1) ));
}
else
{
oss << lookahead(1);
consume();
}
- while(isDigit());
+ while(isDigit(lookahead(1)));
// Capture the decimal point if we have one
if(lookahead(1) == '.')
oss << lookahead(1);
consume();
- if(!isDigit())
+ if(!isDigit(lookahead(1)))
{
Exception ex(line,column);
ex << "Missing fractional portion of floating point number.";
oss << lookahead(1);
consume();
}
- while ( isDigit() );
+ while ( isDigit(lookahead(1)) );
}
void DLLexer::Char(Token& tok)
oss << lookahead(1);
consume();
}
- while(isLetter() || isDigit() || lookahead(1) == '_');
+ while(isLetter() || isDigit(lookahead(1)) || lookahead(1) == '_');
tok = Token( SYMBOL, oss.str(), line, column );
}
DLParser::DLParser() : BTParser()
{
- pattern_types.insert( pair<string,PatternType_T>( "M", MAP_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "V", VECT_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "L", LIST_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "B", BLK_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "I", ID_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "N", NUM_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "C", CHAR_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "St", STR_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "Sy", SYM_TYP ));
- pattern_types.insert( pair<string,PatternType_T>( "E", EXPR_TYP ));
+ core_forms.insert( pair<string,eTokenTypes>("define", DEFINE) );
+ core_forms.insert( pair<string,eTokenTypes>("set!", ASSIGN) );
+ core_forms.insert( pair<string,eTokenTypes>("lambda", LAMBDA) );
+ core_forms.insert( pair<string,eTokenTypes>("begin", BEGIN) );
+ core_forms.insert( pair<string,eTokenTypes>("if", IF) );
+ core_forms.insert( pair<string,eTokenTypes>("macro", MACRO) );
}
DLParser::~DLParser()
{
}
+bool DLParser::isMacroName(void)
+{
+ return false;
+}
+
+bool DLParser::isCoreFormName(void)
+{
+ return false;
+}
+
+eTokenTypes DLParser::getCoreFormId(void)
+{
+ return (eTokenTypes)0;
+}
+
void DLParser::parse(void)
{
result = Program();
AST* DLParser::Program(void)
{
- AST* node = _new AST( PROGRAM );
+ AST* node = new AST( PROGRAM );
while( lookaheadType(1) != EOF )
{
node->addChild( Expression() );
{
AST* ret = NULL;
- // Expression := Application
- // | Literal
+ // Expression := CoreForm
+ // | BasicExp
//
- // Application := define '(' ID Expression ')'
- // | set '(' ID Expression ')'
- // | lambda '(' IdList ExpList? ')'
- // | begin '(' ExpList* ')'
- // | if '(' Expression Expression Expression? ')'
- // | ID '(' ExpList ')'
+ // CoreForm := 'define' ID Expression TERM
+ // | 'set' ID Expression TERM
+ // | 'lambda' IdList ExpList? TERM
+ // | 'begin' ExpList* TERM
+ // | 'if' Expression Expression Expression? TERM
+ // | 'macro' ID IdList ID ExpList TERM
//
- // ExpList := Expression+
- //
- // IdList := '(' ID* ')'
+ // BasicExp := MacroName ExpList? TERM
+ // | '(' Expression ID Expression ')'
+ // | ID '(' ExpList ')'
+ // | Literal
//
// Literal := ID
// | CHAR
// | SYMBOL
// | STRING
// | NUMBER
+ //
+ // ExpList := Expression+
+ //
+ // IdList := '(' ID* ')'
+ //
- if ((ID == lookaheadType(1)) && (LPAR == lookaheadType(2)))
+ if( isCoreFormName() )
{
- // Get the ID text
- Token id = lookaheadToken(1);
- std::string id_text = id.text();
- consume();
+ ret = CoreForm();
+ }
+ else
+ {
+ ret = Application();
+ }
- match(LPAR);
- if (0 == id_text.compare("define"))
- {
- ret = new AST( lookaheadToken(1) );
- match(ID);
- ret = new AST(DEFINE, 2, ret, Expression());
- }
- else if (0 == id_text.compare("set"))
- {
+ return ret;
+}
+
+AST* DLParser::CoreForm(void)
+{
+ AST* ret = NULL;
+ eTokenTypes form_id = getCoreFormId();
+ consume(); // Throw away the form name (we don't need it anymore)
+ switch( form_id )
+ {
+ case DEFINE:
+ case ASSIGN:
ret = new AST( lookaheadToken(1) );
match(ID);
- ret = new AST(ASSIGN, 2, ret, Expression());
- }
- else if (0 == id_text.compare("lambda"))
- {
+ ret = new AST(form_id, 2, ret, Expression());
+ break;
+
+ case LAMBDA:
ret = new AST(LAMBDA, 2, IdList(), ExpList());
- }
- else if (0 == id_text.compare("begin"))
- {
+ break;
+
+ case BEGIN:
ret = new AST(BEGIN, 1, ExpList());
- }
- else if (0 == id_text.compare("if"))
- {
+ break;
+
+ case IF:
ret = new AST(IF, 2, Expression(), Expression());
if(lookaheadType(1) != RPAR)
{
ret->addChild( Expression() );
}
- }
- //else if (0 == id_text.compare("macro"))
- //{
- //}
- else
- {
- ret = new AST( id );
- ret = new AST(APPLY, 2, ret, ExpList());
- }
+ break;
+
+ case MACRO:
+ ret = new AST(MACRO);
+
+ // Get the macro name
+ ret->addChild( new AST( lookaheadToken(1) ) );
+ match(ID);
+
+ // Get the macro keywords
+ ret->addChild( IdList() );
+
+ // Get the macro terminator
+ ret->addChild( new AST( lookaheadToken(1) ) );
+ match(ID);
+
+ // Get the macro transform rules
+ while (TERM != lookaheadType(1))
+ {
+ AST* transform = new AST( TRANSFORM );
+ transform->addChild( IdList() );
+ transform->addChild( Expression() );
+ ret->addChild( transform );
+ }
+ break;
+
+ default:
+ throw Exception( lookaheadToken(1) );
+ break;
+ }
+ match(TERM);
+ return ret;
+}
+
+AST* DLParser::Application(void)
+{
+ AST* ret = NULL;
+
+ // Macro Expression
+ if ( isMacroName() )
+ {
+ }
+
+ // Traditional Function Application
+ else if( (lookaheadType(1) == ID) && (lookaheadType(2) == LPAR) )
+ {
+ ret = new AST( lookaheadToken(1) );
+ consume();
+ match(LPAR);
+ ret = new AST(APPLY, 2, ret, ExpList());
match(RPAR);
}
- else if( LPAR == lookaheadType(1) )
+
+ // Infix Function Application
+ else if( lookaheadType(1) == LPAR )
{
- AST* op = NULL;
- AST* operand1 = NULL;
- AST* operand2 = NULL;
- Token op_tok;
+ AST* operation = NULL;
+ AST* operand1 = NULL;
+ AST* operand2 = NULL;
- // Left Operand
match(LPAR);
operand1 = Expression();
-
- // Operator
- op_tok = lookaheadToken(1);
+ operation = new AST( lookaheadToken(1) );
match(ID);
- op = new AST(op_tok);
-
- // Right Operand
operand2 = Expression();
match(RPAR);
- ret = new AST(APPLY, 3, op, operand1, operand2);
+ ret = new AST( APPLY, 2, operation, new AST(EXP_LIST, 2, operand1, operand2) );
}
+
+ // Literal
else
{
- ret = new AST( lookaheadToken(1) );
- consume();
+ ret = Literal();
}
return ret;
}
+AST* DLParser::Literal(void)
+{
+ AST* ret = new AST( lookaheadToken(1) );
+ consume();
+ return ret;
+}
+
AST* DLParser::ExpList(void)
{
AST* ret = new AST(EXP_LIST);