Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import org.antlr.v4.runtime.ANTLRFileStream
- import org.antlr.v4.runtime.CommonTokenStream
- import org.antlr.v4.runtime.tree.ParseTreeWalker
- import java.io.FileNotFoundException
- import java.io.IOException
- import java.io.PrintWriter
- import java.io.UnsupportedEncodingException
- import java.util.*
- class Generator (private val Grammar : String) : GrammarBaseListener() {
- private var rules = ArrayList<Rule>()
- private var header = ""
- private var members = ""
- private var first: MutableMap<String, MutableSet<String>> = HashMap()
- private var follow: MutableMap<String, MutableSet<String>> = HashMap()
- override fun enterStart(ctx: GrammarParser.StartContext) {
- header = ctx.HEADER().text
- header = header.substring(7, header.length - 2)
- members = ctx.MEMBERS().text
- members = members.substring(8, members.length - 3)
- }
- override fun enterRule_(ctx: GrammarParser.Rule_Context) {
- val rule = Rule()
- // trans attr -- return type
- if (ctx.RETURN_SYM() != null) {
- var ret = ctx.RETURN_SYM().toString()
- ret = ret.substring(1, ret.length - 1)
- rule.ret = ret
- }
- if (ctx.SYNTH_ATR() != null) {
- var synt = ctx.SYNTH_ATR().toString()
- synt = synt.substring(1, synt.length - 1)
- rule.synt = synt
- }
- // NON_TERM -- left part
- rule.non_term = ctx.NONTERM().toString()
- for (part in ctx.rrule()) {
- val rpart = Rpart()
- var cnt = 0
- loop@for(fulpart in part.fulrule()) {
- if(fulpart.SYNTH_ATR() != null) {
- val synth = fulpart.SYNTH_ATR().toString()
- rpart.synth.put(Integer(cnt), synth.substring(1, synth.length - 1))
- }
- if(fulpart.terms() != null) {
- val term = fulpart.terms()
- if (term.WS() != null) {
- continue@loop
- }
- if (term.SYM() != null) {
- val termd = Term(TERMS.SYM, term.SYM().text)
- rpart.terms.add(termd)
- }
- if (term.NONTERM() != null) {
- val termd = Term(TERMS.NONTERM, term.NONTERM().text)
- rpart.terms.add(termd)
- }
- if (term.TOKEN() != null) {
- val termd = Term(TERMS.TOKEN, term.TOKEN().text)
- rpart.terms.add(termd)
- }
- if (term.EPS() != null) {
- val termd = Term(TERMS.EPS, term.EPS().text)
- rpart.terms.add(termd)
- }
- cnt++
- }
- }
- rule.rparts.add(rpart)
- }
- rules.add(rule)
- }
- @Throws(IOException::class)
- fun parseGrammar() {
- val lexer = GrammarLexer(ANTLRFileStream(Grammar))
- val tokens = CommonTokenStream(lexer)
- val parser = GrammarParser(tokens)
- val tree = parser.start()
- val walker = ParseTreeWalker()
- walker.walk(this, tree)
- }
- private fun ntContainEps(nt: String): Boolean {
- return if (!first.containsKey(nt)) false else first[nt].orEmpty().contains("eps")
- }
- private fun getFirst(part: Rpart, ind: Int): MutableSet<String> {
- val ret = mutableSetOf<String>()
- val terms = part.terms
- // transform to eps?
- var maybe_eps = true
- for (i in ind until terms.size) {
- val term = terms[i]
- if (term.type === TERMS.TOKEN) {
- maybe_eps = false
- break
- } else if (term.type === TERMS.NONTERM) {
- if (!ntContainEps(term.v)) {
- maybe_eps = false
- break
- }
- }
- }
- if (maybe_eps) {
- ret.add("eps")
- }
- for (i in ind until terms.size) {
- val term = terms[i]
- if (term.type === TERMS.TOKEN) {
- ret.add(term.v)
- break
- }
- if (term.type === TERMS.NONTERM) {
- first[term.v].orEmpty().filterTo(ret) { it != "eps" }
- if (!ntContainEps(term.v)) {
- break
- }
- }
- }
- return ret
- }
- private fun calcFirst() {
- var changed = true
- while (changed) {
- changed = false
- for (rule in rules) {
- if (!first.containsKey(rule.non_term)) {
- first.put(rule.non_term.orEmpty(), HashSet())
- changed = true
- }
- for (part in rule.rparts) {
- // transform to eps?
- var maybe_eps = true
- for (term in part.terms) {
- if (term.type === TERMS.TOKEN) {
- maybe_eps = false
- break
- } else if (term.type === TERMS.NONTERM) {
- if (!ntContainEps(term.v)) {
- maybe_eps = false
- break
- }
- }
- }
- if (maybe_eps) {
- val s = first[rule.non_term]
- if (!s.orEmpty().contains("eps")) {
- s!!.add("eps")
- changed = true
- }
- }
- // cont
- for (term in part.terms) {
- val s = first[rule.non_term]
- if (term.type === TERMS.TOKEN) {
- if (!s.orEmpty().contains(term.v)) {
- s!!.add(term.v)
- changed = true
- }
- break
- } else if (term.type === TERMS.NONTERM) {
- if (!first.containsKey(term.v)) break
- for (i in first[term.v].orEmpty()) {
- if (i != "eps") {
- if (!s.orEmpty().contains(i)) {
- s!!.add(i)
- changed = true
- }
- }
- }
- if (!ntContainEps(term.v)) {
- break
- }
- }
- }
- }
- }
- }
- }
- private fun calcFollow() {
- for (i in rules.indices) {
- val rule = rules[i]
- follow.put(rule.non_term.orEmpty(), HashSet())
- if (i == 0) {
- follow[rule.non_term]!!.add("$")
- }
- }
- for (rule in rules) {
- for (part in rule.rparts) {
- val terms = part.terms
- for (i in terms.indices) {
- val term = terms[i]
- if (term.type === TERMS.NONTERM) {
- val B = term.v
- val ss = getFirst(part, i + 1)
- ss.filter { it != "eps" }.forEach {
- if(!follow.containsKey(B)) follow.put(B, HashSet())
- follow[B]!!.add(it) }
- }
- }
- }
- }
- var changed = true
- while (changed) {
- changed = false
- for (rule in rules) {
- val A = rule.non_term
- for (part in rule.rparts) {
- val terms = part.terms
- for (i in terms.indices) {
- val term = terms[i]
- if (term.type === TERMS.NONTERM) {
- val B = term.v
- val ss = getFirst(part, i + 1)
- if (ss.contains("eps")) {
- follow[A].orEmpty().map { follow[B]!!.add(it) }.filter { it }.forEach { changed = true }
- }
- }
- }
- }
- }
- }
- }
- @Throws(FileNotFoundException::class, UnsupportedEncodingException::class)
- fun generateParser() {
- calcFirst()
- calcFollow()
- val writer = PrintWriter("./src/" + Grammar + "/" + Grammar + "Parser.kt", "UTF-8")
- //writer.println("package " + Grammar)
- writer.println("import java.text.ParseException;")
- writer.println(header)
- writer.println("class " + Grammar + "Parser constructor(val lex : LexicalAnalyzer) {")
- writer.println(members)
- for (rule in rules) {
- val A = rule.non_term
- writer.println(String.format("class %sContext {", A))
- writer.println("var text = \"\"")
- if (rule.ret != null) {
- val sm = rule.ret
- writer.println(sm)
- }
- writer.println("}")
- // print function
- writer.println(String.format("@Throws (ParseException::class)"))
- if(rule.synt != null)
- writer.println(String.format("public fun %sRule(%s) : %sContext {", A, rule.synt, A))
- else
- writer.println(String.format("public fun %sRule() : %sContext {", A, A))
- writer.println(String.format("val ctx = %sContext()", A))
- writer.println("ctx.text = \"\"")
- // writer.println("val ntok = lex.token")
- writer.println(" when (lex.token) {")
- for (part in rule.rparts) {
- val ss = getFirst(part, 0)
- if (ss.contains("eps")) {
- ss += follow[A].orEmpty()
- ss.remove("eps")
- }
- var c = 0
- for (t in ss) {
- c++
- if (t !== "$") {
- writer.print(String.format("%s", t))
- } else {
- writer.println(String.format("'$'"))
- }
- if(c != ss.size)
- writer.print(", ")
- else
- writer.print(" -> ")
- }
- // print logic
- // part.terms[0].
- var cnt = 0
- var cnt1 = 0
- writer.println("{")
- for (term in part.terms) {
- val nn = String.format("C%d", cnt)
- when {
- term.type === TERMS.TOKEN -> {
- writer.println("ctx.text += lex.token")
- writer.println("lex.nextToken()")
- //cnt++;
- }
- term.type === TERMS.NONTERM -> {
- if(part.synth.containsKey(Integer(cnt1)))
- writer.println(String.format("val %s = %sRule(%s)", nn, term.v, part.synth[Integer(cnt1)]))
- else
- writer.println(String.format("val %s = %sRule()", nn, term.v))
- writer.println(String.format("ctx.text += %s.text", nn))
- cnt++
- }
- term.type === TERMS.SYM -> {
- term.v = term.v.replace("$", "ctx.")
- writer.println("run" + term.v.replace("±", "}"))
- writer.println("//sym")
- }
- }
- cnt1++
- }
- writer.println("return ctx")
- writer.println("}")
- }
- writer.println("else -> throw ParseException(\"? expected at position \" + lex.pos + \" get \" + lex.s[lex.pos], lex.pos)")
- writer.println("}")
- writer.println("}")
- for (part in rule.rparts) {
- val s = HashSet(getFirst(part, 0))
- if (s.contains("eps")) {
- s.addAll(follow[A].orEmpty())
- s.remove("eps")
- }
- }
- }
- writer.println("}")
- writer.close()
- }
- }
Add Comment
Please, Sign In to add comment