░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/var/www/canvas/vendor/bundle/ruby/3.1.0/gems/ritex-1.0.1/lib
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: ritex.rb
## lib/ritex.rb -- contains Ritex::Parser ## Author:: William Morgan (mailto: wmorgan-ritex@masanjin.net) ## Copyright:: Copyright 2005-2010 William Morgan ## License:: GNU GPL version 2 ## ## :title:Ritex: a Ruby WebTeX to MathML converter ## :main:README require "ritex/parser" require "ritex/lexer" require "ritex/mathml/entities" require "ritex/mathml/functions" require "ritex/mathml/markup" require 'racc/parser' # just for Racc::ParserError ## Container module for all Ritex stuff. The entry point is ## Ritex::Parser. module Ritex ## Thrown by Parser upon errors. See Parser#merror=. class Error < StandardError; end ## The parser for itex and the main entry point for Ritex. This class ## is partially defined here and partially generated by Racc from ## lib/parser.y. ## ## Create the parser with #new. Parse strings with #parse. That's all ## there is to it. class Parser FORMATS = [:mathml, :raw] ## If true, Ritex will output a <merror>...</merror> message in the ## MathML if an unknown entity is encountered. If false (the default), ## Ritex will throw a Ritex::Error. attr_accessor :merror ## _format_ is the desired output format and must be in the FORMATS ## list. Right now that's just :mathml. def initialize format = :mathml self.format = format @macros = {} @merror = false end ## Parse a string. Returns the MathML output in string form. Note that macro ## definitions are cumulative and persistent across calls to #parse. If you ## don't want this behavior, you must explicitly call #flush_macros after ## every #parse call. ## ## _opts_ is a hash of options: ## ## _nowrap_, if true, will omit wrapping the output in a top-level XML math ## tag. Only useful if you're generating these tags yourself. ## ## _display_, if true, emits display markup, as opposed to inline markup. ## For mathml output this only has an effect if _nowrap_ is true. def parse s, opts={} nowrap = opts[:nowrap] display = opts[:display] @lex = Lexer.new self, s r = yyparse @lex, :lex r = markup r, (display ? :displaymath : :math) unless nowrap r = raw_blob_to_string(r) if @format == :raw r end attr_reader :format def format= format raise ArgumentError, "format must be one of #{FORMATS * ', '}" unless FORMATS.include? format @format = format end ## Delete all macros def flush_macros; @macros = {}; end def markup what, tag, opts=[] #:nodoc: case @format when :mathml; handle_mathml_markup what, tag, opts when :raw; handle_raw_markup what, tag, opts end end def handle_mathml_markup what, tag, opts tag, opts = case tag when String [tag, opts] when Symbol a, b = MathML::MARKUP[tag] [a, [b, opts].flatten.compact.join(" ")] end unless opts.empty? "<#{tag} #{opts}>#{what}</#{tag}>" else "<#{tag}>#{what}</#{tag}>" end end ## this is a great example of how much a horrible hack raw mode is def handle_raw_markup what, tag, opts #:nodoc: case tag when :var; what when :subsup; "#{what[0]}_#{what[1]}^#{what[2]}" when :sub; "#{what[0]}_#{what[1]}" when :sup; "#{what[0]}^#{what[1]}" when :unaryminus; "-#{what[0]}" when :group; "{#{raw_blob_to_string what}}" else; what end end def lookup sym #:nodoc: case @format when :mathml return error("unknown entity #{sym.inspect}") unless MathML::ENTITIES.member? sym MathML::ENTITIES[sym] when :raw "\\" + sym end end def token o #:nodoc: case @format when :mathml; MathML::TOKENS[o] || o when :raw; o end end def op o, opts=[] case @format when :mathml; markup(token(o), "mo", opts) when :raw; o end end def funcs #:nodoc: case @format when :mathml, :raw; MathML::FUNCTIONS end end def envs #:nodoc: case @format when :mathml, :raw; MathML::ENVS end end def macros #:nodoc: @macros end def op_symbols #:nodoc: case @format when :mathml, :raw; MathML::OPERATORS.merge(MathML::UNARY_OPERATORS).merge(MathML::MATH_FUNCTIONS) end end private def error e if @merror "<merror>e</merror>" else raise Error, e end end def safe s case @format when :mathml; s.gsub("&", "&").gsub(">", ">").gsub("<", "<") when :raw; s end end def join *a case @format when :mathml; a.join when :raw # horrible hack for raw "blobs" if a.size == 1 a[0] elsif a.size == 2 && a.first == "" a[1] else a.flatten end end end def special name, *a if @macros.member? name #puts "evaluating macro (arity #{@macros[name].arity}): type #{name.inspect}, #{a.length} args #{a.inspect}" res = @macros[name][*a] res = raw_blob_to_string res if @format == :raw #puts "got #{res}" @lex.push res "" elsif funcs.member? name # puts "*** running func #{name}" if @format == :raw "\\#{name}" + a.map { |x| raw_funarg(x) }.join else interpret funcs[name][*a] end elsif envs.member? name if @format == :raw "\\#{name}" + a.map { |x| raw_funarg(x) }.join else interpret envs[name][*a] end else error "unknown function, macro or environment #{name.inspect}" end end def raw_funarg f f = raw_blob_to_string f f[0, 1] == '{' ? f : "{#{f}}" end def raw_blob_to_string x #:nodoc: case x when String; x when Array; x.join else; x # ? end end ## functions and environments return either a [method, [args]] array, or a ## string. if the former, do the call; if the latter, just use the string ## directly. ## ## possible one level too many of indirection going on here, but it makes ## writing the functions really simple. def interpret x # :nodoc: case x when Array m, args = x send m, *args else x end end def define sym, arity, exp arity = arity.to_i raise Error, "macro arity must be <= 3" unless arity <= 3 raise Error, "macro arity must be >= 0" unless arity >= 0 # puts "defining macro #{sym} with exp #{exp} (arity #{arity})" warn "overriding definition for #{sym}" if @macros.member? sym @macros[sym] = lambda do |*a| raise Error, "expecting #{arity} arguments, got #{a.length}" unless a.length == arity if @format == :raw a = a.map { |x| raw_blob_to_string x } exp = raw_blob_to_string(exp) end (0 ... arity).inject(exp) { |s, i| s.gsub(/\##{i + 1}/, a[i]) } end @macros[sym].instance_eval "def arity; #{arity}; end" # hack! "" end end end
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📁 ritex/
DIR
—
2023-09-24 03:47
📄 ritex.rb
RB
6.6 KB
2023-09-24 03:47
EDIT