#ifndef __SCANNER_OPERATORPRECEDENCELIST_H
#define __SCANNER_OPERATORPRECEDENCELIST_H
/*
5D programming language
Copyright (C) 2011 Danny Milosavljevic
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 3 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, see .
*/
#include
#include <5D/Values>
#include "Values/Values"
#include "Values/Symbols"
namespace Scanners {
#define SIMPLE_APPLICATION
/* DIY cons for no good reason. TODO change? */
struct OperatorPrecedenceItem : Values::Node {
struct OperatorPrecedenceItem* next;
Values::NodeT operator_;
Values::NodeT associativity;
OperatorPrecedenceItem(struct OperatorPrecedenceItem* next, Values::NodeT operator_, Values::NodeT associativity) {
this->next = next;
this->operator_ = operator_;
this->associativity = associativity;
}
};
#define MAX_PRECEDENCE_LEVELS 37
struct LOperatorPrecedenceList : Values::Node {
int apply_level;
int minus_level;
short prefix_usages[256];
struct OperatorPrecedenceItem* levels[MAX_PRECEDENCE_LEVELS];
LOperatorPrecedenceList(bool bInitDefaults = true);
int get_operator_precedence(Values::NodeT symbol) const;
int get_operator_precedence_and_associativity(Values::NodeT symbol, Values::NodeT& associativity_out) const;
int empty_P(int precedence_level) {
return(precedence_level >= MAX_PRECEDENCE_LEVELS || levels[precedence_level] == NULL);
}
/* for speed reasons, it can happen that the same operator is present multiple times on the same level. */
Values::NodeT match_operator(int precedence_level, Values::NodeT operator_, Values::NodeT& associativity_out, bool& B_visible_operator) const {
B_visible_operator = true;
if(precedence_level < 0 || precedence_level >= MAX_PRECEDENCE_LEVELS)
return(NULL);
struct OperatorPrecedenceItem* precedence = levels[precedence_level];
for(; precedence; precedence = precedence->next) {
if(precedence->operator_ == operator_
|| (precedence->operator_ == Symbols::Sspace /* apply */ &&
!any_operator_P(operator_) &&
operator_ &&
operator_ != Symbols::Srightparen &&
operator_ != Symbols::Srightbracket &&
operator_ != Symbols::Sautorightparen)) {
if(precedence->operator_ != operator_)
B_visible_operator = false;
associativity_out = precedence->associativity;
return(operator_);
}
}
associativity_out = NULL;
return(NULL);
}
bool any_operator_P(Values::NodeT thingie) const {
if(!this) // if we don't have LOperatorPrecedenceList, no point in checking it
return(false);
return(symbol_P(thingie) && get_operator_precedence(thingie) != -1);
}
int next_precedence_level(int precedence_level) const {
++precedence_level;
/* skip empty levels */
while(precedence_level >= 0 && precedence_level < MAX_PRECEDENCE_LEVELS && levels[precedence_level] == NULL)
++precedence_level;
return(precedence_level);
}
void cons(int precedence_level, Values::NodeT operator_, Values::NodeT associativity);
void uncons(int precedence_level, Values::NodeT operator_, Values::NodeT associativity);
Values::NodeT get_all_operators(int precedence_level) const; // Cons
bool prefix_operator_P(Values::NodeT thingie) const {
/* should be: '\\- unary- let let! import
NOT [ */
//if(thingie == Symbols::Sdash) {
// return true; /* shoot me... */
{
Values::NodeT associativity = NULL;
return(get_operator_precedence_and_associativity(thingie, associativity) != -1 && associativity == Symbols::Sprefix);
}
}
};
Scanners::LOperatorPrecedenceList* legacyOPLFrom5DOPL(Values::NodeT source);
}; /* end namespace Scanners */
#endif /*ndef __SCANNER_OPERATORPRECEDENCELIST_H*/