Class | CodeRay::Scanners::CPlusPlus |
In: |
lib/coderay/scanners/cpp.rb
|
Parent: | Scanner |
RESERVED_WORDS | = | [ 'and', 'and_eq', 'asm', 'bitand', 'bitor', 'break', 'case', 'catch', 'class', 'compl', 'const_cast', 'continue', 'default', 'delete', 'do', 'dynamic_cast', 'else', 'enum', 'export', 'for', 'goto', 'if', 'namespace', 'new', 'not', 'not_eq', 'or', 'or_eq', 'reinterpret_cast', 'return', 'sizeof', 'static_cast', 'struct', 'switch', 'template', 'throw', 'try', 'typedef', 'typeid', 'typename', 'union', 'while', 'xor', 'xor_eq' | www.cppreference.com/wiki/keywords/start | |
PREDEFINED_TYPES | = | [ 'bool', 'char', 'double', 'float', 'int', 'long', 'short', 'signed', 'unsigned', 'wchar_t', 'string' | ||
PREDEFINED_CONSTANTS | = | [ 'false', 'true', 'EOF', 'NULL', ] | ||
PREDEFINED_VARIABLES | = | [ 'this' | ||
DIRECTIVES | = | [ 'auto', 'const', 'explicit', 'extern', 'friend', 'inline', 'mutable', 'operator', 'private', 'protected', 'public', 'register', 'static', 'using', 'virtual', 'void', 'volatile' | ||
IDENT_KIND | = | WordList.new(:ident). add(RESERVED_WORDS, :reserved). add(PREDEFINED_TYPES, :pre_type). add(PREDEFINED_VARIABLES, :local_variable). add(DIRECTIVES, :directive). add(PREDEFINED_CONSTANTS, :pre_constant) | ||
ESCAPE | = | / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x | ||
UNICODE_ESCAPE | = | / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x |
# File lib/coderay/scanners/cpp.rb, line 51 51: def scan_tokens tokens, options 52: 53: state = :initial 54: label_expected = true 55: case_expected = false 56: label_expected_before_preproc_line = nil 57: in_preproc_line = false 58: 59: until eos? 60: 61: kind = nil 62: match = nil 63: 64: case state 65: 66: when :initial 67: 68: if match = scan(/ \s+ | \\\n /x) 69: if in_preproc_line && match != "\\\n" && match.index(?\n) 70: in_preproc_line = false 71: label_expected = label_expected_before_preproc_line 72: end 73: tokens << [match, :space] 74: next 75: 76: elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) 77: kind = :comment 78: 79: elsif match = scan(/ \# \s* if \s* 0 /x) 80: match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos? 81: kind = :comment 82: 83: elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x) 84: label_expected = match =~ /[;\{\}]/ 85: if case_expected 86: label_expected = true if match == ':' 87: case_expected = false 88: end 89: kind = :operator 90: 91: elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x) 92: kind = IDENT_KIND[match] 93: if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/) 94: kind = :label 95: match << matched 96: else 97: label_expected = false 98: if kind == :reserved 99: case match 100: when 'class' 101: state = :class_name_expected 102: when 'case', 'default' 103: case_expected = true 104: end 105: end 106: end 107: 108: elsif scan(/\$/) 109: kind = :ident 110: 111: elsif match = scan(/L?"/) 112: tokens << [:open, :string] 113: if match[0] == ?L 114: tokens << ['L', :modifier] 115: match = '"' 116: end 117: state = :string 118: kind = :delimiter 119: 120: elsif scan(/#[ \t]*(\w*)/) 121: kind = :preprocessor 122: in_preproc_line = true 123: label_expected_before_preproc_line = label_expected 124: state = :include_expected if self[1] == 'include' 125: 126: elsif scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox) 127: label_expected = false 128: kind = :char 129: 130: elsif scan(/0[xX][0-9A-Fa-f]+/) 131: label_expected = false 132: kind = :hex 133: 134: elsif scan(/(?:0[0-7]+)(?![89.eEfF])/) 135: label_expected = false 136: kind = :oct 137: 138: elsif scan(/(?:\d+)(?![.eEfF])L?L?/) 139: label_expected = false 140: kind = :integer 141: 142: elsif scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/) 143: label_expected = false 144: kind = :float 145: 146: else 147: getch 148: kind = :error 149: 150: end 151: 152: when :string 153: if scan(/[^\\"]+/) 154: kind = :content 155: elsif scan(/"/) 156: tokens << ['"', :delimiter] 157: tokens << [:close, :string] 158: state = :initial 159: label_expected = false 160: next 161: elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) 162: kind = :char 163: elsif scan(/ \\ | $ /x) 164: tokens << [:close, :string] 165: kind = :error 166: state = :initial 167: label_expected = false 168: else 169: raise_inspect "else case \" reached; %p not handled." % peek(1), tokens 170: end 171: 172: when :include_expected 173: if scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/) 174: kind = :include 175: state = :initial 176: 177: elsif match = scan(/\s+/) 178: kind = :space 179: state = :initial if match.index ?\n 180: 181: else 182: state = :initial 183: next 184: 185: end 186: 187: when :class_name_expected 188: if scan(/ [A-Za-z_][A-Za-z_0-9]* /x) 189: kind = :class 190: state = :initial 191: 192: elsif match = scan(/\s+/) 193: kind = :space 194: 195: else 196: getch 197: kind = :error 198: state = :initial 199: 200: end 201: 202: else 203: raise_inspect 'Unknown state', tokens 204: 205: end 206: 207: match ||= matched 208: if $CODERAY_DEBUG and not kind 209: raise_inspect 'Error token %p in line %d' % 210: [[match, kind], line], tokens 211: end 212: raise_inspect 'Empty token', tokens unless match 213: 214: tokens << [match, kind] 215: 216: end 217: 218: if state == :string 219: tokens << [:close, :string] 220: end 221: 222: tokens 223: end