diff options
Diffstat (limited to 'lib/coderay/scanners/cpp.rb')
-rw-r--r-- | lib/coderay/scanners/cpp.rb | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/lib/coderay/scanners/cpp.rb b/lib/coderay/scanners/cpp.rb index 0b92ef9..6af5066 100644 --- a/lib/coderay/scanners/cpp.rb +++ b/lib/coderay/scanners/cpp.rb @@ -51,6 +51,10 @@ module Scanners def scan_tokens tokens, options state = :initial + label_expected = true + case_expected = false + label_expected_before_preproc_line = nil + in_preproc_line = false until eos? @@ -61,8 +65,13 @@ module Scanners when :initial - if scan(/ \s+ | \\\n /x) - kind = :space + if match = scan(/ \s+ | \\\n /x) + if in_preproc_line && match != "\\\n" && match.index(?\n) + in_preproc_line = false + label_expected = label_expected_before_preproc_line + end + tokens << [match, :space] + next elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) kind = :comment @@ -71,16 +80,29 @@ module Scanners match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos? kind = :comment - elsif scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x) + elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x) + label_expected = match =~ /[;\{\}]/ + if case_expected + label_expected = true if match == ':' + case_expected = false + end kind = :operator elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x) kind = IDENT_KIND[match] - if kind == :ident and check(/:(?!:)/) - # FIXME: don't match a?b:c + if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/) kind = :label - elsif match == 'class' - state = :class_name_expected + match << matched + else + label_expected = false + if kind == :reserved + case match + when 'class' + state = :class_name_expected + when 'case', 'default' + case_expected = true + end + end end elsif scan(/\$/) @@ -95,23 +117,30 @@ module Scanners state = :string kind = :delimiter - elsif scan(/#\s*(\w*)/) + elsif scan(/#[ \t]*(\w*)/) kind = :preprocessor + in_preproc_line = true + label_expected_before_preproc_line = label_expected state = :include_expected if self[1] == 'include' elsif scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox) + label_expected = false kind = :char elsif scan(/0[xX][0-9A-Fa-f]+/) + label_expected = false kind = :hex elsif scan(/(?:0[0-7]+)(?![89.eEfF])/) + label_expected = false kind = :oct elsif scan(/(?:\d+)(?![.eEfF])L?L?/) + label_expected = false kind = :integer elsif scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/) + label_expected = false kind = :float else @@ -127,6 +156,7 @@ module Scanners tokens << ['"', :delimiter] tokens << [:close, :string] state = :initial + label_expected = false next elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox) kind = :char @@ -134,6 +164,7 @@ module Scanners tokens << [:close, :string] kind = :error state = :initial + label_expected = false else raise_inspect "else case \" reached; %p not handled." % peek(1), tokens end |