#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 */