** Table des matières ** Ce modèle a mis du temps à comprendre la structure. c'est difficile.
Le modèle pour lequel vous souhaitez générer une arborescence de syntaxe? Ce modèle exprime un groupe de la balise de début à la balise de fin avec un objet. Composite C'est comme analyser en utilisant un modèle et le traiter en groupe.
Pour une langue, définissez une expression grammaticale et un interprète qui l'utilise pour interpréter la phrase.
-AbstractExpression Classe abstraite pour tous les nœuds -TerminalExpression Une classe qui représente la fin -NonterminalExpression Une classe qui exprime autre chose que la fin ・ Contexte Contexte / Situation ・ Utilisateur client
Implémentez un exemple de programme qui traite les données de quatre règles ayant une structure hiérarchique. <+> ~ </ +> Ajout <-> ~ </-> Soustraction <\ *> ~ </ \ *> Multiplication </> ~ </ /> Diviser
Exemple de données cibles.xml
<+>
1
<->
2
3
4
5
6
<*>
7
8
</*>
9
</->
10
11
</>
12
4
<//>
</+>
Si vous formatez les exemples de données ci-dessus dans une forme familière, ce sera 1 + (2 --3 --4 --- 5 --6- (7 * 8) -9) + 10 + 11 + (12/4)
-56``` est la valeur attendue.
Expression.kt
package interpreter
interface Expression {
enum class Operator(val startTag: String, val endTag: String) {
Plus("<+>", "</+>"),
Minus("<->", "</->"),
Multiplication("<*>", "</*>"),
Divide("</>", "<//>"),
}
fun interpret(context: Context): Int
companion object {
fun getExpression(token: String?): Expression? {
return when (token) {
Operator.Plus.startTag -> {
PlusNonterminalExpression()
}
Operator.Minus.startTag -> {
MinusNonterminalExpression()
}
Operator.Multiplication.startTag -> {
MultiplicationExpression()
}
Operator.Divide.startTag -> {
DivideExpression()
}
Operator.Plus.endTag,
Operator.Minus.endTag,
Operator.Multiplication.endTag,
Operator.Divide.endTag -> {
null
}
else -> {
TerminalExpression()
}
}
}
}
}
L'élément qui est la fin de l'arbre. Dans cet exemple de données, c'est le nombre.
TerminalExpression.kt
package interpreter
class TerminalExpression: Expression {
private var saveToken: String? = null
override fun interpret(context: Context): Int {
saveToken = context.token
context.nextToken()
return Integer.parseInt(saveToken ?: "0")
}
override fun toString(): String {
return saveToken ?: "0"
}
}
L'élément que l'arbre ramifie. Dans cet exemple de données, <+> et <-> lui correspondent.
Classe arithmétique
CalcExpression.kt
package interpreter
import java.util.ArrayList
abstract class CalcExpression: Expression {
protected val numList = ArrayList<Int>()
protected val list = ArrayList<Expression>()
override fun interpret(context: Context): Int {
context.nextToken()
loop@ while (!context.isEnd) {
val childExpressions = Expression.getExpression(context.token)
if (childExpressions == null) {
context.nextToken()
break@loop
} else {
numList.add(childExpressions.interpret(context))
list.add(childExpressions)
}
}
return calc()
}
abstract fun calc(): Int
abstract override fun toString(): String
}
Classe d'addition
PlusNonterminalExpression.kt
package interpreter
/**
*une addition(<+> ~ </+>)
*/
class PlusNonterminalExpression: CalcExpression() {
override fun calc(): Int {
var result = numList.first().toInt()
for (i in 1 until numList.size) {
result += numList[i]
}
return result
}
override fun toString(): String {
return "+$list"
}
}
Classe de soustraction
MinusNonterminalExpression.kt
package interpreter
/**
*soustraction(<-> ~ </->)
*/
class MinusNonterminalExpression: CalcExpression() {
override fun calc(): Int {
var result = numList.first().toInt()
for (i in 1 until numList.size) {
result -= numList[i]
}
return result
}
override fun toString(): String {
return "-$list"
}
}
Classe de multiplication
MultiplicationExpression.kt
package interpreter
/**
*multiplication(<*> ~ </"*>)
*/
class MultiplicationExpression: CalcExpression() {
override fun calc(): Int {
var result = numList.first().toInt()
for (i in 1 until numList.size) {
result *= numList[i]
}
return result
}
override fun toString(): String {
return "*$list"
}
}
Classe de division
DivideExpression.kt
package interpreter
class DivideExpression: CalcExpression() {
override fun calc(): Int {
var result = numList.first().toInt()
for (i in 1 until numList.size) {
result /= numList[i]
}
return result
}
override fun toString(): String {
return "/$list"
}
}
Context.kt
package interpreter
import java.util.*
class Context(source: String) {
private val tokens: StringTokenizer = StringTokenizer(source)
var token: String? = null
private set
val isEnd: Boolean
get() = !tokens.hasMoreElements()
init {
nextToken()
}
fun nextToken() {
var token: String? = null
if (!isEnd) {
token = tokens.nextToken() //la norme.nextToken()Appel
}
this.token = token
}
}
Main.kt
package interpreter
import interpreter.Expression.Companion.getExpression
fun main(args: Array<String>) {
val source = "<+> 1 <-> 2 3 4 5 6 <*> 7 8 </*> 9 </-> 10 11 </> 12 4 <//> </+>"
val context = Context(source)
val expression = getExpression(context.token)
println(expression?.interpret(context))
println(expression.toString())
}
[out-put]
-56
+[1, -[2, 3, 4, 5, 6, *[7, 8], 9], 10, 11, /[12, 4]]
La formule et la solution étaient comme prévu.
Recommended Posts