From 0143e511f7a5f3595907787a832bee4e3cd03daf Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 13 Sep 2009 11:52:46 +0200 Subject: Add code stream interface and SLOC counter --- cutl/compiler/sloc-counter.txx | 225 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 cutl/compiler/sloc-counter.txx (limited to 'cutl/compiler/sloc-counter.txx') diff --git a/cutl/compiler/sloc-counter.txx b/cutl/compiler/sloc-counter.txx new file mode 100644 index 0000000..9befac7 --- /dev/null +++ b/cutl/compiler/sloc-counter.txx @@ -0,0 +1,225 @@ +// file : cutl/compiler/sloc-counter.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include // std::isspace + +namespace cutl +{ + namespace compiler + { + template + sloc_counter:: + sloc_counter (code_stream& out) + : out_ (out), + count_ (0), + prev_ ('\0'), + code_counted_ (false), + construct_ (con_code) + { + } + + template + void sloc_counter:: + put (C c) + { + construct old (construct_); + + switch (construct_) + { + case con_code: + { + code (c); + break; + } + case con_c_com: + { + c_comment (c); + break; + } + case con_cxx_com: + { + cxx_comment (c); + break; + } + case con_char_lit: + { + char_literal (c); + break; + } + case con_string_lit: + { + string_literal (c); + break; + } + } + + // There are cases when a previous character has been already + // 'used' and therefore can not be used again. Good example + // would be '/* *//'. Here, the second slash doesn't start + // C++ comment since it was already used by C comment. + // + // To account for this we are going to set prev_ to '\0' when + // the mode changes. + // + + prev_ = (old == construct_) ? c : '\0'; + + out_.put (c); + } + + template + void sloc_counter:: + unbuffer () + { + } + + template + void sloc_counter:: + code (C c) + { + bool count (true); + + switch (c) + { + case '/': + { + if (prev_ == '/') + { + construct_ = con_cxx_com; + count = false; + } + else + { + // This slash can be a beginning of a comment but we + // yet have no way to know. Will have to examine it later + // (see below). + // + count = false; + } + + break; + } + case '*': + { + if (prev_ == '/') + { + construct_ = con_c_com; + count = false; + } + break; + } + case '\'': + { + construct_ = con_char_lit; + break; + } + case '"': + { + construct_ = con_string_lit; + break; + } + case '\n': + { + code_counted_ = false; // Reset for a new line. + count = false; + break; + } + default: + { + if (std::isspace (c)) + count = false; + break; + } + } + + if (!code_counted_) + { + if (count) + { + count_++; + code_counted_ = true; + } + else if (prev_ == '/' && construct_ == con_code) + { + // This condition accounts for the fact that we cannot count + // '/' right away since it can be a beginning of a comment. + // + count_++; + code_counted_ = (c != '\n'); + } + } + } + + template + void sloc_counter:: + c_comment (C c) + { + switch (c) + { + case '/': + { + if (prev_ == '*') + construct_ = con_code; + break; + } + case '\n': + { + code_counted_ = false; // Reset for a new line. + break; + } + } + } + + template + void sloc_counter:: + cxx_comment (C c) + { + switch (c) + { + case '\n': + { + construct_ = con_code; + code_counted_ = false; // Reset for a new line. + break; + } + } + } + + template + void sloc_counter:: + char_literal (C c) + { + switch (c) + { + case '\'': + { + if (prev_ != '\\') + construct_ = con_code; + break; + } + } + } + + template + void sloc_counter:: + string_literal (C c) + { + switch (c) + { + case '"': + { + if (prev_ != '\\') + construct_ = con_code; + break; + } + case '\n': + { + count_++; + break; + } + } + } + } +} -- cgit v1.1