Skip to content
This repository has been archived by the owner on Sep 8, 2023. It is now read-only.

Commit

Permalink
Add support for Fastly extensions to Varnish lexer (rouge-ruby#1454)
Browse files Browse the repository at this point in the history
This commit adds support for Fastly's extensions to the Varnish
configuration language (a.k.a. VCL). Fastly's VCL is proprietary,
closed-source software but because (1) the primary users are outside the
company, and (2) Rouge already includes some proprietary dialects in
other lexers, this was deemed to be acceptable.
  • Loading branch information
gfx authored and mattt committed May 21, 2020
1 parent 9d84c54 commit b582da9
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 71 deletions.
55 changes: 0 additions & 55 deletions lib/rouge/demos/varnish

This file was deleted.

12 changes: 12 additions & 0 deletions lib/rouge/demos/vcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
vcl 4.0;

backend server1 {
.host = "server1.example.com";
.probe = {
.url = "/";
.timeout = 1s;
.interval = 5s;
.window = 5;
.threshold = 3;
}
}
69 changes: 53 additions & 16 deletions lib/rouge/lexers/varnish.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@
module Rouge
module Lexers
class Varnish < RegexLexer
title 'Varnish'
desc 'The Varnish (high-performance web accelerator) configuration language'
title 'VCL: Varnish Configuration Language'
desc 'The configuration language for Varnish HTTP Cache (varnish-cache.org)'

tag 'varnish'
aliases 'varnishconf', 'VCL'
tag 'vcl'
aliases 'varnishconf', 'varnish'
filenames '*.vcl'
mimetypes 'text/x-varnish'
mimetypes 'text/x-varnish', 'text/x-vcl'

LNUM = '[0-9]+'
DNUM = '([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)'
SPACE = '[ \f\n\r\t\v]+'

# backend acl
def self.keywords
@keywords ||= Set.new %w[
vcl set unset include import if else elseif elif elsif director probe
backend acl

declare local
BOOL FLOAT INTEGER IP RTIME STRING TIME
]
end

Expand Down Expand Up @@ -65,14 +66,23 @@ def self.variables
# long strings ({" ... "})
rule %r/\{".*?"}/m, Str::Single

# heredoc style long strings ({xyz"..."xyz})
rule %r/\{(\w+)".*?"(\1)\}/m, Str::Single

# comments
rule %r'/\*.*?\*/'m, Comment::Multiline
rule %r'(?://|#).*', Comment::Single

rule %r/true|false/, Keyword::Constant

# "wildcard variables"
rule %r/(?:(?:be)?re(?:sp|q)|obj)\.http\.[\w.-]+/ do
var_prefix = Regexp.union(%w(beresp bereq resp req obj))
rule %r/(?:#{var_prefix})\.http\.[\w.-]+/ do
token Name::Variable
end

# local variables (var.*)
rule %r/(?:var)\.[\w.-]+/ do
token Name::Variable
end

Expand All @@ -86,20 +96,47 @@ def self.variables
push :inline_c
end

rule %r/[a-z_.-]+/i do |m|
rule %r/\.?[a-z_][\w.-]*/i do |m|
next token Keyword if self.class.keywords.include? m[0]
next token Name::Function if self.class.functions.include? m[0]
next token Name::Variable if self.class.variables.include? m[0]
token Text
end

# duration
rule %r/(?:#{LNUM}|#{DNUM})(?:ms|[smhdwy])/, Num::Other
# size in bytes
rule %r/#{LNUM}[KMGT]?B/, Num::Other
# literal numeric values (integer/float)
rule %r/#{LNUM}/, Num::Integer
rule %r/#{DNUM}/, Num::Float
## for number literals

decimal = %r/[0-9]+/
hex = %r/[0-9a-f]+/i

numeric = %r{
(?:
0x#{hex}
(?:\.#{hex})?
(?:p[+-]?#{hex})?
)
|
(?:
#{decimal}
(?:\.#{decimal})?
(?:e[+-]?#{decimal})?
)
}xi

# duration literals
duration_suffix = Regexp.union(%w(ms s m h d w y))
rule %r/#{numeric}#{duration_suffix}/, Num::Other

# numeric literals (integer / float)
rule numeric do |m|
case m[0]
when /^#{decimal}$/
token Num::Integer
when /^0x#{hex}$/
token Num::Integer
else
token Num::Float
end
end

# standard strings
rule %r/"/, Str::Double, :string
Expand Down
21 changes: 21 additions & 0 deletions spec/visual/samples/varnish → spec/visual/samples/vcl
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,24 @@ sub vcl_synth {

# Fall-through to default
}

#### Fastly's dialect ####

# reference: https://docs.fastly.com/vcl/

# local variables
declare local var.ip1 IP;
set var.ip1 = "192.0.2.0";

# string literals
set var.s = {xyz"Hello, world!"xyz}; # heredoc-style

# more literals
set resp.http.X-Str = {"Hello, world!"};
set resp.http.X-Rtime = 10ms;
set resp.http.X-RTime = 2.5h;
set resp.http.X-Int = 0xFF;
set resp.http.X-Float = 1.2e3;
set resp.http.X-Float = 1e2;
set resp.http.X-HexFloat = 0xA.Bp3;
set resp.http.X-HexFloat = 0xAp3;

0 comments on commit b582da9

Please sign in to comment.