From 93e2bae74fe6a99c79add1ed4dc6482c8eef0855 Mon Sep 17 00:00:00 2001 From: Ryan Goodfellow Date: Thu, 4 Jul 2024 05:55:49 -0700 Subject: [PATCH 1/7] Add lexer for P4 (#2049) * Add lexer for P4 * ruby 2.7 compat * add P4 to Languages.md --- docs/Languages.md | 1 + lib/rouge/demos/p4 | 99 ++++++++++++ lib/rouge/lexers/p4.rb | 81 ++++++++++ spec/lexers/p4_spec.rb | 18 +++ spec/visual/samples/p4 | 354 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 553 insertions(+) create mode 100644 lib/rouge/demos/p4 create mode 100644 lib/rouge/lexers/p4.rb create mode 100644 spec/lexers/p4_spec.rb create mode 100644 spec/visual/samples/p4 diff --git a/docs/Languages.md b/docs/Languages.md index d5a02920a9..dd7c78dea8 100644 --- a/docs/Languages.md +++ b/docs/Languages.md @@ -144,6 +144,7 @@ - OCL (`ocl`) - OpenEdge ABL (`openedge`) - OpenType Feature File (`opentype_feature_file`) +- P4 (`p4`) - Pascal (`pascal`) - Perl (`perl`) - PHP (`php`) diff --git a/lib/rouge/demos/p4 b/lib/rouge/demos/p4 new file mode 100644 index 0000000000..ed4992b075 --- /dev/null +++ b/lib/rouge/demos/p4 @@ -0,0 +1,99 @@ +#include +#include + +const bit<16> TYPE_IPV4 = 0x800; +typedef bit<9> egressSpec_t; +typedef bit<48> macAddr_t; +typedef bit<32> ip4Addr_t; + +header ethernet_t { + macAddr_t dstAddr; + macAddr_t srcAddr; + bit<16> etherType; +} + +header ipv4_t { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + ip4Addr_t srcAddr; + ip4Addr_t dstAddr; +} + +struct metadata { /* empty */ } + +struct headers { + ethernet_t ethernet; + ipv4_t ipv4; +} + +parser MyParser(packet_in packet, + out headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + + state start { transition parse_ethernet; } + + state parse_ethernet { + packet.extract(hdr.ethernet); + transition select(hdr.ethernet.etherType) { + TYPE_IPV4: parse_ipv4; + default: accept; + } + } + + state parse_ipv4 { + packet.extract(hdr.ipv4); + transition accept; + } + +} + +control MyIngress(inout headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + action drop() { + mark_to_drop(standard_metadata); + } + + action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { + standard_metadata.egress_spec = port; + hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; + hdr.ethernet.dstAddr = dstAddr; + hdr.ipv4.ttl = hdr.ipv4.ttl - 1; + } + + table ipv4_lpm { + key = { hdr.ipv4.dstAddr: lpm; } + actions = { ipv4_forward; drop; NoAction; } + size = 1024; + default_action = drop(); + } + + apply { + if (hdr.ipv4.isValid()) { + ipv4_lpm.apply(); + } + } +} + + +control MyDeparser(packet_out packet, in headers hdr) { + apply { + packet.emit(hdr.ethernet); + packet.emit(hdr.ipv4); + } +} + +V1Switch( +MyParser(), +MyIngress(), +MyDeparser() +) main; diff --git a/lib/rouge/lexers/p4.rb b/lib/rouge/lexers/p4.rb new file mode 100644 index 0000000000..87e656f13f --- /dev/null +++ b/lib/rouge/lexers/p4.rb @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class P4 < RegexLexer + tag 'p4' + title 'P4' + desc 'The P4 programming language' + filenames '*.p4' + mimetypes 'text/x-p4' + + def self.keywords + @keywords ||= %w( + abstract action actions apply const default default_action else enum + entries extern exit if in inout key list out package packet_in + packet_out return size select switch this transition tuple type + typedef + ) + end + + def self.operators + @operators ||= %w( + \|\+\| \|-\| \? \& \&\&\& < > << >> \* \| ~ \^ - \+ / + \# \. = != <= >= \+\+ + ) + end + + def self.decls + @decls ||= %w( + control header header_union parser state struct table + value_set + ) + end + + def self.builtins + @builtins ||= %w( + bit bool error extract int isValid setValid setInvalid match_kind + string varbit verify void + ) + end + + state :whitespace do + rule %r/\s+/m, Text + end + + state :comment do + rule %r((//).*$\n?), Comment::Single + rule %r/\/\*(?:(?!\*\/).)*\*\//m, Comment::Multiline + end + + state :number do + rule %r/([0-9]+[sw])?0[oO][0-7_]+/, Num + rule %r/([0-9]+[sw])?0[xX][0-9a-fA-F_]+/, Num + rule %r/([0-9]+[sw])?0[bB][01_]+/, Num + rule %r/([0-9]+[sw])?0[dD][0-9_]+/, Num + rule %r/([0-9]+[sw])?[0-9_]+/, Num + end + + id = /[\p{XID_Start}_]\p{XID_Continue}*/ + string_element = /\\"|[^"]/x + + state :root do + mixin :whitespace + mixin :comment + + rule %r/#\s*#{id}/, Comment::Preproc + rule %r/\b(?:#{P4.keywords.join('|')})\b/, Keyword + rule %r/\b(?:#{P4.decls.join('|')})\b/, Keyword::Declaration + rule %r/\b(?:#{P4.builtins.join('|')})\b/, Name::Builtin + rule %r/\b#{id}_[th]\b/x, Name::Class + rule %r/(?:#{P4.operators.join('|')})/x, Operator + rule %r/[(){}\[\]<>,:;\.]/, Punctuation + mixin :number + rule %r/@#{id}/x, Name::Label + rule %r/#{id}/x, Text + rule %r/"(?: #{string_element} )*"/x, Str::String + end + end + end +end diff --git a/spec/lexers/p4_spec.rb b/spec/lexers/p4_spec.rb new file mode 100644 index 0000000000..d04479ebe2 --- /dev/null +++ b/spec/lexers/p4_spec.rb @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::P4 do + let(:subject) { Rouge::Lexers::P4.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.p4' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'text/x-p4' + end + end +end diff --git a/spec/visual/samples/p4 b/spec/visual/samples/p4 new file mode 100644 index 0000000000..bf280e9a82 --- /dev/null +++ b/spec/visual/samples/p4 @@ -0,0 +1,354 @@ +// A line comment. + +/* +A multiline comment. +*/ + +// String literals + +"simple string" +"string \" with \" embedded \" quotes" +"string with embedded +line terminator" + +// Integer literals + +32w255 +32w0d255 +32w0xFF +32s0xFF +8w0b10101010 +8w0b_1010_1010 +8w170 +8s0b1010_1010 +16w0377 +16w0o377 + +// Structs and headers + +header h1_t { + bit<8> f1; + bit<8> f2; +} +struct s1_t { + h1_t h1a; + bit<3> a; + bit<7> b; +} +struct s2_t { + h1_t h1b; + s1_t s1; + bit<5> c; +} + +// Externs +extern void f(inout bit x, in bit y); +extern bit g(inout bit z); + +// File "very_simple_switch_model.p4" +// Very Simple Switch P4 declaration +// core library needed for packet_in and packet_out definitions +# include +/* Various constants and structure declarations */ +/* ports are represented using 4-bit values */ +typedef bit<4> PortId; +/* only 8 ports are "real" */ +const PortId REAL_PORT_COUNT = 4w8; // 4w8 is the number 8 in 4 bits +/* metadata accompanying an input packet */ +struct InControl { + PortId inputPort; +} +/* special input port values */ +const PortId RECIRCULATE_IN_PORT = 0xD; +const PortId CPU_IN_PORT = 0xE; +/* metadata that must be computed for outgoing packets */ +struct OutControl { + PortId outputPort; +} +/* special output port values for outgoing packet */ +const PortId DROP_PORT = 0xF; +const PortId CPU_OUT_PORT = 0xE; +const PortId RECIRCULATE_OUT_PORT = 0xD; +/* Prototypes for all programmable blocks */ +/** + * Programmable parser. + * @param type of headers; defined by user + * @param b input packet + * @param parsedHeaders headers constructed by parser + */ +parser Parser(packet_in b, + out H parsedHeaders); +/** + * Match-action pipeline + * @param type of input and output headers + * @param headers headers received from the parser and sent to the deparser + * @param parseError error that may have surfaced during parsing + * @param inCtrl information from architecture, accompanying input packet + * @param outCtrl information for architecture, accompanying output packet + */ +control Pipe(inout H headers, + in error parseError,// parser error + in InControl inCtrl,// input port + out OutControl outCtrl); // output port +/** + * VSS deparser. + * @param type of headers; defined by user + * @param b output packet + * @param outputHeaders headers for output packet + */ +control Deparser(inout H outputHeaders, + packet_out b); +/** + * Top-level package declaration - must be instantiated by user. + * The arguments to the package indicate blocks that + * must be instantiated by the user. + * @param user-defined type of the headers processed. + */ +package VSS(Parser p, + Pipe map, + Deparser d); +// Architecture-specific objects that can be instantiated +// Checksum unit +extern Checksum16 { + Checksum16(); // constructor + void clear(); // prepare unit for computation + void update(in T data); // add data to checksum + void remove(in T data); // remove data from existing checksum + bit<16> get(); // get the checksum for the data added since last clear +} + +// Include P4 core library +# include + +// Include very simple switch architecture declarations +# include "very_simple_switch_model.p4" + +// This program processes packets comprising an Ethernet and an IPv4 +// header, and it forwards packets using the destination IP address + +typedef bit<48> EthernetAddress; +typedef bit<32> IPv4Address; + +// Standard Ethernet header +header Ethernet_h { + EthernetAddress dstAddr; + EthernetAddress srcAddr; + bit<16> etherType; +} + +// IPv4 header (without options) +header IPv4_h { + bit<4> version; + bit<4> ihl; + bit<8> diffserv; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + IPv4Address srcAddr; + IPv4Address dstAddr; +} + +// Structure of parsed headers +struct Parsed_packet { + Ethernet_h ethernet; + IPv4_h ip; +} + +// Parser section + +// User-defined errors that may be signaled during parsing +error { + IPv4OptionsNotSupported, + IPv4IncorrectVersion, + IPv4ChecksumError +} + +parser TopParser(packet_in b, out Parsed_packet p) { + Checksum16() ck; // instantiate checksum unit + + state start { + b.extract(p.ethernet); + transition select(p.ethernet.etherType) { + 0x0800: parse_ipv4; + // no default rule: all other packets rejected + } + } + + state parse_ipv4 { + b.extract(p.ip); + verify(p.ip.version == 4w4, error.IPv4IncorrectVersion); + verify(p.ip.ihl == 4w5, error.IPv4OptionsNotSupported); + ck.clear(); + ck.update(p.ip); + // Verify that packet checksum is zero + verify(ck.get() == 16w0, error.IPv4ChecksumError); + transition accept; + } +} + +// Match-action pipeline section + +control TopPipe(inout Parsed_packet headers, + in error parseError, // parser error + in InControl inCtrl, // input port + out OutControl outCtrl) { + IPv4Address nextHop; // local variable + + /** + * Indicates that a packet is dropped by setting the + * output port to the DROP_PORT + */ + action Drop_action() { + outCtrl.outputPort = DROP_PORT; + } + + /** + * Set the next hop and the output port. + * Decrements ipv4 ttl field. + * @param ipv4_dest ipv4 address of next hop + * @param port output port + */ + action Set_nhop(IPv4Address ipv4_dest, PortId port) { + nextHop = ipv4_dest; + headers.ip.ttl = headers.ip.ttl - 1; + outCtrl.outputPort = port; + } + + /** + * Computes address of next IPv4 hop and output port + * based on the IPv4 destination of the current packet. + * Decrements packet IPv4 TTL. + * @param nextHop IPv4 address of next hop + */ + table ipv4_match { + key = { headers.ip.dstAddr: lpm; } // longest-prefix match + actions = { + Drop_action; + Set_nhop; + } + size = 1024; + default_action = Drop_action; + } + + /** + * Send the packet to the CPU port + */ + action Send_to_cpu() { + outCtrl.outputPort = CPU_OUT_PORT; + } + + /** + * Check packet TTL and send to CPU if expired. + */ + table check_ttl { + key = { headers.ip.ttl: exact; } + actions = { Send_to_cpu; NoAction; } + const default_action = NoAction; // defined in core.p4 + } + + /** + * Set the destination MAC address of the packet + * @param dmac destination MAC address. + */ + action Set_dmac(EthernetAddress dmac) { + headers.ethernet.dstAddr = dmac; + } + + /** + * Set the destination Ethernet address of the packet + * based on the next hop IP address. + * @param nextHop IPv4 address of next hop. + */ + table dmac { + key = { nextHop: exact; } + actions = { + Drop_action; + Set_dmac; + } + size = 1024; + default_action = Drop_action; + } + + /** + * Set the source MAC address. + * @param smac: source MAC address to use + */ + action Set_smac(EthernetAddress smac) { + headers.ethernet.srcAddr = smac; + } + + /** + * Set the source mac address based on the output port. + */ + table smac { + key = { outCtrl.outputPort: exact; } + actions = { + Drop_action; + Set_smac; + } + size = 16; + default_action = Drop_action; + } + + apply { + if (parseError != error.NoError) { + Drop_action(); // invoke drop directly + return; + } + + ipv4_match.apply(); // Match result will go into nextHop + if (outCtrl.outputPort == DROP_PORT) return; + + check_ttl.apply(); + if (outCtrl.outputPort == CPU_OUT_PORT) return; + + dmac.apply(); + if (outCtrl.outputPort == DROP_PORT) return; + + smac.apply(); + } +} + +// deparser section +control TopDeparser(inout Parsed_packet p, packet_out b) { + Checksum16() ck; + apply { + b.emit(p.ethernet); + if (p.ip.isValid()) { + ck.clear(); // prepare checksum unit + p.ip.hdrChecksum = 16w0; // clear checksum + ck.update(p.ip); // compute new checksum. + p.ip.hdrChecksum = ck.get(); + } + b.emit(p.ip); + } +} + +// Instantiate the top-level VSS package +VSS(TopParser(), + TopPipe(), + TopDeparser()) main; + +extern void h(in bit<32> a, in bool b = true); // default value + +// function calls +h(10); // same as h(10, true); +h(a = 10); // same as h(10, true); +h(a = 10, b = true); + +struct Empty {} +control nothing(inout Empty h, inout Empty m) { + apply {} +} + +parser parserProto(packet_in p, out H h, inout M m); +control controlProto(inout H h, inout M m); + +package pack(@optional parserProto _parser, // optional parameter + controlProto _control = nothing()); // default parameter value + +pack() main; // No value for _parser, _control is an instance of nothing() From 04887af849e75ac829c3201c54ea3ccdb2fcdba8 Mon Sep 17 00:00:00 2001 From: Andrew Hills <92505+ahills@users.noreply.github.com> Date: Mon, 15 Jul 2024 08:37:34 -0400 Subject: [PATCH 2/7] Detect Containerfiles as Dockerfiles (#2059) Co-authored-by: Andrew Hills --- lib/rouge/lexers/docker.rb | 4 ++-- spec/lexers/docker_spec.rb | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/rouge/lexers/docker.rb b/lib/rouge/lexers/docker.rb index 2b4467bc4f..ba581a75fe 100644 --- a/lib/rouge/lexers/docker.rb +++ b/lib/rouge/lexers/docker.rb @@ -7,8 +7,8 @@ class Docker < RegexLexer title "Docker" desc "Dockerfile syntax" tag 'docker' - aliases 'dockerfile', 'Dockerfile' - filenames 'Dockerfile', '*.Dockerfile', '*.docker' + aliases 'dockerfile', 'Dockerfile', 'containerfile', 'Containerfile' + filenames 'Dockerfile', '*.Dockerfile', '*.docker', 'Containerfile', '*.Containerfile' mimetypes 'text/x-dockerfile-config' KEYWORDS = %w( diff --git a/spec/lexers/docker_spec.rb b/spec/lexers/docker_spec.rb index 64e48c4dff..2a086d9f4d 100644 --- a/spec/lexers/docker_spec.rb +++ b/spec/lexers/docker_spec.rb @@ -11,6 +11,8 @@ assert_guess :filename => 'Dockerfile' assert_guess :filename => 'docker.docker' assert_guess :filename => 'some.Dockerfile' + assert_guess :filename => 'Containerfile' + assert_guess :filename => 'some.Containerfile' end it 'guesses by mimetype' do From c5e4a8a546463a82e76b287d1f3b243906f81dcf Mon Sep 17 00:00:00 2001 From: ivellapillil Date: Tue, 27 Aug 2024 00:41:32 +0200 Subject: [PATCH 3/7] Mojo language highlighting support. (#2050) * Mojo language highlighting support. * Added new line to fix the Linelint error --- lib/rouge/demos/mojo | 10 ++ lib/rouge/lexers/mojo.rb | 33 ++++++ spec/lexers/mojo_spec.rb | 25 +++++ spec/visual/samples/mojo | 229 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+) create mode 100644 lib/rouge/demos/mojo create mode 100644 lib/rouge/lexers/mojo.rb create mode 100644 spec/lexers/mojo_spec.rb create mode 100644 spec/visual/samples/mojo diff --git a/lib/rouge/demos/mojo b/lib/rouge/demos/mojo new file mode 100644 index 0000000000..dacbefa104 --- /dev/null +++ b/lib/rouge/demos/mojo @@ -0,0 +1,10 @@ +fn fib(n: Int): # write Fibonacci series up to n + """Print a Fibonacci series up to n.""" + var a = 0 + var b = 1 + while a < n: + print(a) + a, b = b, a+b + +fn main(): + fib(10) diff --git a/lib/rouge/lexers/mojo.rb b/lib/rouge/lexers/mojo.rb new file mode 100644 index 0000000000..d28af4efbb --- /dev/null +++ b/lib/rouge/lexers/mojo.rb @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class Mojo < Python + title "Mojo" + desc "The Mojo programming language (modular.com)" + tag 'mojo' + aliases 'mojo' + filenames '*.mojo', '*.🔥' + mimetypes 'text/x-mojo', 'application/x-mojo' + + def self.detect?(text) + return true if text.shebang?(/mojow?(?:[23](?:\.\d+)?)?/) + end + + def self.keywords + @keywords ||= super + %w( + fn self alias inout borrowed owned ref var + struct trait raises with in match case + ) + end + + def self.builtins + @builtins ||= super + %w( + __mlir_attr __mlir_type __mlir_op parameter alwaysinline + register_passable + ) + end + end + end +end diff --git a/spec/lexers/mojo_spec.rb b/spec/lexers/mojo_spec.rb new file mode 100644 index 0000000000..0f13b5dd9a --- /dev/null +++ b/spec/lexers/mojo_spec.rb @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::Mojo do + let(:subject) { Rouge::Lexers::Mojo.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.mojo' + assert_guess :filename => 'foo.🔥' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'text/x-mojo' + assert_guess :mimetype => 'application/x-mojo' + end + + it 'guesses by source' do + assert_guess :source => '#!/usr/bin/env mojo' + assert_guess :source => '#!/usr/bin/mojo' + end + end +end diff --git a/spec/visual/samples/mojo b/spec/visual/samples/mojo new file mode 100644 index 0000000000..1642018ada --- /dev/null +++ b/spec/visual/samples/mojo @@ -0,0 +1,229 @@ +fn lex(code: String, lexer: Lexer) raises: + """ + Lex ``code`` with ``lexer`` and return an iterable of tokens. + """ + try: + return lexer.get_tokens(code) + except e: + raise + +alias lst = List[Int] + +# quotes in strings +def foo(): + "it's working" + +def foo(): + 'he said "hi"' + +def foo(): + """it's working""" + """he said "hi" """ + +def foo(): + '''he said "hi"''' + '''it's working''' + +# unicode docstrings +def foo(): + ur"""unicode-raw""" + +def bar(): + u"""unicode""" + +def baz(): + r'raw' + +def zap(): + """docstring""" + +# escaped characters in string literals +fn baz(): + '\a\b\f\n\r\t\v\"\'' + '\N{DEGREE SIGN}' + '\uaF09' + '\UaaaaAF09' + '\xaf\xAF\x09' + '\007' + '.*\[p00t_(d\d{4})\].*' # There are no escape sequences in this string + +# escaped characters in raw strings +def baz(): + r'\a\b\f\n\r\t\v\"\'' + r'\N{DEGREE SIGN}' + r'\uaF09' + r'\UaaaaAF09' + r'\xaf\xAF\x09' + r'\007' + r'.*\[p00t_(d\d{4})\].*' + +# line continuations +apple.filter(x, y) +apple.\ + filter(x, y) + +1 \ + . \ + __str__ + +from os import path +from \ + os \ + import \ + path + +import os.path as something + +import \ + os.path \ + as \ + something + +class \ + Spam: + pass + +class Spam: pass + +trait Spam: pass + +@register_passable +struct Spam: + var x: Int + fn __init__(inout self): + self.x = 0 + @parameter + for i in (range(10)): + pass + +class Spam(object): + pass + +class \ + Spam \ + ( + object + ) \ + : + pass + + +def \ + spam \ + ( \ + ) \ + : \ + pass + +def the_word_strand(): + a = b.strip() + a = strand + b = band + c = strand + b = error + c = stror + c = string + +py2_long = -123L + +# Python 3 + +def test(): + raise Exception from foo + +def exceptions(): + try: + print("Hello") + except Exception as e: + print("Exception") + +# PEP 515 +integer_literals = [ + 123, -1_2_0, 0, 00, 0_0_00, 0b1, 0B1_0, 0b_1, 0b00_0, + 0o1, 0O1_2, 0O_1, 0o00_0, 0x1, 0X1_2, 0x_1, 0x00_0 +] +float_literals = [ + 0., 1., 00., 0_00., 1_0_0., 0_1., .0, + .1_2, 3.4_5, 1_2.3_4, 00_0.0_0_0, 0_0.1_2, + 0_1_2j, 0_00J, 1.2J, 0.1j, 1_0.J, + 0_00E+2_34_5, 0.e+1, 00_1.E-0_2, -100.e+20, 1e01, + 0_00E+2_34_5j, 0.e+1J, 00_1.E-0_2j, -100.e+20J 1e01j +] +floats = (19.0, 19.) + +# PEP 465 +a = b @ c +x @= y + +# PEP 498 +f'{hello} world {int(x) + 1}' +f'{{ {4*10} }}' +f'result: {value:{width}.{precision}}' +f'{value!r}' + +# Unicode identifiers +α = 10 +def coöperative(б): + return f"{б} is Russian" + +def __init__(self, input_dim: list, output_dim: int, **kwargs): + super(AverageEmbedding, self).__init__(**kwargs) + self.input_dim = input_dim + self.output_dim = output_dim + +@abstractmethod +def evaluate(self, *args, **kwargs): + raise NotImplementedError + +def _get_metadata(self, input_samples: list[InputSample]) -> Tuple[str, str, int]: + project_name, id = self._get_info() + +class Spam: + pass + +spam = Spam() + +# Doctest +def factorial(n): + """Return the factorial of n, an exact integer >= 0. + + >>> [factorial(n) for n in range(6)] + [1, 1, 2, 6, 24, 120] + + >>> for i in [factorial(n) for n in range(2)]: + ... print(i) + 1 + 1 + >>> factorial(30) + 265252859812191058636308480000000 + >>> factorial(-1) + Traceback (most recent call last): + ... + ValueError: n must be >= 0 + + Factorials of floats are OK, but the float must be an exact integer: + >>> factorial(30.1) + Traceback (most recent call last): + ... + ValueError: n must be exact integer + >>> factorial(30.0) + 265252859812191058636308480000000 + + It must also not be ridiculously large: + >>> factorial(1e100) + Traceback (most recent call last): + ... + OverflowError: n too large + """ + print("hello world") + +def do_nothing(): + if False: + return + print("a...a") + + with tracer.start_as_current_span('App Init'): + logger.info('OTEL Initialized...') + + app = FastAPI() + FastAPIInstrumentor.instrument_app(app) From 90b5c836ed5f45e84dea5ae42b4d4ad473e37397 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Thu, 29 Aug 2024 23:40:59 +1000 Subject: [PATCH 4/7] Handle `else if` statement in makefile (#2063) --- lib/rouge/lexers/make.rb | 4 ++++ spec/visual/samples/make | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/rouge/lexers/make.rb b/lib/rouge/lexers/make.rb index 7320632ecf..3b7338325c 100644 --- a/lib/rouge/lexers/make.rb +++ b/lib/rouge/lexers/make.rb @@ -40,6 +40,10 @@ def initialize(opts={}) groups Keyword, Text, Name::Variable end + rule %r/(else\b)([\t ]+)((?:ifn?def|ifn?eq)\b)([\t ]+)([^#\n]+)/ do + groups Keyword, Text, Keyword, Text, Name::Variable + end + rule %r/(?:else|endif|endef|endfor)[\t ]*(?=[#\n])/, Keyword rule %r/(export)([\t ]+)(?=[\w\${}()\t -]+\n)/ do diff --git a/spec/visual/samples/make b/spec/visual/samples/make index c6a0aef84f..4581a31ba2 100644 --- a/spec/visual/samples/make +++ b/spec/visual/samples/make @@ -92,6 +92,14 @@ else THING2 = default endif +ifeq ($(OS), Linux) +MES = "Hi, Linux" +else ifeq ($(OS), Darwin) +MES = "Hi, Mac" +else +MES = "Unknown" +endif + ifeq ($(TARGET),special) # syntax variant: parentheses and separating comma TARGET = something_else else From 7ebb8d15b2fa353d94ffa5bdd80b88b2f593e52f Mon Sep 17 00:00:00 2001 From: Bart Broere Date: Wed, 11 Sep 2024 07:44:52 +0200 Subject: [PATCH 5/7] Fix NameError in the Mojo lexer in Ruby 2.7 (#2068) * Fix CI for 2.7 * Use load_lexer instead --- lib/rouge/lexers/mojo.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rouge/lexers/mojo.rb b/lib/rouge/lexers/mojo.rb index d28af4efbb..be30512a26 100644 --- a/lib/rouge/lexers/mojo.rb +++ b/lib/rouge/lexers/mojo.rb @@ -3,6 +3,8 @@ module Rouge module Lexers + load_lexer 'python.rb' + class Mojo < Python title "Mojo" desc "The Mojo programming language (modular.com)" From 677f2c139f88ccd49683a3b81f398228a5897b7b Mon Sep 17 00:00:00 2001 From: Tan Le Date: Mon, 16 Sep 2024 22:33:02 +1000 Subject: [PATCH 6/7] Add Mojo to list of supported language (#2072) --- docs/Languages.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Languages.md b/docs/Languages.md index dd7c78dea8..18864ebe0a 100644 --- a/docs/Languages.md +++ b/docs/Languages.md @@ -128,6 +128,7 @@ - MATLAB (`matlab`) - Meson (`meson`) - MiniZinc (`minizinc`) +- Mojo (`mojo`) - MoonScript (`moonscript`) - Mosel (`mosel`) - MessageTrans (`msgtrans`) From 173ec7724d215bc1757affaa7fb37d1e56d70ab0 Mon Sep 17 00:00:00 2001 From: Tan Le Date: Tue, 17 Sep 2024 07:55:50 +1000 Subject: [PATCH 7/7] Release v4.4.0 (#2071) --- CHANGELOG.md | 17 ++++++++++++++++- lib/rouge/version.rb | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d14e0ea312..68d3e0a9db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,26 @@ This log summarizes the changes in each released version of Rouge. Rouge follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). +## version 4.4.0: 2024-09-16 + +[Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v4.3.0...v4.4.0) + +- Docker Lexer + - Detect Containerfiles as Dockerfiles ([#2059](https://github.com/rouge-ruby/rouge/pull/2059/) by Andrew Hills) +- Make Lexer + - Handle `else if` statement in makefile ([#2063](https://github.com/rouge-ruby/rouge/pull/2063/) by Tan Le) +- Mojo Lexer (**NEW**) + - Add Mojo to list of supported language ([#2072](https://github.com/rouge-ruby/rouge/pull/2072/) by Tan Le) + - Fix NameError in the Mojo lexer in Ruby 2.7 ([#2068](https://github.com/rouge-ruby/rouge/pull/2068/) by Bart Broere) + - Mojo language highlighting support. ([#2050](https://github.com/rouge-ruby/rouge/pull/2050/) by ivellapillil) +- P4 Lexer (**NEW**) + - Add lexer for P4 ([#2049](https://github.com/rouge-ruby/rouge/pull/2049/) by Ryan Goodfellow) + ## version 4.3.0: 2024-06-14 [Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v4.2.1...v4.3.0) -_ General +- General - Align the base-16 default dark colour palette ([#2040](https://github.com/rouge-ruby/rouge/pull/2040/) by Tan Le) - Brainfuck Lexer - Add "bf" as an alias for brainfuck ([#2038](https://github.com/rouge-ruby/rouge/pull/2038/) by Boris Verkhovskiy) diff --git a/lib/rouge/version.rb b/lib/rouge/version.rb index 1e112cfc13..39c3edd239 100644 --- a/lib/rouge/version.rb +++ b/lib/rouge/version.rb @@ -3,6 +3,6 @@ module Rouge def self.version - "4.3.0" + "4.4.0" end end