rouge 3.7.0 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/lib/rouge/demos/armasm +12 -0
  4. data/lib/rouge/demos/batchfile +3 -0
  5. data/lib/rouge/demos/bbcbasic +6 -0
  6. data/lib/rouge/demos/cmhg +8 -0
  7. data/lib/rouge/demos/cython +6 -0
  8. data/lib/rouge/demos/eex +1 -0
  9. data/lib/rouge/demos/epp +4 -0
  10. data/lib/rouge/demos/haxe +5 -0
  11. data/lib/rouge/demos/hql +5 -0
  12. data/lib/rouge/demos/msgtrans +4 -0
  13. data/lib/rouge/demos/plist +1 -132
  14. data/lib/rouge/demos/terraform +0 -15
  15. data/lib/rouge/formatters/html_line_table.rb +3 -1
  16. data/lib/rouge/formatters/tex.rb +11 -12
  17. data/lib/rouge/guessers/disambiguation.rb +8 -0
  18. data/lib/rouge/lexers/armasm.rb +145 -0
  19. data/lib/rouge/lexers/batchfile.rb +164 -0
  20. data/lib/rouge/lexers/bbcbasic.rb +112 -0
  21. data/lib/rouge/lexers/cmhg.rb +34 -0
  22. data/lib/rouge/lexers/console.rb +1 -1
  23. data/lib/rouge/lexers/cpp.rb +4 -1
  24. data/lib/rouge/lexers/cython.rb +151 -0
  25. data/lib/rouge/lexers/eex.rb +51 -0
  26. data/lib/rouge/lexers/elixir.rb +20 -9
  27. data/lib/rouge/lexers/epp.rb +51 -0
  28. data/lib/rouge/lexers/haxe.rb +246 -0
  29. data/lib/rouge/lexers/hql.rb +139 -0
  30. data/lib/rouge/lexers/http.rb +5 -5
  31. data/lib/rouge/lexers/javascript.rb +1 -1
  32. data/lib/rouge/lexers/json.rb +1 -1
  33. data/lib/rouge/lexers/julia.rb +1 -1
  34. data/lib/rouge/lexers/make.rb +39 -12
  35. data/lib/rouge/lexers/matlab.rb +4 -2
  36. data/lib/rouge/lexers/matlab/builtins.yml +3515 -0
  37. data/lib/rouge/lexers/msgtrans.rb +26 -0
  38. data/lib/rouge/lexers/plain_text.rb +1 -1
  39. data/lib/rouge/lexers/puppet.rb +2 -2
  40. data/lib/rouge/lexers/q.rb +1 -1
  41. data/lib/rouge/lexers/r.rb +2 -3
  42. data/lib/rouge/lexers/sed.rb +1 -1
  43. data/lib/rouge/lexers/sql.rb +26 -6
  44. data/lib/rouge/lexers/terraform.rb +8 -0
  45. data/lib/rouge/tex_theme_renderer.rb +2 -1
  46. data/lib/rouge/themes/magritte.rb +2 -2
  47. data/lib/rouge/version.rb +1 -1
  48. data/rouge.gemspec +4 -2
  49. metadata +28 -6
  50. data/lib/rouge/lexers/matlab/builtins.rb +0 -13
@@ -0,0 +1,164 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ class Batchfile < RegexLexer
7
+ title "Batchfile"
8
+ desc "Windows Batch File"
9
+
10
+ tag 'batchfile'
11
+ aliases 'bat', 'batch', 'dosbatch', 'winbatch'
12
+ filenames '*.bat', '*.cmd'
13
+
14
+ mimetypes 'application/bat', 'application/x-bat', 'application/x-msdos-program'
15
+
16
+ def self.keywords
17
+ @keywords ||= %w(
18
+ if else for in do goto call exit
19
+ )
20
+ end
21
+
22
+ def self.operator_words
23
+ @operator_words ||= %w(
24
+ exist defined errorlevel cmdextversion not equ neq lss leq gtr geq
25
+ )
26
+ end
27
+
28
+ def self.devices
29
+ @devices ||= %w(
30
+ con prn aux nul com1 com2 com3 com4 com5 com6 com7 com8 com9 lpt1 lpt2
31
+ lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9
32
+ )
33
+ end
34
+
35
+ def self.builtin_commands
36
+ @builtin_commands ||= %w(
37
+ assoc attrib break bcdedit cacls cd chcp chdir chkdsk chkntfs choice
38
+ cls cmd color comp compact convert copy date del dir diskpart doskey
39
+ dpath driverquery echo endlocal erase fc find findstr format fsutil
40
+ ftype gpresult graftabl help icacls label md mkdir mklink mode more
41
+ move openfiles path pause popd print prompt pushd rd recover ren
42
+ rename replace rmdir robocopy setlocal sc schtasks shift shutdown sort
43
+ start subst systeminfo takeown tasklist taskkill time timeout title
44
+ tree type ver verify vol xcopy waitfor wmic
45
+ )
46
+ end
47
+
48
+ def self.other_commands
49
+ @other_commands ||= %w(
50
+ addusers admodcmd ansicon arp at bcdboot bitsadmin browstat certreq
51
+ certutil change cidiag cipher cleanmgr clip cmdkey compress convertcp
52
+ coreinfo csccmd csvde cscript curl debug defrag delprof deltree devcon
53
+ diamond dirquota diruse diskshadow diskuse dism dnscmd dsacls dsadd
54
+ dsget dsquery dsmod dsmove dsrm dsmgmt dsregcmd edlin eventcreate
55
+ expand extract fdisk fltmc forfiles freedisk ftp getmac gpupdate
56
+ hostname ifmember inuse ipconfig kill lgpo lodctr logman logoff
57
+ logtime makecab mapisend mbsacli mem mountvol moveuser msg mshta
58
+ msiexec msinfo32 mstsc nbtstat net net1 netdom netsh netstat nlsinfo
59
+ nltest now nslookup ntbackup ntdsutil ntoskrnl ntrights nvspbind
60
+ pathping perms ping portqry powercfg pngout pnputil printbrm prncnfg
61
+ prnmngr procdump psexec psfile psgetsid psinfo pskill pslist
62
+ psloggedon psloglist pspasswd psping psservice psshutdown pssuspend
63
+ qbasic qgrep qprocess query quser qwinsta rasdial reg reg1 regdump
64
+ regedt32 regsvr32 regini reset restore rundll32 rmtshare route rpcping
65
+ run runas scandisk setspn setx sfc share shellrunas shortcut sigcheck
66
+ sleep slmgr strings subinacl sysmon telnet tftp tlist touch tracerpt
67
+ tracert tscon tsdiscon tskill tttracer typeperf tzutil undelete
68
+ unformat verifier vmconnect vssadmin w32tm wbadmin wecutil wevtutil
69
+ wget where whoami windiff winrm winrs wpeutil wpr wusa wuauclt wscript
70
+ )
71
+ end
72
+
73
+ def self.attributes
74
+ @attributes ||= %w(
75
+ on off disable enableextensions enabledelayedexpansion
76
+ )
77
+ end
78
+
79
+ state :basic do
80
+ # Comments
81
+ rule %r/\brem\b.*$/i, Comment
82
+ # Empty Labels
83
+ rule %r/^::.*$/, Comment
84
+
85
+ # Labels
86
+ rule %r/:[a-z]+/i, Name::Label
87
+
88
+ rule %r/([a-z]\w*)(\.exe|com|bat|cmd|msi)?/i do |m|
89
+ if self.class.devices.include? m[1]
90
+ groups Keyword::Reserved, Error
91
+ elsif self.class.keywords.include? m[1]
92
+ groups Keyword, Error
93
+ elsif self.class.operator_words.include? m[1]
94
+ groups Operator::Word, Error
95
+ elsif self.class.builtin_commands.include? m[1]
96
+ token Name::Builtin
97
+ elsif self.class.other_commands.include? m[1]
98
+ token Name::Builtin
99
+ elsif self.class.attributes.include? m[1]
100
+ groups Name::Attribute, Error
101
+ elsif "set".casecmp m[1]
102
+ groups Keyword::Declaration, Error
103
+ else
104
+ token Text
105
+ end
106
+ end
107
+
108
+ rule %r/([\/\-+][a-z]+)\s*/i, Name::Attribute
109
+
110
+ mixin :expansions
111
+
112
+ rule %r/[<>&|(){}\[\]\-+=;,~?*]/, Operator
113
+ end
114
+
115
+ state :escape do
116
+ rule %r/\^./m, Str::Escape
117
+ end
118
+
119
+ state :expansions do
120
+ # Normal and Delayed expansion
121
+ rule %r/[%!]+([a-z_$@#]+)[%!]+/i, Name::Variable
122
+ # For Variables
123
+ rule %r/(\%+~?[a-z]+\d?)/i, Name::Variable::Magic
124
+ end
125
+
126
+ state :double_quotes do
127
+ mixin :escape
128
+ rule %r/["]/, Str::Double, :pop!
129
+ mixin :expansions
130
+ rule %r/[^\^"%!]+/, Str::Double
131
+ end
132
+
133
+ state :single_quotes do
134
+ mixin :escape
135
+ rule %r/[']/, Str::Single, :pop!
136
+ mixin :expansions
137
+ rule %r/[^\^'%!]+/, Str::Single
138
+ end
139
+
140
+ state :backtick do
141
+ mixin :escape
142
+ rule %r/[`]/, Str::Backtick, :pop!
143
+ mixin :expansions
144
+ rule %r/[^\^`%!]+/, Str::Backtick
145
+ end
146
+
147
+ state :data do
148
+ rule %r/\s+/, Text
149
+ rule %r/0x[0-9a-f]+/i, Literal::Number::Hex
150
+ rule %r/[0-9]/, Literal::Number
151
+ rule %r/["]/, Str::Double, :double_quotes
152
+ rule %r/[']/, Str::Single, :single_quotes
153
+ rule %r/[`]/, Str::Backtick, :backtick
154
+ rule %r/[^\s&|()\[\]{}\^=;!%+\-,"'`~?*]+/, Text
155
+ mixin :escape
156
+ end
157
+
158
+ state :root do
159
+ mixin :basic
160
+ mixin :data
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,112 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ class BBCBASIC < RegexLexer
7
+ title "BBCBASIC"
8
+ desc "BBC BASIC syntax"
9
+ tag 'bbcbasic'
10
+ filenames '*,fd1'
11
+
12
+ def self.punctuation
13
+ @punctuation ||= %w(
14
+ [,;'~] SPC TAB
15
+ )
16
+ end
17
+
18
+ def self.function
19
+ @function ||= %w(
20
+ ABS ACS ADVAL ASC ASN ATN BEATS BEAT BGET# CHR\$ COS COUNT DEG DIM
21
+ EOF# ERL ERR EVAL EXP EXT# FN GET\$# GET\$ GET HIMEM INKEY\$ INKEY
22
+ INSTR INT LEFT\$ LEN LN LOG LOMEM MID\$ OPENIN OPENOUT OPENUP PAGE
23
+ POINT POS PTR# RAD REPORT\$ RIGHT\$ RND SGN SIN SQR STR\$ STRING\$ SUM
24
+ SUMLEN TAN TEMPO TIME\$ TIME TOP USR VAL VPOS
25
+ )
26
+ end
27
+
28
+ def self.statement
29
+ @statement ||= %w(
30
+ BEATS BPUT# CALL CASE CHAIN CLEAR CLG CLOSE# CLS COLOR COLOUR DATA
31
+ ELSE ENDCASE ENDIF ENDPROC ENDWHILE END ENVELOPE FOR GCOL GOSUB GOTO
32
+ IF INSTALL LET LIBRARY MODE NEXT OFF OF ON ORIGIN OSCI OTHERWISE
33
+ OVERLAY PLOT PRINT# PRINT PROC QUIT READ REPEAT REPORT RETURN SOUND
34
+ STEP STEREO STOP SWAP SYS THEN TINT TO VDU VOICES VOICE UNTIL WAIT
35
+ WHEN WHILE WIDTH
36
+ )
37
+ end
38
+
39
+ def self.operator
40
+ @operator ||= %w(
41
+ << <= <> < >= >>> >> > [-!$()*+/=?^|] AND DIV EOR MOD NOT OR
42
+ )
43
+ end
44
+
45
+ def self.constant
46
+ @constant ||= %w(
47
+ FALSE TRUE
48
+ )
49
+ end
50
+
51
+ state :expression do
52
+ rule %r/#{BBCBASIC.function.join('|')}/o, Name::Builtin # function or pseudo-variable
53
+ rule %r/#{BBCBASIC.operator.join('|')}/o, Operator
54
+ rule %r/#{BBCBASIC.constant.join('|')}/o, Name::Constant
55
+ rule %r/"[^"]*"/o, Literal::String
56
+ rule %r/[a-z_`][\w`]*[$%]?/io, Name::Variable
57
+ rule %r/@%/o, Name::Variable
58
+ rule %r/[\d.]+/o, Literal::Number
59
+ rule %r/%[01]+/o, Literal::Number::Bin
60
+ rule %r/&[\h]+/o, Literal::Number::Hex
61
+ end
62
+
63
+ state :root do
64
+ rule %r/(:+)( *)(\*)(.*)/ do
65
+ groups Punctuation, Text, Keyword, Text # CLI command
66
+ end
67
+ rule %r/(\n+ *)(\*)(.*)/ do
68
+ groups Text, Keyword, Text # CLI command
69
+ end
70
+ rule %r/(ELSE|OTHERWISE|REPEAT|THEN)( *)(\*)(.*)/ do
71
+ groups Keyword, Text, Keyword, Text # CLI command
72
+ end
73
+ rule %r/[ \n]+/o, Text
74
+ rule %r/:+/o, Punctuation
75
+ rule %r/[\[]/o, Keyword, :assembly1
76
+ rule %r/REM *>.*/o, Comment::Special
77
+ rule %r/REM.*/o, Comment
78
+ rule %r/(?:#{BBCBASIC.statement.join('|')}|CIRCLE(?: *FILL)?|DEF *(?:FN|PROC)|DRAW(?: *BY)?|DIM(?!\()|ELLIPSE(?: *FILL)?|ERROR(?: *EXT)?|FILL(?: *BY)?|INPUT(?:#| *LINE)?|LINE(?: *INPUT)?|LOCAL(?: *DATA| *ERROR)?|MOUSE(?: *COLOUR| *OFF| *ON| *RECTANGLE| *STEP| *TO)?|MOVE(?: *BY)?|ON(?! *ERROR)|ON *ERROR *(?:LOCAL|OFF)?|POINT(?: *BY)?(?!\()|RECTANGE(?: *FILL)?|RESTORE(?: *DATA| *ERROR)?|TRACE(?: *CLOSE| *ENDPROC| *OFF| *STEP(?: *FN| *ON| *PROC)?| *TO)?)/o, Keyword
79
+ mixin :expression
80
+ rule %r/#{BBCBASIC.punctuation.join('|')}/o, Punctuation
81
+ end
82
+
83
+ # Assembly statements are parsed as
84
+ # {label} {directive|opcode |']' {expressions}} {comment}
85
+ # Technically, you don't need whitespace between opcodes and arguments,
86
+ # but this is rare in uncrunched source and trying to enumerate all
87
+ # possible opcodes here is impractical so we colour it as though
88
+ # the whitespace is required. Opcodes and directives can only easily be
89
+ # distinguished from the symbols that make up expressions by looking at
90
+ # their position within the statement. Similarly, ']' is treated as a
91
+ # keyword at the start of a statement or as punctuation elsewhere. This
92
+ # requires a two-state state machine.
93
+
94
+ state :assembly1 do
95
+ rule %r/ +/o, Text
96
+ rule %r/]/o, Keyword, :pop!
97
+ rule %r/[:\n]/o, Punctuation
98
+ rule %r/\.[a-z_`][\w`]*%? */io, Name::Label
99
+ rule %r/(?:REM|;)[^:\n]*/o, Comment
100
+ rule %r/[^ :\n]+/o, Keyword, :assembly2
101
+ end
102
+
103
+ state :assembly2 do
104
+ rule %r/ +/o, Text
105
+ rule %r/[:\n]/o, Punctuation, :pop!
106
+ rule %r/(?:REM|;)[^:\n]*/o, Comment, :pop!
107
+ mixin :expression
108
+ rule %r/[!#,@\[\]^{}]/, Punctuation
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ class CMHG < RegexLexer
7
+ title "CMHG"
8
+ desc "RISC OS C module header generator source file"
9
+ tag 'cmhg'
10
+ filenames '*.cmhg'
11
+
12
+ def self.preproc_keyword
13
+ @preproc_keyword ||= %w(
14
+ define elif else endif error if ifdef ifndef include line pragma undef warning
15
+ )
16
+ end
17
+
18
+ state :root do
19
+ rule %r/;[^\n]*/, Comment
20
+ rule %r/^([ \t]*)(#[ \t]*(?:(?:#{CMHG.preproc_keyword.join('|')})(?:[ \t].*)?)?)(?=\n)/ do
21
+ groups Text, Comment::Preproc
22
+ end
23
+ rule %r/[-a-z]+:/, Keyword::Declaration
24
+ rule %r/[a-z_]\w+/i, Name::Entity
25
+ rule %r/"[^"]*"/, Literal::String
26
+ rule %r/(?:&|0x)\h+/, Literal::Number::Hex
27
+ rule %r/\d+/, Literal::Number
28
+ rule %r/[,\/()]/, Punctuation
29
+ rule %r/[ \t]+/, Text
30
+ rule %r/\n+/, Text
31
+ end
32
+ end
33
+ end
34
+ end
@@ -116,7 +116,7 @@ module Rouge
116
116
  # before we pass to the lang lexer so it can determine where
117
117
  # the "real" beginning of the line is
118
118
  $' =~ /\A\s*/
119
- yield Text, $& unless $&.empty?
119
+ yield Text::Whitespace, $& unless $&.empty?
120
120
 
121
121
  lang_lexer.continue_lex($', &output)
122
122
  elsif comment_regex =~ input[0].strip
@@ -17,7 +17,7 @@ module Rouge
17
17
  '*.cc', '*.hh',
18
18
  '*.cxx', '*.hxx',
19
19
  '*.pde', '*.ino',
20
- '*.tpp'
20
+ '*.tpp', '*.h'
21
21
  mimetypes 'text/x-c++hdr', 'text/x-c++src'
22
22
 
23
23
  def self.keywords
@@ -58,9 +58,11 @@ module Rouge
58
58
 
59
59
  prepend :statements do
60
60
  rule %r/class\b/, Keyword, :classname
61
+ rule %r/\d+(\.\d+)?(?:h|(?:min)|s|(?:ms)|(?:us)|(?:ns))/, Num::Other
61
62
  rule %r((#{dq}[.]#{dq}?|[.]#{dq})(e[+-]?#{dq}[lu]*)?)i, Num::Float
62
63
  rule %r(#{dq}e[+-]?#{dq}[lu]*)i, Num::Float
63
64
  rule %r/0x\h('?\h)*[lu]*/i, Num::Hex
65
+ rule %r/0b[01]+(?:_[01]+)*/, Num::Bin
64
66
  rule %r/0[0-7]('?[0-7])*[lu]*/i, Num::Oct
65
67
  rule %r/#{dq}[lu]*/i, Num::Integer
66
68
  rule %r/\bnullptr\b/, Name::Builtin
@@ -72,6 +74,7 @@ module Rouge
72
74
 
73
75
  # template specification
74
76
  rule %r/\s*(?=>)/m, Text, :pop!
77
+ rule %r/[.]{3}/, Operator
75
78
  mixin :whitespace
76
79
  end
77
80
  end
@@ -0,0 +1,151 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ load_lexer 'python.rb'
7
+
8
+ class Cython < Python
9
+ title "Cython"
10
+ desc "Cython and Pyrex source code (cython.org)"
11
+ tag 'cython'
12
+ aliases 'pyx', 'pyrex'
13
+ filenames '*.pyx', '*.pxd', '*.pxi'
14
+ mimetypes 'text/x-cython', 'application/x-cython'
15
+
16
+ def initialize(opts = {})
17
+ super opts
18
+ @indentation = nil
19
+ end
20
+
21
+ def self.keywords
22
+ @keywords ||= super + %w(
23
+ by except? fused gil nogil
24
+ )
25
+ end
26
+
27
+ def self.c_keywords
28
+ @ckeywords ||= %w(
29
+ public readonly extern api inline enum union
30
+ )
31
+ end
32
+
33
+ identifier = /[a-z_]\w*/i
34
+ dotted_identifier = /[a-z_.][\w.]*/i
35
+
36
+ prepend :root do
37
+ rule %r/cp?def|ctypedef/ do
38
+ token Keyword
39
+ push :c_definitions
40
+ push :c_start
41
+ end
42
+
43
+ rule %r/(from)((?:\\\s|\s)+)(#{dotted_identifier})((?:\\\s|\s)+)(cimport)/ do
44
+ groups Keyword::Namespace,
45
+ Text,
46
+ Name::Namespace,
47
+ Text,
48
+ Keyword::Namespace
49
+ end
50
+
51
+ rule %r/(cimport)(\s+)(#{dotted_identifier})/ do
52
+ groups Keyword::Namespace, Text, Name::Namespace
53
+ end
54
+
55
+ rule %r/(struct)((?:\\\s|\s)+)/ do
56
+ groups Keyword, Text
57
+ push :classname
58
+ end
59
+
60
+ mixin :func_call_fix
61
+
62
+ rule %r/[(,]/, Punctuation, :c_start
63
+ end
64
+
65
+ prepend :classname do
66
+ rule %r/(?:\\\s|\s)+/, Text
67
+ end
68
+
69
+ prepend :funcname do
70
+ rule %r/(?:\\\s|\s)+/, Text
71
+ end
72
+ # This is a fix for the way that function calls are lexed in the Python
73
+ # lexer. This should be moved to the Python lexer once confirmed that it
74
+ # does not cause any regressions.
75
+ state :func_call_fix do
76
+ rule %r/#{identifier}(?=\()/ do |m|
77
+ if self.class.keywords.include? m[0]
78
+ token Keyword
79
+ elsif self.class.exceptions.include? m[0]
80
+ token Name::Builtin
81
+ elsif self.class.builtins.include? m[0]
82
+ token Name::Builtin
83
+ elsif self.class.builtins_pseudo.include? m[0]
84
+ token Name::Builtin::Pseudo
85
+ else
86
+ token Name::Function
87
+ end
88
+ end
89
+ end
90
+
91
+ # The Cython lexer adds three states to those already in the Python lexer.
92
+ # Calls to `cdef`, `cpdef` and `ctypedef` move the lexer into the :c_start
93
+ # state. The primary purpose of this state is to highlight datatypes. Once
94
+ # this has been done, the lexer moves to the :c_definitions state where
95
+ # the majority of text in a definition is lexed. Finally, newlines cause
96
+ # the lexer to move to :c_indent. This state is used to check whether we
97
+ # have moved out of a C block.
98
+
99
+ state :c_start do
100
+ rule %r/[^\S\n]+/, Text
101
+
102
+ rule %r/cp?def|ctypedef/, Keyword
103
+
104
+ rule %r/(?:un)?signed/, Keyword::Type
105
+
106
+ # This rule matches identifiers that could be type declarations. The
107
+ # lookahead matches (1) pointers, (2) arrays and (3) variable names.
108
+ rule %r/#{identifier}(?=(?:\*+)|(?:[ \t]*\[)|(?:[ \t]+\w))/ do |m|
109
+ if self.class.keywords.include? m[0]
110
+ token Keyword
111
+ pop!
112
+ elsif %w(def).include? m[0]
113
+ token Keyword
114
+ goto :funcname
115
+ elsif %w(struct class).include? m[0]
116
+ token Keyword::Reserved
117
+ goto :classname
118
+ elsif self.class.c_keywords.include? m[0]
119
+ token Keyword::Reserved
120
+ else
121
+ token Keyword::Type
122
+ pop!
123
+ end
124
+ end
125
+
126
+ rule(//) { pop! }
127
+ end
128
+
129
+ state :c_definitions do
130
+ rule %r/\n/, Text, :c_indent
131
+ mixin :root
132
+ end
133
+
134
+ state :c_indent do
135
+ rule %r/[ \t]+/ do |m|
136
+ token Text
137
+ goto :c_start
138
+
139
+ if @indentation.nil?
140
+ @indentation = m[0]
141
+ elsif @indentation.length > m[0].length
142
+ @indentation = nil
143
+ pop! 2 # Pop :c_start and :c_definitions
144
+ end
145
+ end
146
+
147
+ rule(//) { @indentation = nil; reset_stack }
148
+ end
149
+ end
150
+ end
151
+ end