Feature: NeoLang

This commit is contained in:
zt515 2017-08-03 23:55:08 +08:00
parent df22d5cf53
commit d5b5755783
41 changed files with 271 additions and 133 deletions

View File

@ -30,3 +30,7 @@ compileTestKotlin {
jvmTarget = "1.8"
}
}
dependencies {
testCompile 'junit:junit:4.12'
}

View File

@ -1,15 +0,0 @@
package io.neolang.ast
import io.neolang.ast.base.NeoLangAstBaseNode
import io.neolang.ast.typed.NeoLangAstTypedNode
/**
* @author kiva
*/
class NeoLangBlockNode(ast: NeoLangAstBaseNode) : NeoLangAstTypedNode(ast) {
companion object {
fun emptyNode() :NeoLangBlockNode {
return NeoLangBlockNode(NeoLangDummyNode())
}
}
}

View File

@ -1,8 +0,0 @@
package io.neolang.ast
import io.neolang.ast.base.NeoLangAstBaseNode
/**
* @author kiva
*/
class NeoLangDummyNode : NeoLangAstBaseNode()

View File

@ -1,8 +0,0 @@
package io.neolang.ast
import io.neolang.ast.typed.NeoLangTokenTypedNode
/**
* @author kiva
*/
class NeoLangNumberNode(token: NeoLangToken) : NeoLangTokenTypedNode(token)

View File

@ -1,8 +0,0 @@
package io.neolang.ast
import io.neolang.ast.typed.NeoLangTokenTypedNode
/**
* @author kiva
*/
class NeoLangStringNode(token: NeoLangToken) : NeoLangTokenTypedNode(token)

View File

@ -1,28 +1,30 @@
package io.neolang.ast
import io.neolang.runtime.type.NeoLangValue
/**
* @author kiva
*/
class NeoLangTokenValue(val value: String) {
class NeoLangTokenValue(val value: NeoLangValue) {
override fun toString(): String {
return value
return value.asString()
}
companion object {
val COLON = NeoLangTokenValue(":")
val BRACKET_START = NeoLangTokenValue("{")
val BRACKET_END = NeoLangTokenValue("}")
val QUOTE = NeoLangTokenValue("\"")
val EOF = NeoLangTokenValue("<EOF>")
val COLON = NeoLangTokenValue(NeoLangValue(":"))
val BRACKET_START = NeoLangTokenValue(NeoLangValue("{"))
val BRACKET_END = NeoLangTokenValue(NeoLangValue("}"))
val QUOTE = NeoLangTokenValue(NeoLangValue("\""))
val EOF = NeoLangTokenValue(NeoLangValue("<EOF>"))
fun wrap(tokenText: String): NeoLangTokenValue {
return when (tokenText) {
COLON.value -> COLON
BRACKET_START.value -> BRACKET_START
BRACKET_END.value -> BRACKET_END
QUOTE.value -> QUOTE
else -> NeoLangTokenValue(tokenText)
COLON.value.asString() -> COLON
BRACKET_START.value.asString() -> BRACKET_START
BRACKET_END.value.asString() -> BRACKET_END
QUOTE.value.asString() -> QUOTE
else -> NeoLangTokenValue(NeoLangValue(tokenText))
}
}
}

View File

@ -1,11 +1,11 @@
package io.neolang.ast.typed
package io.neolang.ast.node
import io.neolang.ast.base.NeoLangAstBaseNode
/**
* @author kiva
*/
open class NeoLangAstTypedNode(val ast: NeoLangAstBaseNode) : NeoLangAstBaseNode() {
open class NeoLangAstBasedNode(val ast: NeoLangAstBaseNode) : NeoLangAstBaseNode() {
override fun toString(): String {
return "${javaClass.simpleName} { ast: $ast }"
}

View File

@ -1,11 +1,11 @@
package io.neolang.ast
package io.neolang.ast.node
import io.neolang.ast.base.NeoLangAstBaseNode
/**
* @author kiva
*/
class NeoLangAttributeNode(private val stringNode: NeoLangStringNode, private val blockNode: NeoLangBlockNode) : NeoLangAstBaseNode() {
class NeoLangAttributeNode(val stringNode: NeoLangStringNode, val blockNode: NeoLangBlockNode) : NeoLangAstBaseNode() {
override fun toString(): String {
return "NeoLangAttributeNode { stringNode: $stringNode, block: $blockNode }"

View File

@ -0,0 +1,14 @@
package io.neolang.ast.node
import io.neolang.ast.base.NeoLangAstBaseNode
/**
* @author kiva
*/
class NeoLangBlockNode(blockElement: NeoLangAstBaseNode) : NeoLangAstBasedNode(blockElement) {
companion object {
fun emptyNode() : NeoLangBlockNode {
return NeoLangBlockNode(NeoLangDummyNode())
}
}
}

View File

@ -0,0 +1,8 @@
package io.neolang.ast.node
import io.neolang.ast.base.NeoLangAstBaseNode
/**
* @author kiva
*/
class NeoLangDummyNode : NeoLangAstBaseNode()

View File

@ -1,11 +1,11 @@
package io.neolang.ast
package io.neolang.ast.node
import io.neolang.ast.base.NeoLangAstBaseNode
/**
* @author kiva
*/
class NeoLangGroupNode(private val attributes: List<NeoLangAttributeNode>) : NeoLangAstBaseNode() {
class NeoLangGroupNode(val attributes: List<NeoLangAttributeNode>) : NeoLangAstBaseNode() {
override fun toString(): String {
return "NeoLangGroupNode { attrs: $attributes }"

View File

@ -0,0 +1,8 @@
package io.neolang.ast.node
import io.neolang.ast.NeoLangToken
/**
* @author kiva
*/
class NeoLangNumberNode(token: NeoLangToken) : NeoLangTokenBasedNode(token)

View File

@ -1,4 +1,4 @@
package io.neolang.ast
package io.neolang.ast.node
import io.neolang.ast.base.NeoLangAstBaseNode
@ -6,7 +6,7 @@ import io.neolang.ast.base.NeoLangAstBaseNode
* @author kiva
*/
class NeoLangProgramNode(private val groups: List<NeoLangGroupNode>) : NeoLangAstBaseNode() {
class NeoLangProgramNode(val groups: List<NeoLangGroupNode>) : NeoLangAstBaseNode() {
override fun toString(): String {
return "NeoLangProgramNode { groups: $groups }"

View File

@ -0,0 +1,8 @@
package io.neolang.ast.node
import io.neolang.ast.NeoLangToken
/**
* @author kiva
*/
class NeoLangStringNode(token: NeoLangToken) : NeoLangTokenBasedNode(token)

View File

@ -1,13 +1,18 @@
package io.neolang.ast.typed
package io.neolang.ast.node
import io.neolang.ast.base.NeoLangAstBaseNode
import io.neolang.ast.NeoLangToken
import io.neolang.runtime.type.NeoLangValue
/**
* @author kiva
*/
open class NeoLangTokenTypedNode(val token: NeoLangToken) : NeoLangAstBaseNode() {
open class NeoLangTokenBasedNode(val token: NeoLangToken) : NeoLangAstBaseNode() {
override fun toString(): String {
return "${javaClass.simpleName} { token: $token }"
}
fun eval() :NeoLangValue {
return token.tokenValue.value
}
}

View File

@ -7,6 +7,6 @@ import io.neolang.ast.base.NeoLangAst
*/
class AstVisitor(private val ast: NeoLangAst, private val visitorCallback: IVisitorCallback) {
fun start() {
// TODO visitor
AstVisitorImpl.visitStartAst(ast, visitorCallback)
}
}

View File

@ -0,0 +1,62 @@
package io.neolang.ast.visitor
import io.neolang.ast.base.NeoLangAst
import io.neolang.ast.node.*
/**
* grammar: [
* program: group (group)*
* group: attribute (attribute)*
* attribute: ID COLON block
* block: STRING | NUMBER | (BRACKET_START group BRACKET_END)
* ]
*/
/**
* @author kiva
*/
internal object AstVisitorImpl {
fun visitProgram(ast: NeoLangProgramNode, visitorCallback: IVisitorCallback) {
visitorCallback.onStart()
ast.groups.forEach { visitGroup(it, visitorCallback) }
visitorCallback.onFinish()
}
fun visitGroup(ast: NeoLangGroupNode, visitorCallback: IVisitorCallback) {
ast.attributes.forEach {
visitAttribute(it, visitorCallback)
}
}
fun visitAttribute(ast: NeoLangAttributeNode, visitorCallback: IVisitorCallback) {
visitBlock(ast.blockNode, ast.stringNode.eval().asString(), visitorCallback)
}
fun visitBlock(ast: NeoLangBlockNode, blockName: String, visitorCallback: IVisitorCallback) {
val visitingNode = ast.ast
when (visitingNode) {
is NeoLangGroupNode -> {
// is a sub block, e.g.
// block: { sub-block: {} }
visitorCallback.onEnterContext(blockName)
AstVisitorImpl.visitGroup(visitingNode, visitorCallback)
visitorCallback.onExitContext()
}
is NeoLangStringNode -> {
// block: { node: "hello" }
visitorCallback.getCurrentContext().defineAttribute(blockName, visitingNode.eval())
}
is NeoLangNumberNode -> {
// block: { node: 123.456 }
visitorCallback.getCurrentContext().defineAttribute(blockName, visitingNode.eval())
}
}
}
fun visitStartAst(ast: NeoLangAst, visitorCallback: IVisitorCallback) {
when (ast) {
is NeoLangProgramNode -> AstVisitorImpl.visitProgram(ast, visitorCallback)
is NeoLangGroupNode -> AstVisitorImpl.visitGroup(ast, visitorCallback)
}
}
}

View File

@ -1,7 +1,18 @@
package io.neolang.ast.visitor
import io.neolang.runtime.context.NeoLangContext
/**
* @author kiva
*/
interface IVisitorCallback {
fun onStart()
fun onFinish()
fun onEnterContext(contextName: String)
fun onExitContext()
fun getCurrentContext() : NeoLangContext
}

View File

@ -1,9 +0,0 @@
package io.neolang.main
import io.neolang.ast.visitor.IVisitorCallback
/**
* @author kiva
*/
class DisplayAstVisitor : IVisitorCallback {
}

View File

@ -0,0 +1,39 @@
package io.neolang.main
import io.neolang.ast.visitor.IVisitorCallback
import io.neolang.runtime.context.NeoLangContext
import java.util.*
/**
* @author kiva
*/
class DisplayProcessVisitor : IVisitorCallback {
private val contextStack = Stack<NeoLangContext>()
override fun onStart() {
println(">>> Start")
onEnterContext("global")
}
override fun onFinish() {
while (contextStack.isNotEmpty()) {
onExitContext()
}
println(">>> Finish")
}
override fun onEnterContext(contextName: String) {
val context = NeoLangContext(contextName)
contextStack.push(context)
println(">>> Entering Context `$contextName'")
}
override fun onExitContext() {
val context = contextStack.pop()
println(">>> Exiting Context ${context.contextName}")
}
override fun getCurrentContext(): NeoLangContext {
return contextStack.peek()
}
}

View File

@ -20,12 +20,10 @@ class Main {
val programCode = readFully(it)
parser.setInputSource(programCode)
val ast = parser.parse()
val visitor = ast.visit().getVisitor(DisplayAstVisitor::class.java)
if (visitor != null) {
println("Compile `$it' -> $ast")
visitor.start()
}
println("Compile `$it'")
ast.visit()
.getVisitor(DisplayProcessVisitor::class.java)
?.start()
}
return
}

View File

@ -8,10 +8,10 @@ import java.util.*
/**
* grammar: [
* prog: group (group)*
* program: group (group)*
* group: attribute (attribute)*
* attribute: TEXT COLON block
* block: NUMBER | TEXT | (BRACKET_START group BRACKET_END)
* attribute: ID COLON block
* block: STRING | NUMBER | (BRACKET_START group BRACKET_END)
* ]
*/
@ -122,7 +122,7 @@ class NeoLangLexer {
val builder = StringBuilder()
var loop = true
while (loop && currentChar != NeoLangTokenValue.QUOTE.value[0]) {
while (loop && currentChar != NeoLangTokenValue.QUOTE.value.asString()[0]) {
// Skip escaped char
if (currentChar == '\\') {
builder.append('\\')

View File

@ -2,6 +2,7 @@ package io.neolang.parser
import io.neolang.ast.*
import io.neolang.ast.base.NeoLangAst
import io.neolang.ast.node.*
/**
* @author kiva

View File

@ -0,0 +1,8 @@
package io.neolang.runtime.context
/**
* @author kiva
*/
interface IContextMaker {
fun makeContext()
}

View File

@ -0,0 +1,18 @@
package io.neolang.runtime.context
import io.neolang.runtime.type.NeoLangValue
/**
* @author kiva
*/
class NeoLangContext(val contextName: String) {
private val attributes = mutableMapOf<String, NeoLangValue>()
fun defineAttribute(attributeName: String, attributeValue: NeoLangValue) {
attributes[attributeName] = attributeValue
}
fun getAttribute(attributeName: String) : NeoLangValue {
return attributes[attributeName] ?: NeoLangValue.UNDEFINED
}
}

View File

@ -0,0 +1,22 @@
package io.neolang.runtime.type
/**
* @author kiva
*/
class NeoLangValue(private val rawValue: Any) {
fun asString() : String {
return rawValue.toString()
}
fun asNumber() : Double {
try {
return asString().toDouble()
} catch (e: NumberFormatException) {
return 0.0
}
}
companion object {
val UNDEFINED = NeoLangValue("<undefined>")
}
}

View File

@ -1,4 +1,4 @@
package io.neoterm
package io.neolang
import io.neolang.main.Main
import org.junit.Test

View File

@ -1,25 +0,0 @@
package io.neoterm
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumentation test, which will execute on an Android device.
*
* @see [Testing documentation](http://d.android.com/tools/testing)
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
@Throws(Exception::class)
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext()
assertEquals("io.neoterm", appContext.packageName)
}
}

View File

@ -4,7 +4,7 @@ import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import io.neoterm.backend.TerminalSession
import io.neoterm.frontend.ShellParameter
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.tinyclient.BasicSessionCallback
import io.neoterm.frontend.tinyclient.BasicViewClient
import io.neoterm.utils.TerminalUtils

View File

@ -0,0 +1,6 @@
package io.neoterm.frontend.service
/**
* @author kiva
*/
class ServiceDuplicateException(serviceName: String) : RuntimeException("Service $serviceName duplicate")

View File

@ -10,9 +10,12 @@ object ServiceManager {
val THROW_WHEN_SERVICE_NOT_FOUND = true
val SERVICE_CACHE = ConcurrentHashMap<Class<out NeoService>, NeoService>()
fun registerService(serviceInterface: Class<out NeoService>) {
val service = createServiceInstance(serviceInterface)
SERVICE_CACHE.put(serviceInterface, service)
fun registerService(serviceClass: Class<out NeoService>) {
if (SERVICE_CACHE.containsKey(serviceClass)) {
throw ServiceDuplicateException(serviceClass.simpleName)
}
val service = createServiceInstance(serviceClass)
SERVICE_CACHE.put(serviceClass, service)
service.onServiceInit()
}
@ -24,7 +27,6 @@ object ServiceManager {
}
}
@Suppress("UNCHECKED_CAST")
inline fun <reified T : NeoService> getService(): T {
Log.e("NeoTerm", SERVICE_CACHE.keys.toString())
val serviceInterface = T::class.java

View File

@ -1,4 +1,4 @@
package io.neoterm.frontend
package io.neoterm.frontend.shell
import io.neoterm.backend.TerminalSession

View File

@ -1,4 +1,4 @@
package io.neoterm.frontend
package io.neoterm.frontend.shell
import android.content.Context
import io.neoterm.R

View File

@ -15,7 +15,7 @@ import android.support.v4.content.WakefulBroadcastReceiver
import io.neoterm.R
import io.neoterm.backend.EmulatorDebug
import io.neoterm.backend.TerminalSession
import io.neoterm.frontend.ShellParameter
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.ui.term.NeoTermActivity
import io.neoterm.utils.TerminalUtils
import java.util.*

View File

@ -13,7 +13,7 @@ import io.neoterm.backend.TerminalSession
import io.neoterm.customize.color.ColorSchemeManager
import io.neoterm.preference.NeoTermPath
import io.neoterm.customize.font.FontManager
import io.neoterm.frontend.ShellParameter
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.utils.FileUtils
import io.neoterm.utils.MediaUtils

View File

@ -22,14 +22,10 @@ import android.widget.Toast
import de.mrapp.android.tabswitcher.*
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.customize.color.ColorSchemeManager
import io.neoterm.customize.eks.ExtraKeysManager
import io.neoterm.customize.font.FontManager
import io.neoterm.customize.setup.BaseFileInstaller
import io.neoterm.frontend.ShellParameter
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.client.TermSessionCallback
import io.neoterm.frontend.client.TermViewClient
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.preference.NeoPermission
import io.neoterm.preference.NeoPreference
import io.neoterm.services.NeoTermService
@ -309,7 +305,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
}
private fun floatTabUp(tab: TermTab) {
Toast.makeText(this, "In Progress", Toast.LENGTH_SHORT).show()
}
private fun forceAddSystemSession() {

View File

@ -16,14 +16,13 @@ import android.widget.Toast
import io.neoterm.R
import io.neoterm.customize.script.UserScript
import io.neoterm.customize.script.UserScriptManager
import io.neoterm.frontend.ShellParameter
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.client.TermSessionCallback
import io.neoterm.preference.NeoPreference
import io.neoterm.services.NeoTermService
import io.neoterm.utils.TerminalUtils
import java.io.File
import android.content.Intent.ShortcutIconResource
import android.os.Parcelable
import io.neoterm.frontend.service.ServiceManager

View File

@ -23,6 +23,6 @@ object CrashHandler : Thread.UncaughtExceptionHandler {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("exception", e)
App.get().startActivity(intent)
Process.killProcess(Process.myPid())
defaultHandler.uncaughtException(t, e)
}
}

View File

@ -4,8 +4,8 @@ import android.content.Context
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.customize.font.FontManager
import io.neoterm.frontend.ShellParameter
import io.neoterm.frontend.ShellTermSession
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.shell.ShellTermSession
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.preference.NeoPreference
import io.neoterm.view.eks.ExtraKeysView

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha8'
classpath 'com.android.tools.build:gradle:3.0.0-alpha9'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong

View File

@ -1,6 +1,6 @@
#Mon Jul 03 20:26:42 CST 2017
#Thu Aug 03 22:06:45 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-milestone-1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-rc-1-all.zip