rouge 3.19.0 → 3.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rouge.rb +1 -0
  3. data/lib/rouge/cli.rb +32 -2
  4. data/lib/rouge/demos/augeas +16 -0
  5. data/lib/rouge/demos/bibtex +12 -0
  6. data/lib/rouge/demos/brightscript +6 -0
  7. data/lib/rouge/demos/email +11 -0
  8. data/lib/rouge/demos/hlsl +20 -0
  9. data/lib/rouge/demos/j +12 -0
  10. data/lib/rouge/demos/janet +3 -0
  11. data/lib/rouge/demos/livescript +15 -0
  12. data/lib/rouge/demos/postscript +9 -0
  13. data/lib/rouge/demos/ssh +4 -0
  14. data/lib/rouge/demos/systemd +4 -0
  15. data/lib/rouge/demos/velocity +9 -0
  16. data/lib/rouge/demos/zig +6 -0
  17. data/lib/rouge/formatters/html_line_highlighter.rb +26 -0
  18. data/lib/rouge/lexer.rb +38 -20
  19. data/lib/rouge/lexers/apex.rb +9 -7
  20. data/lib/rouge/lexers/augeas.rb +93 -0
  21. data/lib/rouge/lexers/batchfile.rb +1 -1
  22. data/lib/rouge/lexers/bibtex.rb +115 -0
  23. data/lib/rouge/lexers/brightscript.rb +147 -0
  24. data/lib/rouge/lexers/cpp.rb +11 -4
  25. data/lib/rouge/lexers/css.rb +3 -1
  26. data/lib/rouge/lexers/diff.rb +1 -1
  27. data/lib/rouge/lexers/docker.rb +1 -1
  28. data/lib/rouge/lexers/elm.rb +5 -5
  29. data/lib/rouge/lexers/email.rb +39 -0
  30. data/lib/rouge/lexers/ghc_core.rb +2 -1
  31. data/lib/rouge/lexers/graphql.rb +1 -1
  32. data/lib/rouge/lexers/hack.rb +1 -1
  33. data/lib/rouge/lexers/haskell.rb +27 -19
  34. data/lib/rouge/lexers/hlsl.rb +166 -0
  35. data/lib/rouge/lexers/html.rb +7 -7
  36. data/lib/rouge/lexers/http.rb +8 -2
  37. data/lib/rouge/lexers/isbl.rb +2 -2
  38. data/lib/rouge/lexers/j.rb +244 -0
  39. data/lib/rouge/lexers/janet.rb +218 -0
  40. data/lib/rouge/lexers/javascript.rb +10 -5
  41. data/lib/rouge/lexers/jinja.rb +22 -7
  42. data/lib/rouge/lexers/jsl.rb +1 -1
  43. data/lib/rouge/lexers/jsonnet.rb +4 -3
  44. data/lib/rouge/lexers/jsp.rb +2 -3
  45. data/lib/rouge/lexers/jsx.rb +47 -59
  46. data/lib/rouge/lexers/julia.rb +4 -2
  47. data/lib/rouge/lexers/kotlin.rb +7 -3
  48. data/lib/rouge/lexers/livescript.rb +310 -0
  49. data/lib/rouge/lexers/opentype_feature_file.rb +26 -42
  50. data/lib/rouge/lexers/perl.rb +21 -3
  51. data/lib/rouge/lexers/php.rb +274 -128
  52. data/lib/rouge/lexers/postscript.rb +93 -0
  53. data/lib/rouge/lexers/powershell.rb +5 -3
  54. data/lib/rouge/lexers/q.rb +1 -1
  55. data/lib/rouge/lexers/rego.rb +27 -12
  56. data/lib/rouge/lexers/ruby.rb +3 -3
  57. data/lib/rouge/lexers/rust.rb +3 -1
  58. data/lib/rouge/lexers/sass/common.rb +1 -0
  59. data/lib/rouge/lexers/smarty.rb +1 -1
  60. data/lib/rouge/lexers/ssh.rb +33 -0
  61. data/lib/rouge/lexers/systemd.rb +34 -0
  62. data/lib/rouge/lexers/tsx.rb +10 -3
  63. data/lib/rouge/lexers/twig.rb +4 -4
  64. data/lib/rouge/lexers/typescript.rb +1 -12
  65. data/lib/rouge/lexers/typescript/common.rb +18 -4
  66. data/lib/rouge/lexers/velocity.rb +71 -0
  67. data/lib/rouge/lexers/wollok.rb +0 -1
  68. data/lib/rouge/lexers/xml.rb +5 -3
  69. data/lib/rouge/lexers/yaml.rb +5 -3
  70. data/lib/rouge/lexers/zig.rb +139 -0
  71. data/lib/rouge/regex_lexer.rb +56 -1
  72. data/lib/rouge/version.rb +1 -1
  73. metadata +29 -2
@@ -0,0 +1,166 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ load_lexer 'c.rb'
7
+
8
+ class HLSL < C
9
+ title "HLSL"
10
+ desc "HLSL, the High Level Shading Language for DirectX (docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl)"
11
+ tag 'hlsl'
12
+ filenames '*.hlsl', '*.hlsli'
13
+ mimetypes 'text/x-hlsl'
14
+
15
+ def self.keywords
16
+ @keywords ||= Set.new %w(
17
+ asm asm_fragment break case cbuffer centroid class column_major
18
+ compile compile_fragment const continue default discard do else export
19
+ extern for fxgroup globallycoherent groupshared if in inline inout
20
+ interface line lineadj linear namespace nointerpolation noperspective
21
+ NULL out packoffset pass pixelfragment point precise return register
22
+ row_major sample sampler shared stateblock stateblock_state static
23
+ struct switch tbuffer technique technique10 technique11 texture
24
+ typedef triangle uniform vertexfragment volatile while
25
+ )
26
+ end
27
+
28
+ def self.keywords_type
29
+ @keywords_type ||= Set.new %w(
30
+ dword matrix snorm string unorm unsigned void vector BlendState Buffer
31
+ ByteAddressBuffer ComputeShader DepthStencilState DepthStencilView
32
+ DomainShader GeometryShader HullShader InputPatch LineStream
33
+ OutputPatch PixelShader PointStream RasterizerState RenderTargetView
34
+ RasterizerOrderedBuffer RasterizerOrderedByteAddressBuffer
35
+ RasterizerOrderedStructuredBuffer RasterizerOrderedTexture1D
36
+ RasterizerOrderedTexture1DArray RasterizerOrderedTexture2D
37
+ RasterizerOrderedTexture2DArray RasterizerOrderedTexture3D RWBuffer
38
+ RWByteAddressBuffer RWStructuredBuffer RWTexture1D RWTexture1DArray
39
+ RWTexture2D RWTexture2DArray RWTexture3D SamplerState
40
+ SamplerComparisonState StructuredBuffer Texture1D Texture1DArray
41
+ Texture2D Texture2DArray Texture2DMS Texture2DMSArray Texture3D
42
+ TextureCube TextureCubeArray TriangleStream VertexShader
43
+
44
+ bool1 bool2 bool3 bool4 BOOL1 BOOL2 BOOL3 BOOL4
45
+ int1 int2 int3 int4
46
+ half1 half2 half3 half4
47
+ float1 float2 float3 float4
48
+ double1 double2 double3 double4
49
+
50
+ bool1x1 bool1x2 bool1x3 bool1x4 bool2x1 bool2x2 bool2x3 bool2x4
51
+ bool3x1 bool3x2 bool3x3 bool3x4 bool4x1 bool4x2 bool4x3 bool4x4
52
+ BOOL1x1 BOOL1x2 BOOL1x3 BOOL1x4 BOOL2x1 BOOL2x2 BOOL2x3 BOOL2x4
53
+ BOOL3x1 BOOL3x2 BOOL3x3 BOOL3x4 BOOL4x1 BOOL4x2 BOOL4x3 BOOL4x4
54
+ half1x1 half1x2 half1x3 half1x4 half2x1 half2x2 half2x3 half2x4
55
+ half3x1 half3x2 half3x3 half3x4 half4x1 half4x2 half4x3 half4x4
56
+ int1x1 int1x2 int1x3 int1x4 int2x1 int2x2 int2x3 int2x4
57
+ int3x1 int3x2 int3x3 int3x4 int4x1 int4x2 int4x3 int4x4
58
+ float1x1 float1x2 float1x3 float1x4 float2x1 float2x2 float2x3 float2x4
59
+ float3x1 float3x2 float3x3 float3x4 float4x1 float4x2 float4x3 float4x4
60
+ double1x1 double1x2 double1x3 double1x4 double2x1 double2x2 double2x3 double2x4
61
+ double3x1 double3x2 double3x3 double3x4 double4x1 double4x2 double4x3 double4x4
62
+ )
63
+ end
64
+
65
+ def self.reserved
66
+ @reserved ||= Set.new %w(
67
+ auto catch char const_cast delete dynamic_cast enum explicit friend
68
+ goto long mutable new operator private protected public
69
+ reinterpret_cast short signed sizeof static_cast template this throw
70
+ try typename union unsigned using virtual
71
+ )
72
+ end
73
+
74
+ def self.builtins
75
+ @builtins ||= Set.new %w(
76
+ abort abs acos all AllMemoryBarrier AllMemoryBarrierWithGroupSync any
77
+ AppendStructuredBuffer asdouble asfloat asin asint asuint asuint atan
78
+ atan2 ceil CheckAccessFullyMapped clamp clip CompileShader
79
+ ConsumeStructuredBuffer cos cosh countbits cross D3DCOLORtoUBYTE4 ddx
80
+ ddx_coarse ddx_fine ddy ddy_coarse ddy_fine degrees determinant
81
+ DeviceMemoryBarrier DeviceMemoryBarrierWithGroupSync distance dot dst
82
+ errorf EvaluateAttributeAtCentroid EvaluateAttributeAtSample
83
+ EvaluateAttributeSnapped exp exp2 f16tof32 f32tof16 faceforward
84
+ firstbithigh firstbitlow floor fma fmod frac frexp fwidth
85
+ GetRenderTargetSampleCount GetRenderTargetSamplePosition
86
+ GlobalOrderedCountIncrement GroupMemoryBarrier
87
+ GroupMemoryBarrierWithGroupSync InterlockedAdd InterlockedAnd
88
+ InterlockedCompareExchange InterlockedCompareStore InterlockedExchange
89
+ InterlockedMax InterlockedMin InterlockedOr InterlockedXor isfinite
90
+ isinf isnan ldexp length lerp lit log log10 log2 mad max min modf
91
+ msad4 mul noise normalize pow printf Process2DQuadTessFactorsAvg
92
+ Process2DQuadTessFactorsMax Process2DQuadTessFactorsMin
93
+ ProcessIsolineTessFactors ProcessQuadTessFactorsAvg
94
+ ProcessQuadTessFactorsMax ProcessQuadTessFactorsMin
95
+ ProcessTriTessFactorsAvg ProcessTriTessFactorsMax
96
+ ProcessTriTessFactorsMin QuadReadLaneAt QuadSwapX QuadSwapY radians
97
+ rcp reflect refract reversebits round rsqrt saturate sign sin sincos
98
+ sinh smoothstep sqrt step tan tanh tex1D tex1D tex1Dbias tex1Dgrad
99
+ tex1Dlod tex1Dproj tex2D tex2D tex2Dbias tex2Dgrad tex2Dlod tex2Dproj
100
+ tex3D tex3D tex3Dbias tex3Dgrad tex3Dlod tex3Dproj texCUBE texCUBE
101
+ texCUBEbias texCUBEgrad texCUBElod texCUBEproj transpose trunc
102
+ WaveAllBitAnd WaveAllMax WaveAllMin WaveAllBitOr WaveAllBitXor
103
+ WaveAllEqual WaveAllProduct WaveAllSum WaveAllTrue WaveAnyTrue
104
+ WaveBallot WaveGetLaneCount WaveGetLaneIndex WaveGetOrderedIndex
105
+ WaveIsHelperLane WaveOnce WavePrefixProduct WavePrefixSum
106
+ WaveReadFirstLane WaveReadLaneAt
107
+
108
+ SV_CLIPDISTANCE SV_CLIPDISTANCE0 SV_CLIPDISTANCE1 SV_CULLDISTANCE
109
+ SV_CULLDISTANCE0 SV_CULLDISTANCE1 SV_COVERAGE SV_DEPTH
110
+ SV_DEPTHGREATEREQUAL SV_DEPTHLESSEQUAL SV_DISPATCHTHREADID
111
+ SV_DOMAINLOCATION SV_GROUPID SV_GROUPINDEX SV_GROUPTHREADID
112
+ SV_GSINSTANCEID SV_INNERCOVERAGE SV_INSIDETESSFACTOR SV_INSTANCEID
113
+ SV_ISFRONTFACE SV_OUTPUTCONTROLPOINTID SV_POSITION SV_PRIMITIVEID
114
+ SV_RENDERTARGETARRAYINDEX SV_SAMPLEINDEX SV_STENCILREF SV_TESSFACTOR
115
+ SV_VERTEXID SV_VIEWPORTARRAYINDEX
116
+
117
+ allow_uav_condition branch call domain earlydepthstencil fastopt
118
+ flatten forcecase instance loop maxtessfactor numthreads
119
+ outputcontrolpoints outputtopology partitioning patchconstantfunc
120
+ unroll
121
+
122
+ BINORMAL BINORMAL0 BINORMAL1 BINORMAL2 BINORMAL3 BINORMAL4
123
+ BLENDINDICES0 BLENDINDICES1 BLENDINDICES2 BLENDINDICES3 BLENDINDICES4
124
+ BLENDWEIGHT0 BLENDWEIGHT1 BLENDWEIGHT2 BLENDWEIGHT3 BLENDWEIGHT4 COLOR
125
+ COLOR0 COLOR1 COLOR2 COLOR3 COLOR4 NORMAL NORMAL0 NORMAL1 NORMAL2
126
+ NORMAL3 NORMAL4 POSITION POSITION0 POSITION1 POSITION2 POSITION3
127
+ POSITION4 POSITIONT PSIZE0 PSIZE1 PSIZE2 PSIZE3 PSIZE4 TANGENT
128
+ TANGENT0 TANGENT1 TANGENT2 TANGENT3 TANGENT4 TESSFACTOR0 TESSFACTOR1
129
+ TESSFACTOR2 TESSFACTOR3 TESSFACTOR4 TEXCOORD0 TEXCOORD1 TEXCOORD2
130
+ TEXCOORD3 TEXCOORD4
131
+
132
+ FOG PSIZE
133
+
134
+ VFACE VPOS
135
+
136
+ DEPTH0 DEPTH1 DEPTH2 DEPTH3 DEPTH4
137
+ )
138
+ end
139
+
140
+ ws = %r((?:\s|//.*?\n|/[*].*?[*]/)+)
141
+ id = /[a-zA-Z_][a-zA-Z0-9_]*/
142
+
143
+ state :root do
144
+ mixin :expr_whitespace
145
+ rule %r(
146
+ ([\w*\s]+?[\s*]) # return arguments
147
+ (#{id}) # function name
148
+ (\s*\([^;]*?\)(?:\s*:\s+#{id})?) # signature
149
+ (#{ws}?)({|;) # open brace or semicolon
150
+ )mx do |m|
151
+ # This is copied from the C lexer
152
+ recurse m[1]
153
+ token Name::Function, m[2]
154
+ recurse m[3]
155
+ recurse m[4]
156
+ token Punctuation, m[5]
157
+ if m[5] == ?{
158
+ push :function
159
+ end
160
+ end
161
+ rule %r/\{/, Punctuation, :function
162
+ mixin :statements
163
+ end
164
+ end
165
+ end
166
+ end
@@ -7,7 +7,7 @@ module Rouge
7
7
  title "HTML"
8
8
  desc "HTML, the markup language of the web"
9
9
  tag 'html'
10
- filenames '*.htm', '*.html', '*.xhtml'
10
+ filenames '*.htm', '*.html', '*.xhtml', '*.cshtml'
11
11
  mimetypes 'text/html', 'application/xhtml+xml'
12
12
 
13
13
  def self.detect?(text)
@@ -47,13 +47,13 @@ module Rouge
47
47
  rule %r(</), Name::Tag, :tag_end
48
48
  rule %r/</, Name::Tag, :tag_start
49
49
 
50
- rule %r(<\s*[a-zA-Z0-9:-]+), Name::Tag, :tag # opening tags
51
- rule %r(<\s*/\s*[a-zA-Z0-9:-]+\s*>), Name::Tag # closing tags
50
+ rule %r(<\s*[\p{L}:_-][\p{Word}\p{Cf}:.·-]*), Name::Tag, :tag # opening tags
51
+ rule %r(<\s*/\s*[\p{L}:_-][\p{Word}\p{Cf}:.·-]*\s*>), Name::Tag # closing tags
52
52
  end
53
53
 
54
54
  state :tag_end do
55
55
  mixin :tag_end_end
56
- rule %r/[a-zA-Z0-9:-]+/ do
56
+ rule %r/[\p{L}:_-][\p{Word}\p{Cf}:.·-]*/ do
57
57
  token Name::Tag
58
58
  goto :tag_end_end
59
59
  end
@@ -67,7 +67,7 @@ module Rouge
67
67
  state :tag_start do
68
68
  rule %r/\s+/, Text
69
69
 
70
- rule %r/[a-zA-Z0-9:-]+/ do
70
+ rule %r/[\p{L}:_-][\p{Word}\p{Cf}:.·-]*/ do
71
71
  token Name::Tag
72
72
  goto :tag
73
73
  end
@@ -83,8 +83,8 @@ module Rouge
83
83
 
84
84
  state :tag do
85
85
  rule %r/\s+/m, Text
86
- rule %r/[a-zA-Z0-9_:\[\]()*.-]+\s*=\s*/m, Name::Attribute, :attr
87
- rule %r/[a-zA-Z0-9_:#*-]+/, Name::Attribute
86
+ rule %r/[\p{L}:_\[\]()*.-][\p{Word}\p{Cf}:.·\[\]()*-]*\s*=\s*/m, Name::Attribute, :attr
87
+ rule %r/[\p{L}:_*#-][\p{Word}\p{Cf}:.·*#-]*/, Name::Attribute
88
88
  rule %r(/?\s*>)m, Name::Tag, :pop!
89
89
  end
90
90
 
@@ -8,16 +8,22 @@ module Rouge
8
8
  title "HTTP"
9
9
  desc 'http requests and responses'
10
10
 
11
+ option :content, "the language for the content (default: auto-detect)"
12
+
11
13
  def self.http_methods
12
14
  @http_methods ||= %w(GET POST PUT DELETE HEAD OPTIONS TRACE PATCH)
13
15
  end
14
16
 
15
17
  def content_lexer
18
+ @content_lexer ||= (lexer_option(:content) || guess_content_lexer)
19
+ end
20
+
21
+ def guess_content_lexer
16
22
  return Lexers::PlainText unless @content_type
17
23
 
18
- @content_lexer ||= Lexer.guess_by_mimetype(@content_type)
24
+ Lexer.guess_by_mimetype(@content_type)
19
25
  rescue Lexer::AmbiguousGuess
20
- @content_lexer = Lexers::PlainText
26
+ Lexers::PlainText
21
27
  end
22
28
 
23
29
  start { @content_type = 'text/plain' }
@@ -41,7 +41,7 @@ module Rouge
41
41
 
42
42
  state :dotted do
43
43
  mixin :whitespace
44
- rule %r/[a-zа-яё_0-9]*/i do |m|
44
+ rule %r/[a-zа-яё_0-9]+/i do |m|
45
45
  name = m[0]
46
46
  if self.class.constants.include? name.downcase
47
47
  token Name::Builtin
@@ -56,7 +56,7 @@ module Rouge
56
56
 
57
57
  state :type do
58
58
  mixin :whitespace
59
- rule %r/[a-zа-яё_0-9]*/i do |m|
59
+ rule %r/[a-zа-яё_0-9]+/i do |m|
60
60
  name = m[0]
61
61
  if self.class.interfaces.include? name.downcase
62
62
  token Keyword::Type
@@ -0,0 +1,244 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ class J < RegexLexer
7
+ title 'J'
8
+ desc "The J programming language (jsoftware.com)"
9
+ tag 'j'
10
+ filenames '*.ijs', '*.ijt'
11
+
12
+ # For J-specific terms we use, see:
13
+ # https://code.jsoftware.com/wiki/Vocabulary/AET
14
+ # https://code.jsoftware.com/wiki/Vocabulary/Glossary
15
+
16
+ # https://code.jsoftware.com/wiki/Vocabulary/PartsOfSpeech
17
+ def self.token_map
18
+ @token_map ||= {
19
+ noun: Keyword::Constant,
20
+ verb: Name::Function,
21
+ modifier: Operator,
22
+ name: Name,
23
+ param: Name::Builtin::Pseudo,
24
+ other: Punctuation,
25
+ nil => Error,
26
+ }
27
+ end
28
+
29
+ # https://code.jsoftware.com/wiki/NuVoc
30
+ def self.inflection_list
31
+ @inflection_list ||= ['', '.', ':', '..', '.:', ':.', '::']
32
+ end
33
+
34
+ def self.primitive_table
35
+ @primitive_table ||= Hash.new([:name]).tap do |h|
36
+ {
37
+ '()' => [:other],
38
+ '=' => [:verb, :other, :other],
39
+ '<>+-*%$|,#' => [:verb, :verb, :verb],
40
+ '^' => [:verb, :verb, :modifier],
41
+ '~"' => [:modifier, :verb, :verb],
42
+ '.:@' => [:modifier, :modifier, :modifier],
43
+ ';' => [:verb, :modifier, :verb],
44
+ '!' => [:verb, :modifier, :modifier],
45
+ '/\\' => [:modifier, :modifier, :verb],
46
+ '[' => [:verb, nil, :verb],
47
+ ']' => [:verb],
48
+ '{' => [:verb, :verb, :verb, nil, nil, nil, :verb],
49
+ '}' => [:modifier, :verb, :verb, nil, nil, nil, :modifier],
50
+ '`' => [:modifier, nil, :modifier],
51
+ '&' => [:modifier, :modifier, :modifier, nil, :modifier],
52
+ '?' => [:verb, :verb],
53
+ 'a' => [:name, :noun, :noun],
54
+ 'ACeEIjorv' => [:name, :verb],
55
+ 'bdfHMT' => [:name, :modifier],
56
+ 'Dt' => [:name, :modifier, :modifier],
57
+ 'F' => [:name, :modifier, :modifier, :modifier, :modifier,
58
+ :modifier, :modifier],
59
+ 'iu' => [:name, :verb, :verb],
60
+ 'L' => [:name, :verb, :modifier],
61
+ 'mny' => [:param],
62
+ 'p' => [:name, :verb, :verb, :verb],
63
+ 'qsZ' => [:name, nil, :verb],
64
+ 'S' => [:name, nil, :modifier],
65
+ 'u' => [:param, :verb, :verb],
66
+ 'v' => [:param, :verb],
67
+ 'x' => [:param, nil, :verb],
68
+ }.each {|k, v| k.each_char {|c| h[c] = v } }
69
+ end
70
+ end
71
+
72
+ def self.primitive(char, inflection)
73
+ i = inflection_list.index(inflection) or return Error
74
+ token_map[primitive_table[char][i]]
75
+ end
76
+
77
+ def self.control_words
78
+ @control_words ||= Set.new %w(
79
+ assert break case catch catchd catcht continue do else elseif end
80
+ fcase for if return select throw try while whilst
81
+ )
82
+ end
83
+
84
+ def self.control_words_id
85
+ @control_words_id ||= Set.new %w(for goto label)
86
+ end
87
+
88
+ state :expr do
89
+ rule %r/\s+/, Text
90
+
91
+ rule %r'([!-&(-/:-@\[-^`{-~]|[A-Za-z]\b)([.:]*)' do |m|
92
+ token J.primitive(m[1], m[2])
93
+ end
94
+
95
+ rule %r/(?:\d|_\d?):([.:]*)/ do |m|
96
+ token m[1].empty? ? J.token_map[:verb] : Error
97
+ end
98
+
99
+ rule %r/[\d_][\w.]*([.:]*)/ do |m|
100
+ token m[1].empty? ? Num : Error
101
+ end
102
+
103
+ rule %r/'/, Str::Single, :str
104
+
105
+ rule %r/NB\.(?![.:]).*/, Comment::Single
106
+
107
+ rule %r/([A-Za-z]\w*)([.:]*)/ do |m|
108
+ if m[2] == '.'
109
+ word, sep, id = m[1].partition '_'
110
+ list = if sep.empty?
111
+ J.control_words
112
+ elsif not id.empty?
113
+ J.control_words_id
114
+ end
115
+ if list and list.include? word
116
+ token Keyword, word + sep
117
+ token((word == 'for' ? Name : Name::Label), id)
118
+ token Keyword, m[2]
119
+ else
120
+ token Error
121
+ end
122
+ else
123
+ token m[2].empty? ? Name : Error
124
+ end
125
+ end
126
+ end
127
+
128
+ state :str do
129
+ rule %r/''/, Str::Escape
130
+ rule %r/[^'\n]+/, Str::Single
131
+ rule %r/'|$/, Str::Single, :pop!
132
+ end
133
+
134
+ start do
135
+ @note_next = false
136
+ end
137
+
138
+ state :root do
139
+ rule %r/\n/ do
140
+ token Text
141
+ if @note_next
142
+ push :note
143
+ @note_next = false
144
+ end
145
+ end
146
+
147
+ # https://code.jsoftware.com/wiki/Vocabulary/com
148
+ # https://code.jsoftware.com/wiki/Vocabulary/NounExplicitDefinition
149
+ rule %r/
150
+ ([0-4]|13|adverb|conjunction|dyad|monad|noun|verb)([\ \t]+)
151
+ (def(?:ine)?\b|:)(?![.:])([\ \t]*)
152
+ /x do |m|
153
+ groups Keyword::Pseudo, Text, Keyword::Pseudo, Text
154
+ @def_body = (m[1] == '0' || m[1] == 'noun') ? :noun : :code
155
+ if m[3] == 'define'
156
+ # stack: [:root]
157
+ # or [:root, ..., :def_next]
158
+ pop! if stack.size > 1
159
+ push @def_body
160
+ push :def_next # [:root, ..., @def_body, :def_next]
161
+ else
162
+ push :expl_def
163
+ end
164
+ end
165
+
166
+ rule %r/^([ \t]*)(Note\b(?![.:]))([ \t\r]*)(?!=[.:]|$)/ do
167
+ groups Text, Name, Text
168
+ @note_next = true
169
+ end
170
+
171
+ rule %r/[mnuvxy]\b(?![.:])/, Name
172
+ mixin :expr
173
+ end
174
+
175
+ state :def_next do
176
+ rule %r/\n/, Text, :pop!
177
+ mixin :root
178
+ end
179
+
180
+ state :expl_def do
181
+ rule %r/0\b(?![.:])/ do
182
+ token Keyword::Pseudo
183
+ # stack: [:root, :expl_def]
184
+ # or [:root, ..., :def_next, :expl_def]
185
+ pop! if stack.size > 2
186
+ goto @def_body
187
+ push :def_next # [:root, ..., @def_body, :def_next]
188
+ end
189
+ rule %r/'/ do
190
+ if @def_body == :noun
191
+ token Str::Single
192
+ goto :str
193
+ else
194
+ token Punctuation
195
+ goto :q_expr
196
+ end
197
+ end
198
+ rule(//) { pop! }
199
+ end
200
+
201
+ # `q_expr` lexes the content of a string literal which is a part of an
202
+ # explicit definition.
203
+ # e.g. dyad def 'x + y'
204
+ state :q_expr do
205
+ rule %r/''/, Str::Single, :q_str
206
+ rule %r/'|$/, Punctuation, :pop!
207
+ rule %r/NB\.(?![.:])([^'\n]|'')*/, Comment::Single
208
+ mixin :expr
209
+ end
210
+
211
+ state :q_str do
212
+ rule %r/''''/, Str::Escape
213
+ rule %r/[^'\n]+/, Str::Single
214
+ rule %r/''/, Str::Single, :pop!
215
+ rule(/'|$/) { token Punctuation; pop! 2 }
216
+ end
217
+
218
+ state :note do
219
+ mixin :delimiter
220
+ rule %r/.+\n?/, Comment::Multiline
221
+ end
222
+
223
+ state :noun do
224
+ mixin :delimiter
225
+ rule %r/.+\n?/, Str::Heredoc
226
+ end
227
+
228
+ state :code do
229
+ mixin :delimiter
230
+ rule %r/^([ \t]*)(:)([ \t\r]*)$/ do
231
+ groups Text, Punctuation, Text
232
+ end
233
+ mixin :expr
234
+ end
235
+
236
+ state :delimiter do
237
+ rule %r/^([ \t]*)(\))([ \t\r]*$\n?)/ do
238
+ groups Text, Punctuation, Text
239
+ pop!
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end