package Ġpi ac enti . dsl maker Ċ Ċ import Ġpi ac enti . dsl maker . ab straction . Production Step Ċ import Ġpi ac enti . dsl maker . errors . Parser Exception Ċ import Ġpi ac enti . dsl maker . interfaces . Grammar Inventory Ċ import Ġpi ac enti . dsl maker . structures . Expression Ċ import Ġpi ac enti . dsl maker . structures . Grammar Ċ import Ġpi ac enti . dsl maker . structures . Production Ċ import Ġkotlin . test .* Ċ Ċ infix Ġfun ĠAny ?. validate Equals ( other : ĠAny ) Ġ{ ĊĠĠĠ ĠassertEquals ( other , Ġthis ) Ċ } Ċ Ċ object ĠNumber Expression Tokens Ġ: ĠGram mar Inventory Ġ{ ĊĠĠĠ Ġoverride Ġval Ġtokens Ġ= Ġmutable ListOf < Production Step >() ĊĠĠĠ Ġoverride Ġval Ġproduction s Ġ= Ġmutable ListOf < Production Step >() ĊĠĠĠ Ġval Ġnumber Ġ= Ġcreate Token (" number ", Ġ"\\ d +") ĊĠĠĠ Ġval Ġoperation Ġ= Ġcreate Token (" operation ", Ġ"\\ + |- | \\ * | /") ĊĠĠĠ Ġval ĠOper n Par Ġ= Ġcreate Token (" Oper n Par ", Ġ"\\ (" ) ĊĠĠĠ Ġval ĠClose Par Ġ= Ġcreate Token (" Close Par ", Ġ"\\ )") ĊĠĠĠ Ġval ĠNUMBER Ġ= Ġcreate Production (" NUMBER ") ĊĠĠĠ Ġval ĠEXPRESS ION Ġ= Ġcreate Production (" EXPRESSION ") ĊĠĠĠ Ġval ĠOPER ATION Ġ= Ġcreate Production (" OPERATION ") ĊĠĠĠ Ġval ĠOP Ġ= Ġcreate Production (" OP ") ĊĠĠĠ Ġval ĠCP Ġ= Ġcreate Production (" CP ") Ċ Ċ } Ċ Ċ class ĠNumber Expression Grammar ( root : ĠProduction Step , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnumber Expressions Tokens : ĠNumber Expression Tokens Ġ= ĠNumber Expression Tokens ) Ġ: ĠGram mar < Number Expression Tokens >( ĊĠĠĠĠĠĠĠ Ġroot , Ġnumber Expressions Tokens ) Ġ{ ĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġproduction s [ Number Expression Tokens . OP ] Ġ= ĠProduction ( null , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExpression ( Number Expression Tokens . Oper n Par )) ĊĠĠĠĠĠĠĠ Ġproduction s [ Number Expression Tokens . CP ] Ġ= ĠProduction ( null , ĠExpression ( Number Expression Tokens . Close Par )) ĊĠĠĠĠĠĠĠ Ġproduction s [ Number Expression Tokens . NUMBER ] Ġ= ĠProduction ( null , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExpression ( Number Expression Tokens . number )) ĊĠĠĠĠĠĠĠ Ġproduction s [ Number Expression Tokens . OPERATION ] Ġ= ĠProduction ( null , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExpression ( Number Expression Tokens . operation )) ĊĠĠĠĠĠĠĠ Ġproduction s [ Number Expression Tokens . EXPRESSION ] Ġ= ĠProduction ( null , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExpression ( Number Expression Tokens . Oper n Par , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠNumber Expression Tokens . EXPRESSION , ĠNumber Expression Tokens . Close Par ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExpression ( Number Expression Tokens . NUMBER , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠNumber Expression Tokens . OPERATION , ĠNumber Expression Tokens . EXPRESSION ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExpression ( Number Expression Tokens . NUMBER )) ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠCreated Ġby ĠPi ac enti Ġon Ġ 4 / 1 2 / 2 0 1 6 .*/ Ċ class ĠSimple Generic Parser Test Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġresult Ġ= Ġ"" ĊĠĠĠ Ġlateinit Ġvar Ġgrammar : ĠNumber Expression Grammar ĊĠĠĠ Ġlateinit Ġvar Ġparser : ĠGeneric Parser < Number Expression Tokens > ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġparser 2 : ĠGeneric Parser 2 < Number Expression Tokens > ĊĊĠĠĠ Ġ@ Before Test ĊĠĠĠ Ġfun Ġsetup () Ġ{ ĊĠĠĠĠĠĠĠ Ġgrammar Ġ= ĠNumber Expression Grammar ( Number Expression Tokens . EXPRESSION ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġproduction s [ Number Expression Tokens . EXPRESSION ] !!. action Ġ= Ġ{ Ġdata Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult Ġ= Ġdata . match ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġparser Ġ= ĠGeneric Parser ( grammar ) ĊĠĠĠĠĠĠĠ Ġparser 2 Ġ= ĠGeneric Parser 2 ( grammar ) ĊĠĠĠĠĠĠĠ Ġresult Ġ= Ġ"" ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ parse _ if _ ent ire _ text _ match () Ġ{ ĊĠĠĠĠĠĠĠ Ġparser . parse (" 5 + 7 - 2 ") ĊĠĠĠĠĠĠĠ Ġresult Ġvalidate Equals Ġ" 5 + 7 - 2 " ĊĠĠĠĠĠĠĠ Ġparser . parse (" 7 - 2 * 5 ") ĊĠĠĠĠĠĠĠ Ġresult Ġvalidate Equals Ġ" 7 - 2 * 5 " ĊĠĠĠ Ġ} ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ parse _ full _ usage (){ ĊĠĠĠĠĠĠĠ Ġval Ġresult = parser 2 . parse ("( 4 + 2 )", Ġtrue ) ĊĠĠĠĠĠĠĠ Ġresult . to DOT Graph () ĊĠĠĠĠĠĠĠ Ġresult . tree ToString () Ġvalidate Equals Ġ""" ĊĠĠĠĠĠĠĠĠĠĠĠ ĠEXPRESS ION : Ġ( 4 + 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶľâĶĢâĶĢ ĠOper n Par : Ġ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶľâĶĢâĶĢ ĠEXPRESS ION : Ġ 4 + 2 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶľâĶĢâĶĢ ĠNUMBER : Ġ 4 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶĤ ĠĠ ĠâĶĶâĶĢâĶĢ Ġnumber : Ġ 4 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶľâĶĢâĶĢ ĠOPER ATION : Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶĤ ĠĠ ĠâĶĶâĶĢâĶĢ Ġoperation : Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶĶâĶĢâĶĢ ĠEXPRESS ION : Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠĠĠĠĠ ĠâĶĶâĶĢâĶĢ ĠNUMBER : Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠĠĠĠĠĠĠĠĠ ĠâĶĶâĶĢâĶĢ Ġnumber : Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĶâĶĢâĶĢ ĠClose Par : Ġ) ĊĠĠĠĠĠĠĠ Ġ""" . trim Indent (). trim () ĊĠĠĠ Ġ} ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ parse _ if _ ent ire _ text _ match 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġparser 2 . parse (" 7 - 2 * 5 ") ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġparser 2 . parse (" 5 + 7 - 2 ") ĊĠĠĠĠĠĠĠ Ġresult . tree ToString () Ġvalidate Equals Ġ""" ĊĠĠĠĠĠĠĠ ĠEXPRESS ION : Ġ 5 + 7 - 2 ĊĠĠĠĠĠĠĠ ĠâĶľâĶĢâĶĢ ĠNUMBER : Ġ 5 ĊĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶĶâĶĢâĶĢ Ġnumber : Ġ 5 ĊĠĠĠĠĠĠĠ ĠâĶľâĶĢâĶĢ ĠOPER ATION : Ġ+ ĊĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶĶâĶĢâĶĢ Ġoperation : Ġ+ ĊĠĠĠĠĠĠĠ ĠâĶĶâĶĢâĶĢ ĠEXPRESS ION : Ġ 7 - 2 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶľâĶĢâĶĢ ĠNUMBER : Ġ 7 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶĶâĶĢâĶĢ Ġnumber : Ġ 7 ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶľâĶĢâĶĢ ĠOPER ATION : Ġ- ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĤ ĠĠ ĠâĶĶâĶĢâĶĢ Ġoperation : Ġ- ĊĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĶâĶĢâĶĢ ĠEXPRESS ION : Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĶâĶĢâĶĢ ĠNUMBER : Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠâĶĶâĶĢâĶĢ Ġnumber : Ġ 2 ĊĠĠĠĠĠĠĠ Ġ""" . trim Indent (). trim () ĊĠĠĠ Ġ} ĊĠĠĠ Ġ@ Ignore ĊĠĠĠ Ġ@ Test ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ/* TODO Ġneed Ġto Ġaddress Ġthis Ġproblem . ĠMight Ġbe Ġable Ġto Ġmodify Ġthe Ġexpression Ġalgorithm Ġto Ġinstead Ġof Ġpassing Ġdata ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġto Ġeach Ġmethod Ġcall , Ġto Ġhold Ġa Ġseparate Ġstack Ġvariables Ġthat Ġwill Ġcontain Ġthe Ġarguments Ġpotentially Ġincreasing Ġd ram atically ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġhow Ġdeep Ġyou Ġcan Ġgo Ġwith Ġthe Ġalgorithm Ġmay Ġalso Ġneed Ġto Ġexternal ize Ġany Ġvariable Ġdefined Ġoutside Ġthe Ġloop Ġclosure ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġsince Ġthey Ġare Ġcaptured Ġby Ġit . ĠThis Ġmeans Ġno Ġvariables Ġare Ġdefined Ġoutside Ġof Ġthose Ġmethods Ġand Ġno Ġparameters Ġare Ġpassed ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġand Ġinstead Ġwe Ġmanage Ġeverything Ġwith Ġglobal Ġclass Ġvariables ĊĠĠĠĠĠĠĠĠĠĠĠĠ ĠOther Ġoptions Ġmay Ġalso Ġbe Ġneeded Ġsince Ġthe Ġtests Ġbel low Ġprove Ġthat Ġyou Ġcan Ġonly ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġgo Ġas Ġdeep Ġas Ġabout Ġ 1 0 0 0 0 0 . ĠDefault Ġjava Ġstack Ġis Ġof Ġ 4 0 0 k . ĠUsing Ġwhile Ġloops Ġto Ġsimulate ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġthe Ġrecursion Ġmay Ġbe Ġan Ġoption Ġalthough Ġa Ġdifficult Ġone ĊĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġ- X ss 6 1 2 8 Ġincreases Ġthe Ġthread Ġstack Ġsize Ġso Ġthat Ġthis Ġtest Ġpasses ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġbut Ġnot Ġoptimal Ġsince Ġit Ġchanges Ġdefault Ġstack Ġsize Ġfor Ġevery Ġnew Ġthread ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhich Ġincreases Ġmemory Ġusage Ġoverall . ĠIt Ġalso Ġdoesn 't Ġsolve Ġthe Ġproblem Ġfor Ġjavascript */ ĊĠĠĠ Ġfun Ġshould _ not _ cause _ stack _ overflow () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtext Ġ= Ġ" 5 + 7 " Ġ+ Ġ(" - 2 + 7 " Ġ* Ġ 1 0 0 0 ) ĊĠĠĠĠĠĠĠ Ġparser . parse ( text , Ġtrue ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ not _ cause _ stack _ overflow 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtext Ġ= Ġ" 5 + 7 " Ġ+ Ġ(" - 2 + 7 " Ġ* Ġ 1 0 0 0 ) ĊĠĠĠĠĠĠĠ Ġparser 2 . parse ( text , Ġtrue ) ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ fail _ if _ not _ all _ match _ and _ flag _ s ays _ it _ should () Ġ{ ĊĠĠĠĠĠĠĠ Ġparser . parse (" 5 + 7 - 2 ! @ #$ % ") ĊĠĠĠĠĠĠĠ Ġresult Ġvalidate Equals Ġ" 5 + 7 - 2 " ĊĠĠĠĠĠĠĠ Ġassert Fails With < Parser Exception > Ġ{ Ġparser . parse (" 5 + 7 - 2 ! @ #$ %", Ġtrue ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ fail _ if _ not _ all _ match _ and _ flag _ s ays _ it _ should 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult = parser 2 . parse (" 5 + 7 - 2 ! @ #$ % ") ĊĠĠĠĠĠĠĠ Ġresult . text Ġvalidate Equals Ġ" 5 + 7 - 2 " ĊĠĠĠĠĠĠĠ Ġassert Fails With < Parser Exception > Ġ{ Ġparser . parse (" 5 + 7 - 2 ! @ #$ %", Ġtrue ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ be _ able _ to _ find _ in _ text () Ġ{ ĊĠĠĠĠĠĠĠ Ġparser . parse Find (" ! @ #$ % 5 + 7 - 2 ") ĊĠĠĠĠĠĠĠ Ġresult Ġvalidate Equals Ġ" 5 + 7 - 2 " ĊĠĠĠ Ġ} ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ be _ able _ to _ find _ in _ text 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresult = parser 2 . parse Find (" ! @ #$ % 5 + 7 - 2 ") ĊĠĠĠĠĠĠĠ Ġresult . first (). text Ġvalidate Equals Ġ" 5 + 7 - 2 " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġparse Find _ should _ be _ perform ant () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstart Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 .. 5 0 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparser . parse Find (" ! @ #$ % 5 + 7 - 2 ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġend Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġval Ġdiff Ġ= Ġend Ġ- Ġstart ĊĠĠĠĠĠĠĠ ĠassertTrue ( diff Ġ/ Ġ 1 0 0 0 Ġ< Ġ 2 . 0 ) ĊĠĠĠĠĠĠĠ Ġprintln ( diff ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġparse Find _ should _ be _ perform ant 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstart Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 .. 5 0 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparser 2 . parse Find (" ! @ #$ % 5 + 7 - 2 ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġend Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġval Ġdiff Ġ= Ġend Ġ- Ġstart ĊĠĠĠĠĠĠĠ ĠassertTrue ( diff Ġ/ Ġ 1 0 0 0 Ġ< Ġ 2 . 0 ) ĊĠĠĠĠĠĠĠ Ġprintln ( diff ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ be _ perform ant () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstart Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 .. 3 0 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparser . parse (" 7 - 2 * 5 ", Ġtrue ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġend Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġval Ġdiff Ġ= Ġend Ġ- Ġstart ĊĠĠĠĠĠĠĠ ĠassertTrue ( diff Ġ/ Ġ 1 0 0 0 Ġ< Ġ 2 . 0 ) ĊĠĠĠĠĠĠĠ Ġprintln ( diff ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġshould _ be _ perform ant _ 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstart Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 .. 3 0 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparser 2 . parse (" 7 - 2 * 5 ", Ġtrue ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġend Ġ= ĠgetCurrent TimeIn Milli Seconds () ĊĠĠĠĠĠĠĠ Ġval Ġdiff Ġ= Ġend Ġ- Ġstart ĊĠĠĠĠĠĠĠ ĠassertTrue ( diff Ġ/ Ġ 1 0 0 0 Ġ< Ġ 2 . 0 ) ĊĠĠĠĠĠĠĠ Ġprintln ( diff ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġglobal _ regex _ should _ work () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġglobal Dot Regex String Ġ= Ġ"( ? s ) \" (. + ? )\ "" . generic Regex () ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġglobal Dot Regex String . find (""" Ġstuff Ġ" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġmore " ĊĠĠĠĠĠĠĠ Ġ"" ") ĊĠĠĠĠĠĠĠ Ġassert Not Equals ( null , Ġresult ) ĊĠĠĠ Ġ} Ċ } ĊĊ