192 lines
5.4 KiB
Ruby
192 lines
5.4 KiB
Ruby
# -*- coding: utf-8 -*- #
|
||
# frozen_string_literal: true
|
||
|
||
module Rouge
|
||
module Lexers
|
||
class Coq < RegexLexer
|
||
title "Coq"
|
||
desc 'Coq (coq.inria.fr)'
|
||
tag 'coq'
|
||
mimetypes 'text/x-coq'
|
||
|
||
def self.gallina
|
||
@gallina ||= Set.new %w(
|
||
as fun if in let match then else return end Type Set Prop
|
||
forall
|
||
)
|
||
end
|
||
|
||
def self.coq
|
||
@coq ||= Set.new %w(
|
||
Definition Theorem Lemma Remark Example Fixpoint CoFixpoint
|
||
Record Inductive CoInductive Corollary Goal Proof
|
||
Ltac Require Import Export Module Section End Variable
|
||
Context Polymorphic Monomorphic Universe Universes
|
||
Variables Class Instance Global Local Include
|
||
Printing Notation Infix Arguments Hint Rewrite Immediate
|
||
Qed Defined Opaque Transparent Existing
|
||
Compute Eval Print SearchAbout Search About Check
|
||
)
|
||
end
|
||
|
||
def self.ltac
|
||
@ltac ||= Set.new %w(
|
||
apply eapply auto eauto rewrite setoid_rewrite
|
||
with in as at destruct split inversion injection
|
||
intro intros unfold fold cbv cbn lazy subst
|
||
clear symmetry transitivity etransitivity erewrite
|
||
edestruct constructor econstructor eexists exists
|
||
f_equal refine instantiate revert simpl
|
||
specialize generalize dependent red induction
|
||
beta iota zeta delta exfalso autorewrite setoid_rewrite
|
||
compute vm_compute native_compute
|
||
)
|
||
end
|
||
|
||
def self.tacticals
|
||
@tacticals ||= Set.new %w(
|
||
repeat first try
|
||
)
|
||
end
|
||
|
||
def self.terminators
|
||
@terminators ||= Set.new %w(
|
||
omega solve congruence reflexivity exact
|
||
assumption eassumption
|
||
)
|
||
end
|
||
|
||
def self.keyopts
|
||
@keyopts ||= Set.new %w(
|
||
:= => -> /\\ \\/ _ ; :> : ⇒ → ↔ ⇔ ≔ ≡ ∀ ∃ ∧ ∨ ¬ ⊤ ⊥ ⊢ ⊨ ∈
|
||
)
|
||
end
|
||
|
||
def self.end_sentence
|
||
@end_sentence ||= Punctuation::Indicator
|
||
end
|
||
|
||
def self.classify(x)
|
||
if self.coq.include? x
|
||
return Keyword
|
||
elsif self.gallina.include? x
|
||
return Keyword::Reserved
|
||
elsif self.ltac.include? x
|
||
return Keyword::Pseudo
|
||
elsif self.terminators.include? x
|
||
return Name::Exception
|
||
elsif self.tacticals.include? x
|
||
return Keyword::Pseudo
|
||
else
|
||
return Name::Constant
|
||
end
|
||
end
|
||
|
||
operator = %r([\[\];,{}_()!$%&*+./:<=>?@^|~#-]+)
|
||
id = /(?:[a-z][\w']*)|(?:[_a-z][\w']+)/i
|
||
dot_id = /\.((?:[a-z][\w']*)|(?:[_a-z][\w']+))/i
|
||
dot_space = /\.(\s+)/
|
||
module_type = /Module(\s+)Type(\s+)/
|
||
set_options = /(Set|Unset)(\s+)(Universe|Printing|Implicit|Strict)(\s+)(Polymorphism|All|Notations|Arguments|Universes|Implicit)(\s*)\./m
|
||
|
||
state :root do
|
||
rule %r/[(][*](?![)])/, Comment, :comment
|
||
rule %r/\s+/m, Text::Whitespace
|
||
rule module_type do |m|
|
||
token Keyword , 'Module'
|
||
token Text::Whitespace , m[1]
|
||
token Keyword , 'Type'
|
||
token Text::Whitespace , m[2]
|
||
end
|
||
rule set_options do |m|
|
||
token Keyword , m[1]
|
||
i = 2
|
||
while m[i] != ''
|
||
token Text::Whitespace , m[i]
|
||
token Keyword , m[i+1]
|
||
i += 2
|
||
end
|
||
token self.class.end_sentence , '.'
|
||
end
|
||
rule id do |m|
|
||
@name = m[0]
|
||
@continue = false
|
||
push :continue_id
|
||
end
|
||
rule %r(/\\), Operator
|
||
rule %r/\\\//, Operator
|
||
|
||
rule %r/-?\d[\d_]*(.[\d_]*)?(e[+-]?\d[\d_]*)/i, Num::Float
|
||
rule %r/\d[\d_]*/, Num::Integer
|
||
|
||
rule %r/'(?:(\\[\\"'ntbr ])|(\\[0-9]{3})|(\\x\h{2}))'/, Str::Char
|
||
rule %r/'/, Keyword
|
||
rule %r/"/, Str::Double, :string
|
||
rule %r/[~?]#{id}/, Name::Variable
|
||
|
||
rule %r/./ do |m|
|
||
match = m[0]
|
||
if self.class.keyopts.include? match
|
||
token Punctuation
|
||
elsif match =~ operator
|
||
token Operator
|
||
else
|
||
token Error
|
||
end
|
||
end
|
||
end
|
||
|
||
state :comment do
|
||
rule %r/[^(*)]+/, Comment
|
||
rule(/[(][*]/) { token Comment; push }
|
||
rule %r/[*][)]/, Comment, :pop!
|
||
rule %r/[(*)]/, Comment
|
||
end
|
||
|
||
state :string do
|
||
rule %r/(?:\\")+|[^"]/, Str::Double
|
||
mixin :escape_sequence
|
||
rule %r/\\\n/, Str::Double
|
||
rule %r/"/, Str::Double, :pop!
|
||
end
|
||
|
||
state :escape_sequence do
|
||
rule %r/\\[\\"'ntbr]/, Str::Escape
|
||
end
|
||
|
||
state :continue_id do
|
||
# the stream starts with an id (stored in @name) and continues here
|
||
rule dot_id do |m|
|
||
token Name::Namespace , @name
|
||
token Punctuation , '.'
|
||
@continue = true
|
||
@name = m[1]
|
||
end
|
||
rule dot_space do |m|
|
||
if @continue
|
||
token Name::Constant , @name
|
||
else
|
||
token self.class.classify(@name) , @name
|
||
end
|
||
token self.class.end_sentence , '.'
|
||
token Text::Whitespace , m[1]
|
||
@name = false
|
||
@continue = false
|
||
pop!
|
||
end
|
||
rule %r// do
|
||
if @continue
|
||
token Name::Constant , @name
|
||
else
|
||
token self.class.classify(@name) , @name
|
||
end
|
||
@name = false
|
||
@continue = false
|
||
pop!
|
||
end
|
||
end
|
||
|
||
end
|
||
end
|
||
end
|