asciimath 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d9ffbd1e2a3ba0ae760422ed287d430cce18f80583aa8ceb043cd5235a9805e
4
- data.tar.gz: ebbf1108292b512df0b9aa76a7ee4a17e91fdebf52019dafca3d1e4c9950c4e1
3
+ metadata.gz: 86018ef6bb3e96fddebb125bf2d246b847378dd686cfa720398c09970ad00696
4
+ data.tar.gz: 6347a679a01a6fbfa1b56cfa366e43f80bf195a763efe9150f69067dbaf0c227
5
5
  SHA512:
6
- metadata.gz: 6d117d91868212eea9a0a5fe763fd91e0d4e2febe112c6ed92f8ed6fe745005fb27fc91c0e4dbcfe274cf3beced5d2ffcaa566f03fa2310b355eb40e93fde964
7
- data.tar.gz: 49580040db7cc0f1f5941bdd5d55d2d5829c5b84503ce093faef266ef54aae5a74b8fb7992bebd62b55b92d3f3d0fc75645e82c25a2ca3e0b990b4f7147aa11e
6
+ metadata.gz: 9886f869eafa972e926c0103fc13c56a67203d2a71eaa607489169d7695225cfe3cdbf216ef325153e9d24f7ea8f57c26482a71752a9713992d866826b08a879
7
+ data.tar.gz: 985c445a620542eb3d6f851ce1c832b2c8b89c9aa1d3a2258c64d23456cddb7b36b7953de5f954c3fbbfd9769f113edc499881b88206b4bfc67137ea3cfbaf03
data/AST.adoc CHANGED
@@ -257,8 +257,8 @@ Empty matrix cells are represented as `AsciiMath::AST::Empty`.
257
257
  |++oo++ |:infty |++∞++ (https://codepoints.net/U+221E[U+221E]) |++\infty++
258
258
  |++infty++ |:infty |++∞++ (https://codepoints.net/U+221E[U+221E]) |++\infty++
259
259
  |++aleph++ |:aleph |++ℵ++ (https://codepoints.net/U+2135[U+2135]) |++\aleph++
260
- |++...++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ellipsis++
261
- |++ldots++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ellipsis++
260
+ |++...++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ldots++
261
+ |++ldots++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ldots++
262
262
  |++:.++ |:therefore |++∴++ (https://codepoints.net/U+2234[U+2234]) |++\therefore++
263
263
  |++therefore++ |:therefore |++∴++ (https://codepoints.net/U+2234[U+2234]) |++\therefore++
264
264
  |++:'++ |:because |++∵++ (https://codepoints.net/U+2235[U+2235]) |++\because++
data/CHANGELOG.adoc CHANGED
@@ -1,5 +1,19 @@
1
1
  = Asciimath Changelog
2
2
 
3
+ == 2.0.5
4
+
5
+ Bug fixes::
6
+
7
+ * Issue #75: render `tilde x` as `\tilde{x}` instead of `\~{x}` in LaTeX output.
8
+
9
+ == 2.0.4
10
+
11
+ Bug fixes::
12
+
13
+ * Issue #69: correctly render sub and superscripts as following `obrace` and `ubrace`.
14
+ * Issue #70: fix MathML output for `frac`.
15
+ * Issue #71: correctly parse row vectors.
16
+
3
17
  == 2.0.3
4
18
 
5
19
  Enhancements::
data/lib/asciimath/ast.rb CHANGED
@@ -51,8 +51,8 @@ module AsciiMath
51
51
  Number.new(value)
52
52
  end
53
53
 
54
- def symbol(symbol, text)
55
- Symbol.new(symbol, text)
54
+ def symbol(symbol, text, type)
55
+ Symbol.new(symbol, text, type)
56
56
  end
57
57
 
58
58
  def identifier(value)
@@ -340,14 +340,16 @@ module AsciiMath
340
340
 
341
341
  class Symbol < ValueNode
342
342
  attr_reader :text
343
+ attr_reader :type
343
344
 
344
- def initialize(value, text)
345
+ def initialize(value, text, type)
345
346
  super(value)
346
347
  @text = text.dup.freeze
348
+ @type = type
347
349
  end
348
350
 
349
351
  def ==(o)
350
- super && o.text == text
352
+ super && o.text == text && o.type == type
351
353
  end
352
354
 
353
355
  def to_s
@@ -27,7 +27,9 @@ module AsciiMath
27
27
  :ne => "\\neq",
28
28
  :assign => ":=",
29
29
  :lt => ?<,
30
+ :mlt => "\\ll",
30
31
  :gt => ?>,
32
+ :mgt => "\\gg",
31
33
  :sub => "\\text{–}",
32
34
  :sup => "\\text{^}",
33
35
  :implies => "\\Rightarrow",
@@ -71,7 +73,7 @@ module AsciiMath
71
73
  :glb => "\\operatorname{glb}",
72
74
  :partial => "\\del",
73
75
  :prime => ?',
74
- :tilde => "\\~",
76
+ :tilde => "\\tilde",
75
77
  :nbsp => "\\;",
76
78
  :lceiling => "\\lceil",
77
79
  :rceiling => "\\rceil",
@@ -83,6 +85,7 @@ module AsciiMath
83
85
  :f => "f",
84
86
  :g => "g",
85
87
  :to => "\\rightarrow",
88
+ :ellipsis => "\\ldots",
86
89
  :bold => "\\mathbf",
87
90
  :double_struck => "\\mathbb",
88
91
  :italic => "\\mathit",
@@ -166,7 +169,12 @@ module AsciiMath
166
169
  sup = expression.sup_expression
167
170
  e = expression.base_expression
168
171
 
169
- curly(e)
172
+ if e.is_a?(AsciiMath::AST::UnaryOp) &&
173
+ %i[underbrace overbrace].include?(e.operator.value)
174
+ append(e)
175
+ else
176
+ curly(e)
177
+ end
170
178
 
171
179
  if sub
172
180
  @latex << "_"
@@ -38,7 +38,9 @@ module AsciiMath
38
38
  b.add(:ne, "\u2260", :operator)
39
39
  b.add(:assign, "\u2254", :operator)
40
40
  b.add(:lt, "\u003C", :operator)
41
+ b.add(:mlt, "\u226A", :operator)
41
42
  b.add(:gt, "\u003E", :operator)
43
+ b.add(:mgt, "\u226B", :operator)
42
44
  b.add(:le, "\u2264", :operator)
43
45
  b.add(:ge, "\u2265", :operator)
44
46
  b.add(:prec, "\u227A", :operator)
@@ -52,6 +54,7 @@ module AsciiMath
52
54
  b.add(:subseteq, "\u2286", :operator)
53
55
  b.add(:supseteq, "\u2287", :operator)
54
56
  b.add(:equiv, "\u2261", :operator)
57
+ b.add(:sim, "\u223C", :operator)
55
58
  b.add(:cong, "\u2245", :operator)
56
59
  b.add(:approx, "\u2248", :operator)
57
60
  b.add(:propto, "\u221D", :operator)
@@ -92,6 +95,7 @@ module AsciiMath
92
95
  b.add(:partial, "\u2202", :operator)
93
96
  b.add(:nabla, "\u2207", :operator)
94
97
  b.add(:pm, "\u00B1", :operator)
98
+ b.add(:mp, "\u2213", :operator)
95
99
  b.add(:emptyset, "\u2205", :operator)
96
100
  b.add(:infty, "\u221E", :operator)
97
101
  b.add(:aleph, "\u2135", :operator)
@@ -206,8 +210,8 @@ module AsciiMath
206
210
  b.add(:ddot, '..', :accent, :position => :over)
207
211
  b.add(:overarc, "\u23DC", :accent, :position => :over)
208
212
  b.add(:underline, '_', :accent, :position => :under)
209
- b.add(:underbrace, "\u23DF", :accent, :position => :under)
210
- b.add(:overbrace, "\u23DE", :accent, :position => :over)
213
+ b.add(:underbrace, "\u23DF", :accent, :position => :under, :underover => true)
214
+ b.add(:overbrace, "\u23DE", :accent, :position => :over, :underover => true)
211
215
  b.add(:bold, :bold, :font)
212
216
  b.add(:double_struck, :double_struck, :font)
213
217
  b.add(:italic, :italic, :font)
@@ -344,7 +348,7 @@ module AsciiMath
344
348
  when ::AsciiMath::AST::Paren
345
349
  append_paren(resolve_paren(node.lparen), node.expression, resolve_paren(node.rparen), opts)
346
350
  when ::AsciiMath::AST::SubSup
347
- if (resolve_symbol(node.base_expression) || {})[:underover]
351
+ if is_underover(node.base_expression)
348
352
  append_underover(node.base_expression, node.sub_expression, node.sup_expression)
349
353
  else
350
354
  append_subsup(node.base_expression, node.sub_expression, node.sup_expression)
@@ -383,6 +387,8 @@ module AsciiMath
383
387
  append_root(node.operand2, node.operand1)
384
388
  when :color
385
389
  append_color(node.operand1.to_hex_rgb, node.operand2)
390
+ when :frac
391
+ append_fraction(node.operand1, node.operand2)
386
392
  end
387
393
  end
388
394
  when ::AsciiMath::AST::InfixOp
@@ -505,5 +511,16 @@ module AsciiMath
505
511
  resolved = resolve_symbol(node)
506
512
  !resolved.nil? && resolved[:type] == :accent
507
513
  end
514
+
515
+ def is_underover(node)
516
+ case node
517
+ when AsciiMath::AST::UnaryOp
518
+ symbol = node.operator
519
+ else
520
+ symbol = node
521
+ end
522
+
523
+ (resolve_symbol(symbol) || {})[:underover]
524
+ end
508
525
  end
509
526
  end
@@ -253,7 +253,9 @@ module AsciiMath
253
253
  b.add('!=', 'ne', :ne, :symbol)
254
254
  b.add(':=', :assign, :symbol)
255
255
  b.add('<', 'lt', :lt, :symbol)
256
+ b.add('mlt', 'll', :mlt, :symbol)
256
257
  b.add('>', 'gt', :gt, :symbol)
258
+ b.add('mgt', 'gg', :mgt, :symbol)
257
259
  b.add('<=', 'le', :le, :symbol)
258
260
  b.add('>=', 'ge', :ge, :symbol)
259
261
  b.add('-<', '-lt', 'prec', :prec, :symbol)
@@ -267,6 +269,7 @@ module AsciiMath
267
269
  b.add('sube', 'subseteq', :subseteq, :symbol)
268
270
  b.add('supe', 'supseteq', :supseteq, :symbol)
269
271
  b.add('-=', 'equiv', :equiv, :symbol)
272
+ b.add('~', 'sim', :sim, :symbol)
270
273
  b.add('~=', 'cong', :cong, :symbol)
271
274
  b.add('~~', 'approx', :approx, :symbol)
272
275
  b.add('prop', 'propto', :propto, :symbol)
@@ -312,6 +315,7 @@ module AsciiMath
312
315
  b.add('del', 'partial', :partial, :symbol)
313
316
  b.add('grad', 'nabla', :nabla, :symbol)
314
317
  b.add('+-', 'pm', :pm, :symbol)
318
+ b.add('-+', 'mp', :mp, :symbol)
315
319
  b.add('O/', 'emptyset', :emptyset, :symbol)
316
320
  b.add('oo', 'infty', :infty, :symbol)
317
321
  b.add('aleph', :aleph, :symbol)
@@ -428,16 +432,16 @@ module AsciiMath
428
432
  b.add('ubrace', 'underbrace', :underbrace, :unary)
429
433
  b.add('obrace', 'overbrace', :overbrace, :unary)
430
434
  b.add('cancel', :cancel, :unary)
431
- b.add('bb', :bold, :unary)
432
- b.add('bbb', :double_struck, :unary)
435
+ b.add('bb', 'mathbf', :bold, :unary)
436
+ b.add('bbb', 'mathbb', :double_struck, :unary)
433
437
  b.add('ii', :italic, :unary)
434
438
  b.add('bii', :bold_italic, :unary)
435
- b.add('cc', :script, :unary)
439
+ b.add('cc', 'mathcal', :script, :unary)
436
440
  b.add('bcc', :bold_script, :unary)
437
- b.add('tt', :monospace, :unary)
438
- b.add('fr', :fraktur, :unary)
441
+ b.add('tt', 'mathtt', :monospace, :unary)
442
+ b.add('fr', 'mathfrak', :fraktur, :unary)
439
443
  b.add('bfr', :bold_fraktur, :unary)
440
- b.add('sf', :sans_serif, :unary)
444
+ b.add('sf', 'mathsf', :sans_serif, :unary)
441
445
  b.add('bsf', :bold_sans_serif, :unary)
442
446
  b.add('sfi', :sans_serif_italic, :unary)
443
447
  b.add('sfbi', :sans_serif_bold_italic, :unary)
@@ -507,7 +511,7 @@ module AsciiMath
507
511
  def parse(input)
508
512
  Expression.new(
509
513
  input,
510
- parse_expression(Tokenizer.new(input, @symbol_table), 0)
514
+ parse_expression(Tokenizer.new(input, @symbol_table), nil)
511
515
  )
512
516
  end
513
517
 
@@ -515,36 +519,36 @@ module AsciiMath
515
519
 
516
520
  include AsciiMath::AST
517
521
 
518
- def parse_expression(tok, depth)
519
- e = []
522
+ def parse_expression(tok, close_paren_type)
523
+ e = nil
520
524
 
521
- while (s1 = parse_intermediate_expression(tok, depth))
525
+ while (i1 = parse_intermediate_expression(tok, close_paren_type))
522
526
  t1 = tok.next_token
523
527
 
524
528
  if t1[:type] == :infix && t1[:value] == :frac
525
- s2 = parse_intermediate_expression(tok, depth)
526
- if s2
527
- e << infix(unwrap_paren(s1), symbol(:frac, t1[:text]), unwrap_paren(s2))
529
+ i2 = parse_intermediate_expression(tok, close_paren_type)
530
+ if i2
531
+ e = concat_expressions(e, infix(unwrap_paren(i1), token_to_symbol(t1), unwrap_paren(i2)))
528
532
  else
529
- e << s1
533
+ e = concat_expressions(e, i1)
530
534
  end
531
535
  elsif t1[:type] == :eof
532
- e << s1
536
+ e = concat_expressions(e, i1)
533
537
  break
534
538
  else
535
- e << s1
539
+ e = concat_expressions(e, i1)
536
540
  tok.push_back(t1)
537
- if (t1[:type] == :lrparen || t1[:type] == :rparen) && depth > 0
541
+ if t1[:type] == close_paren_type
538
542
  break
539
543
  end
540
544
  end
541
545
  end
542
546
 
543
- expression(*e)
547
+ e
544
548
  end
545
549
 
546
- def parse_intermediate_expression(tok, depth)
547
- s = parse_simple_expression(tok, depth)
550
+ def parse_intermediate_expression(tok, close_paren_type)
551
+ s = parse_simple_expression(tok, close_paren_type)
548
552
  sub = nil
549
553
  sup = nil
550
554
 
@@ -553,17 +557,17 @@ module AsciiMath
553
557
  when :infix
554
558
  case t1[:value]
555
559
  when :sub
556
- sub = parse_simple_expression(tok, depth)
560
+ sub = parse_simple_expression(tok, close_paren_type)
557
561
  if sub
558
562
  t2 = tok.next_token
559
563
  if t2[:type] == :infix && t2[:value] == :sup
560
- sup = parse_simple_expression(tok, depth)
564
+ sup = parse_simple_expression(tok, close_paren_type)
561
565
  else
562
566
  tok.push_back(t2)
563
567
  end
564
568
  end
565
569
  when :sup
566
- sup = parse_simple_expression(tok, depth)
570
+ sup = parse_simple_expression(tok, close_paren_type)
567
571
  else
568
572
  tok.push_back(t1)
569
573
  end
@@ -582,46 +586,54 @@ module AsciiMath
582
586
  end
583
587
  end
584
588
 
585
- def parse_simple_expression(tok, depth)
589
+ def parse_simple_expression(tok, close_paren_type)
586
590
  t1 = tok.next_token
587
591
 
588
592
  case t1[:type]
589
593
  when :lparen, :lrparen
594
+ if t1[:type] == :lparen
595
+ close_with = :rparen
596
+ else
597
+ close_with = :lrparen
598
+ end
599
+
590
600
  t2 = tok.next_token
591
- case t2[:type]
592
- when :rparen, :lrparen
593
- paren(token_to_symbol(t1), nil, token_to_symbol(t2))
594
- else
595
- tok.push_back(t2)
601
+ if t2[:type] == close_with
602
+ paren(token_to_symbol(t1), nil, token_to_symbol(t2))
603
+ else
604
+ tok.push_back(t2)
596
605
 
597
- e = parse_expression(tok, depth + 1)
606
+ e = parse_expression(tok, close_with)
598
607
 
599
- t2 = tok.next_token
600
- case t2[:type]
601
- when :rparen, :lrparen
602
- convert_to_matrix(paren(token_to_symbol(t1), e, token_to_symbol(t2)))
603
- else
604
- tok.push_back(t2)
605
- paren(token_to_symbol(t1), e, nil)
608
+ t2 = tok.next_token
609
+ if t2[:type] == close_with
610
+ convert_to_matrix(paren(token_to_symbol(t1), e, token_to_symbol(t2)))
611
+ else
612
+ tok.push_back(t2)
613
+ if t1[:type] == :lrparen
614
+ concat_expressions(token_to_symbol(t1), e)
615
+ else
616
+ paren(token_to_symbol(t1), e, nil)
606
617
  end
618
+ end
607
619
  end
608
620
  when :rparen
609
- if depth > 0
621
+ if close_paren_type.nil?
622
+ token_to_symbol(t1)
623
+ else
610
624
  tok.push_back(t1)
611
625
  nil
612
- else
613
- token_to_symbol(t1)
614
626
  end
615
627
  when :unary
616
- parse_simple_expression = parse_simple_expression(tok, depth)
628
+ parse_simple_expression = parse_simple_expression(tok, close_paren_type)
617
629
  s = unwrap_paren(parse_simple_expression)
618
630
  s = identifier('') if s.nil?
619
631
  s = convert_node(s, t1[:convert_operand])
620
632
  unary(token_to_symbol(t1), s)
621
633
  when :binary
622
- s1 = unwrap_paren(parse_simple_expression(tok, depth))
634
+ s1 = unwrap_paren(parse_simple_expression(tok, close_paren_type))
623
635
  s1 = identifier('') if s1.nil?
624
- s2 = unwrap_paren(parse_simple_expression(tok, depth))
636
+ s2 = unwrap_paren(parse_simple_expression(tok, close_paren_type))
625
637
  s2 = identifier('') if s2.nil?
626
638
 
627
639
  s1 = convert_node(s1, t1[:convert_operand1])
@@ -641,12 +653,37 @@ module AsciiMath
641
653
  end
642
654
  end
643
655
 
656
+ def concat_expressions(e1, e2)
657
+ case e1
658
+ when Sequence
659
+ case e2
660
+ when Sequence
661
+ expression(*(e1.to_a), *(e2.to_a))
662
+ when nil
663
+ e1
664
+ else
665
+ expression(*(e1.to_a), e2)
666
+ end
667
+ when nil
668
+ e2
669
+ else
670
+ case e2
671
+ when Sequence
672
+ expression(e1, *(e2.to_a))
673
+ when nil
674
+ e1
675
+ else
676
+ expression(e1, e2)
677
+ end
678
+ end
679
+ end
680
+
644
681
  def token_to_symbol(t1)
645
- symbol(t1[:value], t1[:text])
682
+ symbol(t1[:value], t1[:text], t1[:type])
646
683
  end
647
684
 
648
685
  def unwrap_paren(node)
649
- if node.is_a?(::AsciiMath::AST::Paren)
686
+ if node.is_a?(::AsciiMath::AST::Paren) && (node.lparen.nil? || node.lparen.type == :lparen) && (node.rparen.nil? || node.rparen.type == :rparen)
650
687
  group(node.lparen, node.expression, node.rparen)
651
688
  else
652
689
  node
@@ -654,14 +691,23 @@ module AsciiMath
654
691
  end
655
692
 
656
693
  def convert_to_matrix(node)
657
- return node unless node.is_a?(::AsciiMath::AST::Paren) && node.expression.is_a?(::AsciiMath::AST::Sequence)
694
+ return node unless node.is_a?(::AsciiMath::AST::Paren)
695
+
696
+ case node.expression
697
+ when ::AsciiMath::AST::Sequence
698
+ rows, separators = node.expression.partition.with_index { |obj, i| i.even? }
699
+ when ::AsciiMath::AST::Paren
700
+ rows = [node.expression]
701
+ separators = []
702
+ else
703
+ return node
704
+ end
658
705
 
659
- rows, separators = node.expression.partition.with_index { |obj, i| i.even? }
660
- return node unless rows.length > 1 &&
706
+ return node unless rows.length >= 1 &&
661
707
  rows.length > separators.length &&
662
708
  separators.all? { |item| is_matrix_separator(item) } &&
663
- (rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lparen, '(') && item.rparen == symbol(:rparen, ')') } ||
664
- rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lbracket, '[') && item.rparen == symbol(:rbracket, ']') })
709
+ (rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lparen, '(', :lparen) && item.rparen == symbol(:rparen, ')', :rparen) } ||
710
+ rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lbracket, '[', :lparen) && item.rparen == symbol(:rbracket, ']', :rparen) })
665
711
 
666
712
  rows = rows.map do |row|
667
713
  chunks = []
@@ -755,7 +801,7 @@ module AsciiMath
755
801
  end
756
802
 
757
803
  DEFAULT_COLOR_TABLE = ::AsciiMath::Parser.add_default_colors(AsciiMath::ColorTableBuilder.new).build
758
- DEFAULT_PARSER_SYMBOL_TABLE = ::AsciiMath::Parser.add_default_parser_symbols(AsciiMath::SymbolTableBuilder.new).build
804
+ DEFAULT_PARSER_SYMBOL_TABLE = ::AsciiMath::Parser.add_default_parser_symbols(AsciiMath::SymbolTableBuilder.new(allow_symbol_overwrites: false)).build
759
805
  end
760
806
 
761
807
  class Expression
@@ -1,7 +1,8 @@
1
1
  module AsciiMath
2
2
  class SymbolTableBuilder
3
- def initialize()
3
+ def initialize(allow_symbol_overwrites: true)
4
4
  @table = {}
5
+ @allow_symbol_overwrites = allow_symbol_overwrites
5
6
  end
6
7
 
7
8
  def add(*args)
@@ -15,7 +16,11 @@ module AsciiMath
15
16
  entry[:value] = args.pop
16
17
 
17
18
  entry.freeze
18
- args.each { |name| @table[name.freeze] = entry }
19
+ args.map(&:freeze).each do |name|
20
+ raise "Symbol overwrites are disallowed, but were attempted for #{name}" if !@allow_symbol_overwrites && !@table[name].nil?
21
+
22
+ @table[name] = entry
23
+ end
19
24
  end
20
25
 
21
26
  def build
@@ -1,3 +1,3 @@
1
1
  module AsciiMath
2
- VERSION = "2.0.3"
2
+ VERSION = "2.0.5"
3
3
  end
data/spec/ast.rb CHANGED
@@ -90,7 +90,7 @@ module AsciiMath
90
90
  def symbol(text)
91
91
  symbol = ::AsciiMath::Parser::DEFAULT_PARSER_SYMBOL_TABLE[text]
92
92
  if symbol
93
- ACTUAL_AST.symbol(symbol[:value], text)
93
+ ACTUAL_AST.symbol(symbol[:value], text, symbol[:type])
94
94
  else
95
95
  nil
96
96
  end
@@ -14,7 +14,7 @@ describe 'AsciiMath::Parser', :variant => :ast do
14
14
  my_tokens_table.add('mysymbol', :mysymbol, :symbol)
15
15
 
16
16
  parsed = AsciiMath::parse("a + mysymbol + b", my_tokens_table.build)
17
- expect(parsed.ast).to eq(seq(identifier('a'), symbol('+'), ::AsciiMath::AST::Symbol.new(:mysymbol, 'mysymbol'), symbol('+'), identifier('b')))
17
+ expect(parsed.ast).to eq(seq(identifier('a'), symbol('+'), ::AsciiMath::AST::Symbol.new(:mysymbol, 'mysymbol', :symbol), symbol('+'), identifier('b')))
18
18
  end
19
19
 
20
20
  it "should support replacing standard symbols" do
@@ -23,6 +23,12 @@ describe 'AsciiMath::Parser', :variant => :ast do
23
23
  my_tokens_table.add('+', :foo, :symbol)
24
24
 
25
25
  parsed = AsciiMath::parse("a + b", my_tokens_table.build)
26
- expect(parsed.ast).to eq(seq(identifier('a'), ::AsciiMath::AST::Symbol.new(:foo, '+'), identifier('b')))
26
+ expect(parsed.ast).to eq(seq(identifier('a'), ::AsciiMath::AST::Symbol.new(:foo, '+', :symbol), identifier('b')))
27
+ end
28
+
29
+ it "should support disallowing symbol overwrites" do
30
+ my_tokens_table = AsciiMath::SymbolTableBuilder.new(allow_symbol_overwrites: false)
31
+ AsciiMath::Parser.add_default_parser_symbols(my_tokens_table)
32
+ expect{my_tokens_table.add('+', :foo, :symbol)}.to raise_error 'Symbol overwrites are disallowed, but were attempted for +'
27
33
  end
28
34
  end
data/spec/parser_spec.rb CHANGED
@@ -328,6 +328,13 @@ RSpec.shared_examples 'AsciiMath Examples' do
328
328
  :latex => '\\left ( \\begin{matrix} 1 \\\\ 42 \\end{matrix} \\right )',
329
329
  ))
330
330
 
331
+ example('((1,42))', &should_generate(
332
+ :ast => matrix([%w[1 42]]),
333
+ :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>42</mn></mtd></mtr></mtable><mo>)</mo></mrow></math>',
334
+ :html => '<span class="math-inline"><span class="math-row"><span class="math-brace" style="font-size: 100%;">(</span><span class="math-matrix" style="grid-template-columns:repeat(2,1fr);grid-template-rows:repeat(1,1fr);"><span class="math-row"><span class="math-number">1</span></span><span class="math-row"><span class="math-number">42</span></span></span><span class="math-brace" style="font-size: 100%;">)</span></span></span>',
335
+ :latex => '\\left ( \\begin{matrix} 1 & 42 \\end{matrix} \\right )',
336
+ ))
337
+
331
338
  example('((1,2,3),(4,5,6),(7,8,9))', &should_generate(
332
339
  :ast => matrix([%w[1 2 3], %w[4 5 6], %w[7 8 9]]),
333
340
  :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>2</mn></mtd><mtd><mn>3</mn></mtd></mtr><mtr><mtd><mn>4</mn></mtd><mtd><mn>5</mn></mtd><mtd><mn>6</mn></mtd></mtr><mtr><mtd><mn>7</mn></mtd><mtd><mn>8</mn></mtd><mtd><mn>9</mn></mtd></mtr></mtable><mo>)</mo></mrow></math>',
@@ -337,7 +344,7 @@ RSpec.shared_examples 'AsciiMath Examples' do
337
344
 
338
345
  example('|(a,b),(c,d)|=ad-bc', &should_generate(
339
346
  :ast => seq(
340
- matrix(symbol('|'), [%w(a b), %w(c d)], symbol('|'),),
347
+ matrix(symbol('|'), [%w(a b), %w(c d)], symbol('|')),
341
348
  symbol('='),
342
349
  'a', 'd',
343
350
  symbol('-'),
@@ -596,6 +603,58 @@ RSpec.shared_examples 'AsciiMath Examples' do
596
603
  :latex => '40 \% \cdot 3 !'
597
604
  ))
598
605
 
606
+ example('R(alpha_(K+1)|x)', &should_generate(
607
+ :ast => seq('R', paren(symbol('('), seq(sub('alpha', grseq('K', symbol('+'), '1')), symbol('|'), 'x'), symbol(')'))),
608
+ :mathml => '<math><mi>R</mi><mrow><mo>(</mo><mrow><msub><mi>&#x3B1;</mi><mrow><mi>K</mi><mo>+</mo><mn>1</mn></mrow></msub><mo>|</mo><mi>x</mi></mrow><mo>)</mo></mrow></math>',
609
+ :latex => 'R \\left ( \\alpha_{K + 1} | x \\right )'
610
+ ))
611
+
612
+ example('|(a),(b)|', &should_generate(
613
+ :ast => matrix(symbol('|'), [%w(a), %w(b)], symbol('|')),
614
+ ))
615
+
616
+ example('|a+b|', &should_generate(
617
+ :ast => paren(symbol('|'), seq('a', '+', 'b'), symbol('|')),
618
+ ))
619
+
620
+ example('|a+b|/c', &should_generate(
621
+ :ast => infix(paren(symbol('|'), seq('a', '+', 'b'), symbol('|')), '/', 'c'),
622
+ ))
623
+
624
+ example('[[a,b,|,c],[d,e,|,f]]', &should_generate(
625
+ :ast => matrix(symbol('['), [['a', 'b', symbol('|'), 'c'], ['d', 'e', symbol('|'), 'f']], symbol(']')),
626
+ ))
627
+
628
+ example('~a mlt b mgt -+c', &should_generate(
629
+ :ast => seq(symbol('~'), 'a', symbol('mlt'), 'b', symbol('mgt'), symbol('-+'), 'c'),
630
+ :latex => '\\sim a \\ll b \\gg \\mp c',
631
+ :mathml => '<math><mo>&#x223C;</mo><mi>a</mi><mo>&#x226A;</mo><mi>b</mi><mo>&#x226B;</mo><mo>&#x2213;</mo><mi>c</mi></math>'
632
+ ))
633
+
634
+ example('a+b+...+c', &should_generate(
635
+ :ast => seq('a', symbol('+'), 'b', symbol('+'), symbol('...'), symbol('+'), 'c'),
636
+ :latex => 'a + b + \ldots + c',
637
+ :mathml => '<math><mi>a</mi><mo>+</mo><mi>b</mi><mo>+</mo><mo>&#x2026;</mo><mo>+</mo><mi>c</mi></math>'
638
+ ))
639
+
640
+ example('frac{a}{b}', &should_generate(
641
+ :ast => binary('frac', group(symbol('{'), 'a', symbol('}')), group(symbol('{'), 'b', symbol('}'))),
642
+ :latex => '\frac{a}{b}',
643
+ :mathml => '<math><mfrac><mi>a</mi><mi>b</mi></mfrac></math>'
644
+ ))
645
+
646
+ example('ubrace(((1, 0),(0, 1)))_("Adjustment to texture space")', &should_generate(
647
+ :ast => subsup(unary(symbol('ubrace'), group(matrix([%w[1 0], %w[0 1]]))), group("Adjustment to texture space"), []),
648
+ :latex => '\underbrace{\left ( \begin{matrix} 1 & 0 \\\\ 0 & 1 \end{matrix} \right )}_{\text{Adjustment to texture space}}',
649
+ :mathml => '<math><munder><munder accentunder="true"><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable><mo>)</mo></mrow><mo>&#x23DF;</mo></munder><mtext>Adjustment to texture space</mtext></munder></math>'
650
+ ))
651
+
652
+ example('tilde x', &should_generate(
653
+ :ast => unary(symbol('tilde'), 'x'),
654
+ :latex => '\\tilde{x}'
655
+ ))
656
+
657
+
599
658
  version = RUBY_VERSION.split('.').map { |s| s.to_i }
600
659
 
601
660
  if version[0] > 1 || version[1] > 8
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciimath
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pepijn Van Eeckhoudt
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-07-26 00:00:00.000000000 Z
12
+ date: 2023-04-09 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A pure Ruby AsciiMath parsing and conversion library.
15
15
  email:
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  - !ruby/object:Gem::Version
101
101
  version: '0'
102
102
  requirements: []
103
- rubygems_version: 3.1.4
103
+ rubygems_version: 3.0.3.1
104
104
  signing_key:
105
105
  specification_version: 4
106
106
  summary: AsciiMath parser and converter