** Inhaltsverzeichnis ** Es dauerte lange, bis dieses Muster die Struktur verstand. es ist schwierig.
Ist das Muster, für das Sie einen Syntaxbaum generieren möchten? Dieses Muster drückt eine Gruppe vom Start-Tag bis zum End-Tag mit einem Objekt aus. Composite Es ist, als würde man anhand eines Musters analysieren und es als Gruppe verarbeiten.
Definieren Sie für eine Sprache einen grammatikalischen Ausdruck und einen Interpreter, der ihn zur Interpretation des Satzes verwendet.
-AbstractExpression Abstrakte Klasse für alle Knoten -TerminalExpression Eine Klasse, die das Ende darstellt -NonterminalExpression Eine Klasse, die etwas anderes als das Ende ausdrückt ・ Kontext Kontext / Situation ・ Client-Benutzer
Implementieren Sie ein Beispielprogramm, das Daten für vier Regeln mit hierarchischer Struktur verarbeitet. <+> ~ </ +> Addition <-> ~ </-> Subtraktion <\ *> ~ </ \ *> Multiplikation </> ~ /> Teilen
Zielproben-Daten.xml
<+>
1
<->
2
3
4
5
6
<*>
7
8
</*>
9
</->
10
11
</>
12
4
<//>
</+>
Wenn Sie die obigen Beispieldaten in eine vertraute Form formatieren, sind dies "1 + (2 - 3 - 4 - 5 - 6 - (7 * 8) -9) + 10 + 11 + (12/4)" und die Lösung `` `-56``` ist der erwartete Wert.
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()
}
}
}
}
}
Das Element, das das Ende des Baums darstellt. In diesen Beispieldaten ist dies die Nummer.
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"
}
}
Das Element, das der Baum verzweigt. In diesen Beispieldaten entsprechen <+> und <-> diesen.
Rechenunterricht
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
}
Zusatzklasse
PlusNonterminalExpression.kt
package interpreter
/**
*Zusatz(<+> ~ </+>)
*/
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"
}
}
Subtraktionsklasse
MinusNonterminalExpression.kt
package interpreter
/**
*Subtraktion(<-> ~ </->)
*/
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"
}
}
Multiplikationsklasse
MultiplicationExpression.kt
package interpreter
/**
*Multiplikation(<*> ~ </"*>)
*/
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"
}
}
Divisionsklasse
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() //Standard.nextToken()Anruf
}
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]]
Die Formel und Lösung waren wie erwartet.
Recommended Posts