From 29c8ce737f513766673fd3e57e30233d9fcce159 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 13 Sep 2009 14:02:04 +0200 Subject: Add C++ source code indenter --- cutl/compiler/cxx-indenter.hxx | 169 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 cutl/compiler/cxx-indenter.hxx (limited to 'cutl/compiler/cxx-indenter.hxx') diff --git a/cutl/compiler/cxx-indenter.hxx b/cutl/compiler/cxx-indenter.hxx new file mode 100644 index 0000000..0e5e2a1 --- /dev/null +++ b/cutl/compiler/cxx-indenter.hxx @@ -0,0 +1,169 @@ +// file : cutl/compiler/cxx-indenter.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_COMPILER_CXX_INDENTER_HXX +#define CUTL_COMPILER_CXX_INDENTER_HXX + +#include +#include +#include +#include // std::size_t + +#include + +namespace cutl +{ + namespace compiler + { + template + class cxx_indenter: public code_stream + { + public: + cxx_indenter (code_stream& out); + + private: + cxx_indenter (cxx_indenter const&); + + cxx_indenter& + operator= (cxx_indenter const&); + + public: + virtual void + put (C); + + virtual void + unbuffer (); + + private: + typedef std::basic_string string; + + enum construct + { + con_other, + con_pp_dir, + con_c_com, + con_cxx_com, + con_string_lit, + con_char_lit + }; + + private: + void + next_token (string const& old, C); + + void + ensure_new_line (); + + void + output_indentation (); + + void + write (C); + + private: + void + tokenize (C, construct old); + + void + retire (C); + + private: + enum char_class_type + { + cc_alpha, // Alpha + '_'. + cc_digit, + cc_op_punc, // Operator or punctuation. + cc_space + }; + + static char_class_type + char_class (C); + + private: + enum keyword_type + { + kw_if, + kw_do, + kw_for, + kw_else, + kw_case, + kw_while, + kw_catch, + kw_default + }; + + static C const* + keyword (keyword_type); + + private: + code_stream& out_; + bool buffering_; // True if write() should buffer the char. + std::size_t position_; // Current position on the line. + std::size_t paren_balance_; // ( ) balance. + std::stack indentation_; + std::size_t spaces_; + bool suppress_nl_; + construct construct_; + + // Special state stach for the do-while construct. The presence + // of an element in the stack indicates that we are in a braced + // do-while construct. The value of the element is the brace + // balance. + std::stack do_while_state_; + + typedef std::deque hold; + hold hold_; + + private: + string token_; // previously fully recognized token + string lexeme_; // current lexeme (accumulator) + + // Keywords that may be folowed by a single-line block, e.g., if, + // else, etc. + // + std::set single_line_blocks_; + + // Keywords that may follow (and be related) to a previous block, + // e.g., else, case, catch. + // + std::set follow_blocks_; + + string do_; + string lbrace_; + string rbrace_; + + private: + // Single-line indented blocks such as if, else, while, etc. The + // newline flag indicates whether a new line has been seen after + // the keyword. This is needed to properly distinguish cases such + // as: + // + // else if (...) + // foo (); + // + // else + // if (...) + // foo (); + // + struct indent_block + { + indent_block (bool newline, bool indented) + : newline_ (newline), indented_ (indented) + { + } + + bool newline_; + bool indented_; + }; + + std::stack indent_stack_; + }; + } +} + +#include +#include + +#endif // CUTL_COMPILER_CXX_INDENTER_HXX -- cgit v1.1