#ifndef __SCANNER_H
#define __SCANNER_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
/* C++ has a template isxdigit which conflicts with the macro isxdigit */
#undef isxdigit
#include
#include
#include
#include
#include "AST/Symbol"
#include "AST/AST"
namespace Scanners {
class ParseException : std::exception {
char* message;
public:
ParseException(const char* s) throw();
virtual const char* what() const throw();
};
#define SCROLL_LEFT(x, n) \
x[0] = x[1]; \
x[1] = x[2]; \
x[2] = x[3]; \
x[3] = n;
#define SCROLL_RIGHT(x) \
(x[4] = x[3], x[3] = x[2], x[2] = x[1], x[1] = x[0], x[4])
class Scanner : public AST::Node {
protected:
FILE* input_file;
//std::stringstream matchtext;
int position;
int previous_position;
int line_number;
int column_number;
char* input_name;
int backtracking_column_numbers[5]; /* last is dummy */
bool backtracking_beginning_of_line[5]; /* last is dummy */
bool B_honor_indentation;
bool B_beginning_of_line;
int brace_level; // non-indentation braces.
void update_indentation();
inline int increment_position(int input) {
++position;
if(input == '\n') {
SCROLL_LEFT(backtracking_column_numbers, column_number)
SCROLL_LEFT(backtracking_beginning_of_line, B_beginning_of_line)
++line_number;
column_number = 0;
B_beginning_of_line = true;
} else if(B_beginning_of_line && (input != ' ' && input != '\t' && input != EOF && input != '\r')) {
B_beginning_of_line = false;
update_indentation();
++column_number;
} else
++column_number;
return(input);
}
inline int decrement_position(int input) {
--position;
assert(input != ' ' && input != '\t');
if(input == '\n') {
column_number = SCROLL_RIGHT(backtracking_column_numbers);
B_beginning_of_line = SCROLL_RIGHT(backtracking_beginning_of_line);
--line_number;
} else
--column_number;
return(input);
}
void increase_brace_level() {
++brace_level;
}
void decrease_brace_level() {
--brace_level;
}
void inject(AST::NodeT input_value);
public:
AST::NodeT input_value; // read-only
void push(FILE* input_file, int line_number, const char* input_name);
void pop(void);
int get_position(void) const {
return(previous_position);
}
int get_column_number(void) const {
return(column_number);
}
int get_line_number(void) const {
return(line_number);
}
void raise_error(const std::string& expected_text, int got_text);
void raise_error(const std::string& expected_text, std::string got_text);
Scanner(void);
bool EOFP(void) const;
void ensure_end(void);
AST::NodeT consume(AST::NodeT expected_value = NULL);
bool setHonorIndentation(bool value) {
bool result = B_honor_indentation;
B_honor_indentation = value;
return(result);
}
virtual std::string toString(void) const;
private:
std::list injected_input_values;
bool deinject();
void parse_token(void);
void parse_optional_whitespace(void);
void parse_number(int input);
void parse_structural(int input);
void parse_string(int input);
void parse_special_coding(int input);
void parse_number_with_base(int input, int base);
void parse_operator(int input);
void parse_symbol(int input, int special_prefix = 0, int special_prefix_2 = 0);
};
bool symbol_char_P(int input);
}; /* end namespace Scanners */
#endif /* ndef __SCANNER_H */