Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 13a5ba6

Browse files
committed
Add systemverilog scanner
1 parent cab119c commit 13a5ba6

File tree

3 files changed

+226
-15
lines changed

3 files changed

+226
-15
lines changed

lib/coderay/helpers/file_type.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,11 @@ def shebang filename
118118
'rxml' => :ruby,
119119
# 'sch' => :scheme,
120120
'sql' => :sql,
121+
'sv' => :systemverilog,
122+
'svh' => :systemverilog,
121123
# 'ss' => :scheme,
122124
'tmproj' => :xml,
125+
'v' => :systemverilog,
123126
'xhtml' => :html,
124127
'xml' => :xml,
125128
'yaml' => :yaml,

lib/coderay/scanners/_map.rb

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,22 @@ module CodeRay
22
module Scanners
33

44
map \
5-
:'c++' => :cpp,
6-
:cplusplus => :cpp,
7-
:ecmascript => :java_script,
8-
:ecma_script => :java_script,
9-
:rhtml => :erb,
10-
:eruby => :erb,
11-
:irb => :ruby,
12-
:javascript => :java_script,
13-
:js => :java_script,
14-
:pascal => :delphi,
15-
:patch => :diff,
16-
:plain => :text,
17-
:plaintext => :text,
18-
:xhtml => :html,
19-
:yml => :yaml
5+
:'c++' => :cpp,
6+
:cplusplus => :cpp,
7+
:ecmascript => :java_script,
8+
:ecma_script => :java_script,
9+
:rhtml => :erb,
10+
:eruby => :erb,
11+
:irb => :ruby,
12+
:javascript => :java_script,
13+
:js => :java_script,
14+
:pascal => :delphi,
15+
:patch => :diff,
16+
:plain => :text,
17+
:plaintext => :text,
18+
:verilog => :systemverilog,
19+
:xhtml => :html,
20+
:yml => :yaml
2021

2122
default :text
2223

lib/coderay/scanners/systemverilog.rb

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
module CodeRay
2+
module Scanners
3+
4+
# TODO: Review. Most of this code is copied from the C++ scanner and not
5+
# for applicability for SystemVerilog.
6+
7+
# Scanner for SystemVerilog
8+
#
9+
# Aliases: +verilog+
10+
class SystemVerilog < Scanner
11+
12+
register_for :systemverilog
13+
file_extension 'sv'
14+
title 'SystemVerilog'
15+
16+
17+
KEYWORDS = [
18+
'accept_on', 'alias', 'always', 'always_comb', 'always_ff', 'always_latch', 'and', 'assert', 'assign', 'assume', 'before', 'begin', 'bind', 'bins', 'binsof', 'break', 'buf', 'bufif0', 'bufif1', 'byte', 'case', 'casex', 'casez', 'cell', 'chandle', 'checker', 'class', 'clocking', 'cmos', 'config', 'const', 'constraint', 'context', 'continue', 'cover', 'covergroup', 'coverpoint', 'cross', 'deassign', 'default', 'defparam', 'design', 'disable', 'dist', 'do', 'edge', 'else', 'end', 'endcase', 'endchecker', 'endclass', 'endclocking', 'endconfig', 'endfunction', 'endgenerate', 'endgroup', 'endinterface', 'endmodule', 'endpackage', 'endprimitive', 'endprogram', 'endproperty', 'endsequence', 'endspecify', 'endtable', 'endtask', 'enum', 'event', 'eventually', 'expect', 'export', 'extends', 'extern', 'final', 'first_match', 'for', 'force', 'foreach', 'forever', 'fork', 'forkjoin', 'function', 'generate', 'genvar', 'global', 'highz0', 'highz1', 'if', 'iff', 'ifnone', 'ignore_bins', 'illegal_bins', 'implies', 'import', 'incdir', 'include', 'initial', 'inout', 'input', 'inside', 'instance', 'interface', 'intersect', 'join', 'join_any', 'join_none', 'large', 'let', 'liblist', 'library', 'local', 'localparam', 'macromodule', 'matches', 'medium', 'modport', 'module', 'nand', 'negedge', 'new', 'nexttime', 'nmos', 'nor', 'noshowcancelled', 'not', 'notif0', 'notif1', 'or', 'output', 'package', 'packed', 'parameter', 'pmos', 'posedge', 'primitive', 'priority', 'program', 'property', 'protected', 'pull0', 'pull1', 'pulldown', 'pullup', 'pulsestyle_ondetect', 'pulsestyle_onevent', 'pure', 'rand', 'randc', 'randcase', 'randsequence', 'rcmos', 'real', 'realtime', 'ref', 'reg', 'reject_on', 'release', 'repeat', 'restrict', 'return', 'rnmos', 'rpmos', 'rtran', 'rtranif0', 'rtranif1', 's_always', 's_eventually', 's_nexttime', 's_until', 's_until_with', 'scalared', 'sequence', 'shortint', 'shortreal', 'showcancelled', 'signed', 'small', 'solve', 'specify', 'specparam', 'static', 'strong', 'strong0', 'strong1', 'struct', 'super', 'supply0', 'supply1', 'sync_accept_on', 'sync_reject_on', 'table', 'tagged', 'task', 'throughout', 'time', 'timeprecision', 'timeunit', 'tran', 'tranif0', 'tranif1', 'tri', 'tri0', 'tri1', 'triand', 'trior', 'trireg', 'type', 'typedef', 'union', 'unique', 'unique0', 'unsigned', 'until', 'until_with', 'untyped', 'use', 'uwire', 'var', 'vectored', 'wait', 'wait_order', 'wand', 'weak', 'weak0', 'weak1', 'while', 'wildcard', 'with', 'within', 'wor', 'xnor', 'xor'
19+
] # :nodoc:
20+
21+
PREDEFINED_TYPES = [
22+
'bit', 'int', 'integer', 'logic', 'longint', 'string', 'wire'
23+
] # :nodoc:
24+
PREDEFINED_CONSTANTS = [
25+
'null'
26+
] # :nodoc:
27+
PREDEFINED_VARIABLES = [
28+
'this',
29+
] # :nodoc:
30+
DIRECTIVES = [
31+
'automatic', 'virtual', 'void'
32+
] # :nodoc:
33+
34+
IDENT_KIND = WordList.new(:ident).
35+
add(KEYWORDS, :keyword).
36+
add(PREDEFINED_TYPES, :predefined_type).
37+
add(PREDEFINED_VARIABLES, :local_variable).
38+
add(DIRECTIVES, :directive).
39+
add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
40+
41+
ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
42+
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
43+
44+
protected
45+
46+
def scan_tokens encoder, options
47+
48+
state = :initial
49+
label_expected = true
50+
case_expected = false
51+
label_expected_before_preproc_line = nil
52+
in_preproc_line = false
53+
54+
until eos?
55+
56+
case state
57+
58+
when :initial
59+
60+
if match = scan(/ \s+ | \\\n /x)
61+
if in_preproc_line && match != "\\\n" && match.index(?\n)
62+
in_preproc_line = false
63+
label_expected = label_expected_before_preproc_line
64+
end
65+
encoder.text_token match, :space
66+
67+
elsif match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
68+
encoder.text_token match, :comment
69+
70+
elsif match = scan(/ \# \s* if \s* 0 /x)
71+
match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
72+
encoder.text_token match, :comment
73+
74+
elsif match = scan(/ [-+*=<>?:;,!&^|()\[\]{}~%]+ | \/=? | \.(?!\d) /x)
75+
label_expected = match =~ /[;\{\}]/
76+
if case_expected
77+
label_expected = true if match == ':'
78+
case_expected = false
79+
end
80+
encoder.text_token match, :operator
81+
82+
elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
83+
kind = IDENT_KIND[match]
84+
if kind == :ident && label_expected && !in_preproc_line && scan(/:(?!:)/)
85+
kind = :label
86+
match << matched
87+
else
88+
label_expected = false
89+
if kind == :keyword
90+
case match
91+
when 'class'
92+
state = :class_name_expected
93+
when 'case', 'default'
94+
case_expected = true
95+
end
96+
end
97+
end
98+
encoder.text_token match, kind
99+
100+
elsif match = scan(/\$/)
101+
encoder.text_token match, :ident
102+
103+
elsif match = scan(/L?"/)
104+
encoder.begin_group :string
105+
if match[0] == ?L
106+
encoder.text_token match, 'L', :modifier
107+
match = '"'
108+
end
109+
state = :string
110+
encoder.text_token match, :delimiter
111+
112+
elsif match = scan(/`[ \t]*(\w*)/)
113+
encoder.text_token match, :preprocessor
114+
in_preproc_line = true
115+
label_expected_before_preproc_line = label_expected
116+
state = :include_expected if self[1] == 'include'
117+
118+
elsif match = scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
119+
label_expected = false
120+
encoder.text_token match, :char
121+
122+
elsif match = scan(/0[xX][0-9A-Fa-f]+/)
123+
label_expected = false
124+
encoder.text_token match, :hex
125+
126+
elsif match = scan(/(?:0[0-7]+)(?![89.eEfF])/)
127+
label_expected = false
128+
encoder.text_token match, :octal
129+
130+
elsif match = scan(/(?:\d+)(?![.eEfF])L?L?/)
131+
label_expected = false
132+
encoder.text_token match, :integer
133+
134+
elsif match = scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
135+
label_expected = false
136+
encoder.text_token match, :float
137+
138+
else
139+
encoder.text_token getch, :error
140+
141+
end
142+
143+
when :string
144+
if match = scan(/[^\\"]+/)
145+
encoder.text_token match, :content
146+
elsif match = scan(/"/)
147+
encoder.text_token match, :delimiter
148+
encoder.end_group :string
149+
state = :initial
150+
label_expected = false
151+
elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
152+
encoder.text_token match, :char
153+
elsif match = scan(/ \\ | $ /x)
154+
encoder.end_group :string
155+
encoder.text_token match, :error
156+
state = :initial
157+
label_expected = false
158+
else
159+
raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
160+
end
161+
162+
when :include_expected
163+
if match = scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
164+
encoder.text_token match, :include
165+
state = :initial
166+
167+
elsif match = scan(/\s+/)
168+
encoder.text_token match, :space
169+
state = :initial if match.index ?\n
170+
171+
else
172+
state = :initial
173+
174+
end
175+
176+
when :class_name_expected
177+
if match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
178+
encoder.text_token match, :class
179+
state = :initial
180+
181+
elsif match = scan(/\s+/)
182+
encoder.text_token match, :space
183+
184+
else
185+
encoder.text_token getch, :error
186+
state = :initial
187+
188+
end
189+
190+
else
191+
raise_inspect 'Unknown state', encoder
192+
193+
end
194+
195+
end
196+
197+
if state == :string
198+
encoder.end_group :string
199+
end
200+
201+
encoder
202+
end
203+
204+
end
205+
206+
end
207+
end

0 commit comments

Comments
 (0)