Remove Comments

medium string simulation parsing

Problem

Given a list of source code lines, remove all // line comments and /* */ block comments. Block comments may span multiple lines; concatenate surviving fragments across lines and drop empty resulting lines.

Input["/*Test*/","int a;","//x","b/*c*/d"]
Output["int a;","bd"]
The block comment is removed and the // line is dropped entirely.

def removeComments(source):
    res, buf, inblock = [], [], False
    for line in source:
        i, n = 0, len(line)
        if not inblock: buf = []
        while i < n:
            if not inblock and i + 1 < n and line[i:i+2] == '/*':
                inblock = True; i += 2
            elif inblock and i + 1 < n and line[i:i+2] == '*/':
                inblock = False; i += 2
            elif not inblock and i + 1 < n and line[i:i+2] == '//':
                break
            else:
                if not inblock: buf.append(line[i])
                i += 1
        if not inblock and buf: res.append(''.join(buf))
    return res
function removeComments(source) {
  const res = []; let buf = '', inblock = false;
  for (const line of source) {
    let i = 0, n = line.length;
    if (!inblock) buf = '';
    while (i < n) {
      if (!inblock && line.slice(i, i+2) === '/*') { inblock = true; i += 2; }
      else if (inblock && line.slice(i, i+2) === '*/') { inblock = false; i += 2; }
      else if (!inblock && line.slice(i, i+2) === '//') break;
      else { if (!inblock) buf += line[i]; i++; }
    }
    if (!inblock && buf.length) res.push(buf);
  }
  return res;
}
class Solution {
  public List<String> removeComments(String[] source) {
    List<String> res = new ArrayList<>();
    StringBuilder buf = new StringBuilder();
    boolean inblock = false;
    for (String line : source) {
      int i = 0, n = line.length();
      if (!inblock) buf.setLength(0);
      while (i < n) {
        if (!inblock && i + 1 < n && line.charAt(i)=='/' && line.charAt(i+1)=='*') { inblock = true; i += 2; }
        else if (inblock && i + 1 < n && line.charAt(i)=='*' && line.charAt(i+1)=='/') { inblock = false; i += 2; }
        else if (!inblock && i + 1 < n && line.charAt(i)=='/' && line.charAt(i+1)=='/') break;
        else { if (!inblock) buf.append(line.charAt(i)); i++; }
      }
      if (!inblock && buf.length() > 0) res.add(buf.toString());
    }
    return res;
  }
}
class Solution {
public:
  vector<string> removeComments(vector<string>& source) {
    vector<string> res; string buf; bool inblock = false;
    for (auto& line : source) {
      int i = 0, n = line.size();
      if (!inblock) buf.clear();
      while (i < n) {
        if (!inblock && i+1 < n && line[i]=='/' && line[i+1]=='*') { inblock = true; i += 2; }
        else if (inblock && i+1 < n && line[i]=='*' && line[i+1]=='/') { inblock = false; i += 2; }
        else if (!inblock && i+1 < n && line[i]=='/' && line[i+1]=='/') break;
        else { if (!inblock) buf.push_back(line[i]); i++; }
      }
      if (!inblock && !buf.empty()) res.push_back(buf);
    }
    return res;
  }
};
Time: O(N) Space: O(N)