Remove curly

To reduce the complexity of the parse tree we remove the curly
element which is used for grouping in TeX. Instead, we use
use an attribute which defines if the group is put into curly
brackets or not. The functionality of the curly element
is transferred to the TexArray which was the only possible
child of the curly element before. To ease the transition,
we add a special constructor to TexArray.

We could not measure any performance implications of this change.

Bug: T333973
Change-Id: Idcb58694022831113bdc437576bb9f48658fff2f
这个提交包含在:
Moritz Schubotz (physikerwelt) 2024-02-18 00:02:37 +01:00
父节点 5f4cfc47bc
当前提交 a102a4ed52
找不到此签名对应的密钥
GPG 密钥 ID: F803DB146DDF36C3
共有 15 个文件被更改,包括 100 次插入154 次删除

查看文件

@ -65,7 +65,6 @@ const useStatements =
'use MediaWiki\\Extension\\Math\\WikiTexVC\\Nodes\\Big;\n' +
'use MediaWiki\\Extension\\Math\\WikiTexVC\\Nodes\\ChemFun2u;\n' +
'use MediaWiki\\Extension\\Math\\WikiTexVC\\Nodes\\ChemWord;\n' +
'use MediaWiki\\Extension\\Math\\WikiTexVC\\Nodes\\Curly;\n' +
'use MediaWiki\\Extension\\Math\\WikiTexVC\\Nodes\\Declh;\n' +
'use MediaWiki\\Extension\\Math\\WikiTexVC\\Nodes\\Dollar;\n' +
'use MediaWiki\\Extension\\Math\\WikiTexVC\\Nodes\\DQ;\n' +

查看文件

@ -31,7 +31,6 @@ use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmtext;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmtr;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmunder;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmunderover;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\FQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun1;
@ -41,6 +40,7 @@ use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun2sq;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun4;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Literal;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Matrix;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexNode;
use MediaWiki\Extension\Math\WikiTexVC\TexVC;
@ -136,7 +136,7 @@ class BaseParsing {
foreach ( $tableRow->getArgs() as $tableCell ) {
$renderedInner .= $mtd->getStart();
foreach ( $tableCell->getArgs() as $cellItem ) {
if ( !$discarded && $cellItem instanceof Curly ) {
if ( !$discarded && $cellItem->isCurly() ) {
$discarded = true;
// Just discard the number of rows atm, it is in the first Curly
} else {
@ -357,7 +357,7 @@ class BaseParsing {
}
public static function hskip( $node, $passedArgs, $operatorContent, $name ) {
if ( $node->getArg() instanceof Curly ) {
if ( $node->getArg()->isCurly() ) {
$unit = MMLutil::squashLitsToUnit( $node->getArg() );
if ( !$unit ) {
return null;
@ -556,7 +556,7 @@ class BaseParsing {
$addHlines = true;
}
}
if ( count( $arg->getArgs() ) >= 1 && $arg->getArgs()[0] instanceof Curly ) {
if ( count( $arg->getArgs() ) >= 1 && $arg->getArgs()[0]->isCurly() ) {
// Discarding the column information Curly at the moment
// $usedArg->getArgs()[0] = null;
$columnInfo = $usedArg->getArgs()[0]->render();
@ -743,7 +743,8 @@ class BaseParsing {
}
$arg1 = $node->getArg1();
if ( $arg1 instanceof Curly ) {
// the second check is to avoid a false positive for PhanTypeMismatchArgumentSuperType
if ( $arg1->isCurly() && $arg1 instanceof TexArray ) {
$unit = MMLutil::squashLitsToUnit( $arg1 );
if ( !$unit ) {
return null;
@ -1043,8 +1044,8 @@ class BaseParsing {
if ( $node instanceof Fun2sq ) {
$arg1 = $node->getArg1();
$arg1i = "";
if ( $arg1 instanceof Curly ) {
$arg1i = $arg1->getArg()->render();
if ( $arg1->isCurly() ) {
$arg1i = $arg1->render();
}
if ( str_contains( $arg1i, "{b}" ) ) {
@ -1099,11 +1100,12 @@ class BaseParsing {
// match args in row of subargs, unless an element has explicit annotations
// nested annotations ?
$arg1 = $node->getArg1();
if ( !$node->getArg2() instanceof Curly ) {
$arg2 = $node->getArg2();
if ( !$arg2->isCurly() ) {
return null;
}
// tbd refactor intent form and fiddle in mml or tree
$intentStr = MMLutil::squashLitsToUnitIntent( $node->getArg2() );
$intentStr = MMLutil::squashLitsToUnitIntent( $arg2 );
$intentContent = MMLParsingUtil::getIntentContent( $intentStr );
$intentParams = MMLParsingUtil::getIntentParams( $intentContent );
// Sometimes the intent has additioargs = {array[3]} nal args in the same string
@ -1122,19 +1124,19 @@ class BaseParsing {
$intentParamsState = $intentParams ? [ "intent-params" => $intentParams ] : $operatorContent;
// Here are some edge cases, they might go into renderMML in the related element
if ( str_contains( $intentContent, "matrix" ) ||
( $arg1 instanceof Curly && $arg1->getArg()->getArgs()[0] instanceof Matrix ) ) {
$element = $arg1->getArg()->getArgs()[0];
( $arg1->isCurly() && $arg1->getArgs()[0] instanceof Matrix ) ) {
$element = $arg1->getArgs()[0];
$rendered = $element->renderMML( [], $intentParamsState );
$hackyXML = MMLParsingUtil::forgeIntentToSpecificElement( $rendered,
$intentContentAtr, "mtable" );
return $hackyXML;
} elseif ( $arg1 instanceof Curly && count( $arg1->getArg()->getArgs() ) >= 2 ) {
} elseif ( $arg1->isCurly() && count( $arg1->getArgs() ) >= 2 ) {
// Create a surrounding element which holds the intents
$mrow = new MMLmrow( "", $intentContentAtr );
return $mrow->encapsulateRaw( $arg1->renderMML( [], $intentParamsState ) );
} elseif ( $arg1 instanceof Curly && count( $arg1->getArg()->getArgs() ) >= 1 ) {
} elseif ( $arg1->isCurly() && count( $arg1->getArgs() ) >= 1 ) {
// Forge the intent attribute to the top-level element after MML rendering
$element = $arg1->getArg()->getArgs()[0];
$element = $arg1->getArgs()[0];
$rendered = $element->renderMML( [], $intentParamsState );
$hackyXML = MMLParsingUtil::forgeIntentToTopElement( $rendered, $intentContentAtr );
return $hackyXML;
@ -1185,7 +1187,7 @@ class BaseParsing {
$mmlMrow = new MMLmrow();
$mtext = new MMLmtext( "", MMLParsingUtil::getFontArgs( $name, null, null ) );
$inner = $node->getArg() instanceof Curly ? $node->getArg()->getArg()->renderMML(
$inner = $node->getArg()->isCurly() ? $node->getArg()->renderMML(
[], [ "inHBox" => true ] )
: $node->getArg()->renderMML( [ "fromHBox" => true ] );
return $mmlMrow->encapsulateRaw( $mtext->encapsulateRaw( $inner ) );

查看文件

@ -2,9 +2,9 @@
namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util;
use IntlChar;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Literal;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexNode;
/**
@ -78,12 +78,12 @@ class MMLutil {
/**
* Assumes the input curly contains an TexArray of literals, squashes the TexArray characters to a string.
* @param Curly $node curly containing a TexArray of literals
* @param TexArray $node TexArray of literals
* @return ?string squashed string in example "2mu", "-3mu" etc. Null if no TexArray inside curly.
*/
public static function squashLitsToUnit( Curly $node ): ?string {
public static function squashLitsToUnit( TexArray $node ): ?string {
$unit = "";
foreach ( $node->getArg()->getArgs() as $literal ) {
foreach ( $node->getArgs() as $literal ) {
if ( !$literal instanceof Literal ) {
continue;
}
@ -220,11 +220,11 @@ class MMLutil {
* @return ?string squashed string in example "2mu", "-3mu" etc. Null if no TexArray inside curly.
*/
public static function squashLitsToUnitIntent( TexNode $node ): ?string {
if ( !$node instanceof Curly ) {
if ( !$node->isCurly() ) {
return null;
}
$unit = "";
foreach ( $node->getArg()->getArgs() as $literal ) {
foreach ( $node->getArgs() as $literal ) {
if ( $literal instanceof DQ ) {
$args = $literal->getArgs();
if ( !$args[0] instanceof Literal || !$args[1] instanceof Literal ) {

查看文件

@ -1,51 +0,0 @@
<?php
declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\WikiTexVC\Nodes;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow;
class Curly extends TexNode {
/** @var TexArray */
private $arg;
public function __construct( TexArray $arg ) {
parent::__construct( $arg );
$this->arg = $arg;
}
/**
* @return TexArray
*/
public function getArg(): TexArray {
return $this->arg;
}
public function render() {
return $this->arg->inCurlies();
}
public function renderMML( $arguments = [], $state = [] ) {
if ( count( $this->arg->getArgs() ) > 1 ) {
$mmlRow = new MMLmrow();
return $mmlRow->encapsulateRaw( parent::renderMML( $arguments, $state ) );
}
return parent::renderMML( $arguments, $state );
}
public function inCurlies() {
return $this->render();
}
public function extractSubscripts() {
return $this->arg->extractSubscripts();
}
public function getModIdent() {
return $this->arg->getModIdent();
}
}

查看文件

@ -47,7 +47,7 @@ class DQ extends TexNode {
$emptyMrow = "";
// In cases with empty curly preceding like: "{}_pF_q"
if ( $this->getBase() instanceof Curly && $this->getBase()->isEmpty() ) {
if ( $this->getBase()->isCurly() && $this->getBase()->isEmpty() ) {
$mrow = new MMLmrow();
$emptyMrow = $mrow->getEmpty();
}

查看文件

@ -57,24 +57,19 @@ class FQ extends TexNode {
// A specific FQ case with preceding limits, just invoke the limits parsing manually.
return BaseParsing::limits( $this, $arguments, $state, "" );
}
$base = $this->getBase();
if ( $this->getArgs()[0]->getLength() == 0 ) {
if ( $base->getLength() == 0 && !$base->isCurly() ) {
// this happens when FQ is located in Sideset (is this a common parsing way?)
$mrow = new MMLmrow();
return $mrow->encapsulateRaw( $this->getDown()->renderMML( [], $state ) ) .
$mrow->encapsulateRaw( $this->getUp()->renderMML( [], $state ) );
}
// Not sure if this case is necessary ..
if ( is_string( $this->getArgs()[0] ) ) {
return $this->parseToMML( $this->getArgs()[0], $arguments, null );
}
$melement = new MMLmsubsup();
// tbd check for more such cases like TexUtilTest 317
$base = $this->getBase();
if ( $base instanceof Literal ) {
$litArg = trim( $this->getBase()->getArgs()[0] );
$litArg = trim( $base->getArgs()[0] );
$tu = TexUtil::getInstance();
// "sum", "bigcap", "bigcup", "prod" ... all are nullary macros.
if ( $tu->nullary_macro( $litArg ) && !$tu->is_literal( $litArg ) ) {
@ -85,13 +80,13 @@ class FQ extends TexNode {
$mrow = new MMLmrow();
$emptyMrow = "";
// In cases with empty curly preceding like: "{}_1^2\!\Omega_3^4"
if ( $this->getBase() instanceof Curly && $this->getBase()->isEmpty() ) {
if ( $base->isCurly() && $base->isEmpty() ) {
$emptyMrow = $mrow->getEmpty();
}
// This seems to be the common case
$inner = $melement->encapsulateRaw(
$emptyMrow .
$this->getBase()->renderMML( [], $state ) .
$base->renderMML( [], $state ) .
$mrow->encapsulateRaw( $this->getDown()->renderMML( $arguments, $state ) ) .
$mrow->encapsulateRaw( $this->getUp()->renderMML( $arguments, $state ) ) );

查看文件

@ -9,11 +9,19 @@ use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\BaseMappings;
use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLParsingUtil;
use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLutil;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmo;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmstyle;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmsup;
use MediaWiki\Extension\Math\WikiTexVC\TexUtil;
class TexArray extends TexNode {
protected bool $curly = false;
public static function newCurly( ...$args ) {
$node = new self( ...$args );
$node->curly = true;
return $node;
}
public function __construct( ...$args ) {
$nargs = [];
@ -246,10 +254,10 @@ class TexArray extends TexNode {
if ( $styleArguments ) {
$state["styleargs"] = $styleArguments;
if ( $next instanceof Curly ) {
$mmlStyle = new MMLmstyle( "", $styleArguments );
$fullRenderedArray .= $mmlStyle->getStart();
if ( $next->isCurly() ) {
// Wrap with style-tags when the next element is a Curly which determines start and end tag.
$mmlStyle = new MMLmstyle( "", $styleArguments );
$fullRenderedArray .= $mmlStyle->getStart();
$fullRenderedArray .= $this->createMMLwithContext( $currentColor, $next, $state, $arguments );
$fullRenderedArray .= $mmlStyle->getEnd();
$mmlStyle = null;
@ -257,8 +265,6 @@ class TexArray extends TexNode {
$i++;
} else {
// Start the style indicator in cases like \textstyle abc
$mmlStyle = new MMLmstyle( "", $styleArguments );
$fullRenderedArray .= $mmlStyle->getStart();
$mmlStyles[] = $mmlStyle->getEnd();
}
@ -280,6 +286,10 @@ class TexArray extends TexNode {
foreach ( array_reverse( $mmlStyles ) as $mmlStyleEnd ) {
$fullRenderedArray .= $mmlStyleEnd;
}
if ( $this->curly && count( $this->getArgs() ) > 1 ) {
$mmlRow = new MMLmrow();
return $mmlRow->encapsulateRaw( $fullRenderedArray );
}
return $fullRenderedArray;
}
@ -340,7 +350,7 @@ class TexArray extends TexNode {
if ( isset( $this->args[0] ) && count( $this->args ) == 1 ) {
return $this->args[0]->inCurlies();
} else {
return '{' . $this->render() . '}';
return '{' . parent::render() . '}';
}
}
@ -455,4 +465,15 @@ class TexArray extends TexNode {
}
}
public function render() {
if ( $this->curly ) {
return $this->inCurlies();
}
return parent::render();
}
public function isCurly(): bool {
return $this->curly;
}
}

查看文件

@ -204,4 +204,9 @@ class TexNode {
return false;
}
public function isCurly(): bool {
return false;
}
}

查看文件

@ -11,7 +11,6 @@ use MediaWiki\Extension\Math\WikiTexVC\Nodes\Box;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Big;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\ChemFun2u;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\ChemWord;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Declh;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Dollar;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ;
@ -462,14 +461,14 @@ class Parser {
private function peg_f26($b, $r) { return new Big($b, $r); }
private function peg_f27($b) { return new Big($b, "]"); }
private function peg_f28($l, $e, $r) {return new Lr($l, $r, ParserUtil::lst2arr($e)); }
private function peg_f29($name, $e, $l) { return new Fun2sq($name, new Curly(ParserUtil::lst2arr($e)), $l); }
private function peg_f29($name, $e, $l) { return new Fun2sq($name, ParserUtil::lst2arr($e, true), $l); }
private function peg_f30($name, $l) { return new Fun1($name, $l); }
private function peg_f31($name, $l) {return new Fun1nb($name, $l); }
private function peg_f32($name, $l) { return new Mhchem($name, $l); }
private function peg_f33($name, $l1, $l2) { return new Fun2($name, $l1, $l2); }
private function peg_f34($name, $l1, $l2, $l3, $l4) { return new Fun4($name, $l1, $l2, $l3, $l4); }
private function peg_f35($name, $l1, $l2) { return new Fun2nb($name, $l1, $l2); }
private function peg_f36($e) { return new Curly(ParserUtil::lst2arr($e)); }
private function peg_f36($e) { return ParserUtil::lst2arr($e, true); }
private function peg_f37($e1, $name, $e2) { return new Infix($name, ParserUtil::lst2arr($e1), ParserUtil::lst2arr($e2)); }
private function peg_f38($m) { return new Matrix("matrix", ParserUtil::lst2arr($m)); }
private function peg_f39($m) { return new Matrix("pmatrix", ParserUtil::lst2arr($m)); }
@ -504,8 +503,8 @@ class Parser {
private function peg_f57($e, $l) { return $l; }
private function peg_f58($e, $tail) { return new TexArray($e, $tail); }
private function peg_f59() { return $this->text(); }
private function peg_f60($cs) { return new Curly(new TexArray(new Literal($cs))); }
private function peg_f61($num) { return new Curly(new TexArray(new Literal($num))); }
private function peg_f60($cs) { return TexArray::newCurly(new Literal($cs)); }
private function peg_f61($num) { return TexArray::newCurly(new Literal($num)); }
private function peg_f62($p, $s) { return new TexArray($p,new TexArray(new Literal(" "),$s)); }
private function peg_f63($p) { return new TexArray($p,new TexArray()); }
private function peg_f64($m) { return new Literal($m); }
@ -516,9 +515,9 @@ class Parser {
private function peg_f69() { return new Literal(""); }
private function peg_f70($m) { return $m;}
private function peg_f71($c) { return new Literal($c); }
private function peg_f72($c) { return new Curly(new TexArray($c)); }
private function peg_f72($c) { return TexArray::newCurly($c); }
private function peg_f73($c) { return new Dollar(ParserUtil::lst2arr($c)); }
private function peg_f74($e) { return new Curly(new TexArray(new Literal($e))); }
private function peg_f74($e) { return TexArray::newCurly(new Literal($e)); }
private function peg_f75($a, $b) { return new ChemWord(new Literal($a), new Literal($b)); }
private function peg_f76($a, $b) { return new ChemWord(new Literal($a), $b); }
private function peg_f77($a, $b) { return new ChemWord(new Literal($a), new Dollar(ParserUtil::lst2arr($b))); }

查看文件

@ -10,10 +10,11 @@ class ParserUtil {
/**
* @param TexArray|null $l
* @param bool $curly
* @return TexArray
*/
public static function lst2arr( $l ) {
$arr = new TexArray();
public static function lst2arr( $l, $curly = false ) {
$arr = $curly ? TexArray::newCurly() : new TexArray();
while ( $l !== null ) {
$first = $l->first();

查看文件

@ -143,7 +143,7 @@ lit
/ b:BIG SQ_CLOSE { return new Big($b, "]"); }
/ l:left e:expr r:right {return new Lr($l, $r, ParserUtil::lst2arr($e)); }
/ name:FUN_AR1opt e:expr_nosqc SQ_CLOSE l:lit /* must be before FUN_AR1 */
{ return new Fun2sq($name, new Curly(ParserUtil::lst2arr($e)), $l); }
{ return new Fun2sq($name, ParserUtil::lst2arr($e, true), $l); }
/ name:FUN_AR1 l:lit { return new Fun1($name, $l); }
/ name:FUN_AR1nb l:lit {return new Fun1nb($name, $l); }
/ name:FUN_MHCHEM l:chem_lit { return new Mhchem($name, $l); }
@ -152,7 +152,7 @@ lit
/ name:FUN_AR2nb l1:lit l2:lit { return new Fun2nb($name, $l1, $l2); }
/ BOX
/ CURLY_OPEN e:expr CURLY_CLOSE
{ return new Curly(ParserUtil::lst2arr($e)); }
{ return ParserUtil::lst2arr($e, true); }
/ CURLY_OPEN e1:ne_expr name:FUN_INFIX e2:ne_expr CURLY_CLOSE
{ return new Infix($name, ParserUtil::lst2arr($e1), ParserUtil::lst2arr($e2)); }
/ BEGIN_MATRIX m:(array/matrix) END_MATRIX
@ -222,7 +222,7 @@ line
column_spec
= CURLY_OPEN cs:(one_col+ { return $this->text(); }) CURLY_CLOSE
{ return new Curly(new TexArray(new Literal($cs))); }
{ return TexArray::newCurly(new Literal($cs)); }
one_col
= [lrc] _
@ -237,7 +237,7 @@ one_col
alignat_spec
= CURLY_OPEN num:([0-9]+ { return $this->text(); }) _ CURLY_CLOSE
{ return new Curly(new TexArray(new Literal($num))); }
{ return TexArray::newCurly(new Literal($num)); }
opt_pos
= "[" _ [tcb] _ "]" _
@ -249,7 +249,7 @@ opt_pos
chem_lit
= CURLY_OPEN e:chem_sentence CURLY_CLOSE { return new Curly(ParserUtil::lst2arr($e)); }
= CURLY_OPEN e:chem_sentence CURLY_CLOSE { return ParserUtil::lst2arr($e, true); }
chem_sentence =
_ p:chem_phrase " " s:chem_sentence { return new TexArray($p,new TexArray(new Literal(" "),$s)); } /
@ -275,14 +275,14 @@ chem_char =
chem_char_nl =
m:chem_script { return $m;} /
CURLY_OPEN c:chem_text CURLY_CLOSE { return new Curly(new TexArray($c)); } /
CURLY_OPEN c:chem_text CURLY_CLOSE { return TexArray::newCurly($c); } /
BEGIN_MATH c:expr END_MATH { return new Dollar(ParserUtil::lst2arr($c)); }/
name:CHEM_BONDI l:chem_bond { return new Fun1($name, $l); } /
m:chem_macro { return $m; } /
c:CHEM_NONLETTER { return new Literal($c); }
chem_bond
= CURLY_OPEN e:CHEM_BOND_TYPE CURLY_CLOSE { return new Curly(new TexArray(new Literal($e))); }
= CURLY_OPEN e:CHEM_BOND_TYPE CURLY_CLOSE { return TexArray::newCurly(new Literal($e)); }
chem_script =
a:CHEM_SUPERSUB b:CHEM_SCRIPT_FOLLOW { return new ChemWord(new Literal($a), new Literal($b)); } /

查看文件

@ -2,77 +2,53 @@
namespace MediaWiki\Extension\Math\Tests\WikiTexVC\Nodes;
use ArgumentCountError;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Literal;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexNode;
use MediaWikiUnitTestCase;
use RuntimeException;
use TypeError;
/**
* @covers \MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly
* @covers \MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray
*/
class CurlyTest extends MediaWikiUnitTestCase {
public function testEmptyDollar() {
$this->expectException( ArgumentCountError::class );
new Curly();
throw new ArgumentCountError( 'Should not create an empty curly' );
}
public function testOneArgumentCurly() {
$this->expectException( ArgumentCountError::class );
new Curly( new TexArray( new TexNode( 'a' ) ), new TexArray( new TexNode( 'b' ) ) );
throw new ArgumentCountError( 'Should not create a curly with more than one argument' );
}
public function testIncorrectTypeCurly() {
$this->expectException( TypeError::class );
new Curly( new TexNode() );
throw new RuntimeException( 'Should not create a curly with incorrect type' );
}
public function testRenderTexCurly() {
$curly = new Curly( new TexArray() );
$curly = TexArray::newCurly();
$this->assertEquals( '{}', $curly->render(), 'Should render a curly with empty tex array' );
}
public function testRenderListCurly() {
$curly = new Curly( new TexArray(
new Literal( 'hello' ),
new Literal( ' ' ),
new Literal( 'world' )
) );
$curly = TexArray::newCurly(
new Literal( 'hello' ),
new Literal( ' ' ),
new Literal( 'world' )
);
$this->assertEquals( '{hello world}', $curly->render(), 'Should render a list' );
}
public function testGetters() {
$curly = new Curly( new TexArray( new Literal( 'b' ) ) );
$curly = TexArray::newCurly( new Literal( 'b' ) );
$this->assertNotEmpty( $curly->getArgs() );
$this->assertNotEmpty( $curly->getArg() );
}
public function testNoExtraCurliesDQ() {
$dq = new DQ( new Literal( 'a' ),
new Curly( new TexArray( new Literal( 'b' ) ) ) );
TexArray::newCurly( new Literal( 'b' ) ) );
$this->assertEquals( 'a_{b}', $dq->render(), 'Should not create extra curlies from dq' );
}
public function testNoExtraCurliesCurly() {
$curly = new Curly( new TexArray( new Literal( 'a' ) ) );
$curly = TexArray::newCurly( new Literal( 'a' ) );
$this->assertEquals( '{a}', $curly->inCurlies(), 'Should not create extra curlies from curly' );
}
public function testExtractIdentifierModsCurly() {
$curly = new Curly( new TexArray( new Literal( 'b' ) ) );
$curly = TexArray::newCurly( new Literal( 'b' ) );
$this->assertEquals( 'b', $curly->getModIdent(), 'Should extract identifier modifications' );
}
public function testExtractSubscirpts() {
$curly = new Curly( new TexArray( new Literal( 'b' ) ) );
$curly = TexArray::newCurly( new Literal( 'b' ) );
$this->assertEquals( 'b', $curly->extractSubscripts(), 'Should extract subscripts' );
}
}

查看文件

@ -4,7 +4,6 @@ namespace MediaWiki\Extension\Math\Tests\WikiTexVC\Nodes;
use ArgumentCountError;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Literal;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray;
@ -53,7 +52,7 @@ class DQTest extends MediaWikiUnitTestCase {
}
public function testRenderEmptyDq() {
$dq = new DQ( new Curly( new TexArray() ), new Literal( 'b' ) );
$dq = new DQ( TexArray::newCurly(), new Literal( 'b' ) );
$this->assertStringContainsString( ( new MMLmrow() )->getEmpty(), $dq->renderMML() );
}

查看文件

@ -4,7 +4,6 @@ namespace MediaWiki\Extension\Math\Tests\WikiTexVC\Nodes;
use ArgumentCountError;
use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\FQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Literal;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray;
@ -47,8 +46,10 @@ class FQTest extends MediaWikiUnitTestCase {
}
public function testRenderEmptyFq() {
$fq = new FQ( new Curly( new TexArray() ), new Literal( 'b' ), new Literal( 'c' ) );
$this->assertStringContainsString( ( new MMLmrow() )->getEmpty(), $fq->renderMML() );
$fq = new FQ( TexArray::newCurly(), new Literal( 'b' ), new Literal( 'c' ) );
$result = $fq->renderMML();
$this->assertStringContainsString( 'msubsup', $result );
$this->assertStringContainsString( ( new MMLmrow() )->getEmpty(), $result );
}
public function testLatin() {

查看文件

@ -3,7 +3,6 @@
namespace MediaWiki\Extension\Math\Tests\WikiTexVC\Nodes;
use ArgumentCountError;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Curly;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\FQ;
use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun1;
@ -108,28 +107,28 @@ class Fun1Test extends MediaWikiUnitTestCase {
}
public function testMathRmCurly() {
$f = new Fun1( '\\mathrm', new Curly( new TexArray(
$f = new Fun1( '\\mathrm', TexArray::newCurly(
new Literal( 'a' ),
new Literal( 'b' ),
) ) );
) );
$rendering = $f->renderMML();
preg_match_all( '/mathvariant="normal"/', $rendering, $matches );
$this->assertCount( 2, $matches[0] );
}
public function testMathRmDq() {
$f = new Fun1( '\\mathrm', new Curly( new TexArray(
$f = new Fun1( '\\mathrm', TexArray::newCurly(
new DQ( new Literal( 'a' ), new Literal( 'b' ) )
) ) );
) );
$rendering = $f->renderMML();
preg_match_all( '/mathvariant="normal"/', $rendering, $matches );
$this->assertCount( 2, $matches[0] );
}
public function testMathRmFq() {
$f = new Fun1( '\\mathrm', new Curly( new TexArray(
$f = new Fun1( '\\mathrm', TexArray::newCurly(
new FQ( new Literal( 'a' ), new Literal( 'b' ), new Literal( 'c' ) )
) ) );
) );
$rendering = $f->renderMML();
preg_match_all( '/mathvariant="normal"/', $rendering, $matches );
$this->assertCount( 2, $matches[0] );