Составление комбинаторов синтаксического анализатора во время выполнения - PullRequest
0 голосов
/ 05 июля 2018

Я видел несколько других сообщений SO, относящихся к этой теме, предполагая, что наследование с использованием признаков является единственным выходом из этой проблемы, но я не понимаю, как использовать это здесь.

Я пишу ассемблер, у которого есть директива, которая позволяет вам изменять модель процессора, тем самым влияя на то, какой набор кодов операций может быть проанализирован. У меня есть два класса анализатора, один обрабатывает все ключевые слова директивы, а другой обрабатывает инструкции. (Будет больше, для разных моделей процессоров). Когда директива cpu анализируется, выбирается соответствующий анализатор команд. Вот очень урезанная иллюстрация:

import scala.util.parsing.combinator.JavaTokenParsers

class ComposingParser {

    sealed abstract class Statement {
    }
    case class Dinst(value: String) extends Statement
    case class Keyword(value: String) extends Statement

    class InstructionParser extends JavaTokenParsers {
        def directOpcode: Parser[Statement] = j | ldlp | pfix

        private def j: Parser[Dinst]     = """(?i)J""".r     ^^ ( x => Dinst(x.toUpperCase) )
        private def ldlp: Parser[Dinst]  = """(?i)LDLP""".r  ^^ ( x => Dinst(x.toUpperCase) )
        private def pfix: Parser[Dinst]  = """(?i)PFIX""".r  ^^ ( x => Dinst(x.toUpperCase) )
    }

    class KeywordParser extends JavaTokenParsers {
        def program: Parser[Statement] = keys | instruction // the main, top-level parser

        def keys: Parser[Keyword] = start | end

        private def start: Parser[Keyword]  = """(?i)START""".r  ^^ ( x => Keyword(x.toUpperCase) )
        private def end: Parser[Keyword]  = """(?i)END""".r  ^^ ( x => Keyword(x.toUpperCase) )

        private def instruction: Parser[Statement] = {
            val ip = new InstructionParser // will be dynamically instantiating different parsers for different instruction sets so can't use traits
            ip.directOpcode
            // Error:(46, 16) type mismatch;
            // found   : ip.Parser[ComposingParser.this.Statement]
            // required: KeywordParser.this.Parser[ComposingParser.this.Statement]
            // ip.directOpcode
        }
        // I can't use traits as in /1866546/scala-kak-obedinit-parsernye-kombinatory-iz-raznyh-obektov
        // I can't see how to apply the solution from https://stackoverflow.com/questions/40166258/reuse-parser-within-another-parser-with-scala-parser-combinators
        // Is it possible to convert an 'ip.Parser[Statement]' into a 'KeywordParser.this.Parser[Statement]' ?
    }
}

directOpcode и инструкция возвращают Parser [Statement], почему я не могу их так скомбинировать? Могут ли здесь помочь аннотации самопечатания? Заранее благодарим за любую помощь, которую вы можете оказать ... (или иллюстрации, показывающие, как могут помочь решения, опубликованные в других цитируемых публикациях SO).

1 Ответ

0 голосов
/ 06 июля 2018

Из вопроса не очевидно, почему вы «не можете использовать черты». По крайней мере, ваш конкретный пример отлично работает с чертами:

// uses `$ivy`-imports, either run with Ammonite, or remove the import and
// compile using SBT.
import $ivy.`org.scala-lang.modules:scala-parser-combinators_2.12:1.1.1`
import scala.util.parsing.combinator.JavaTokenParsers

class ComposingParser {

    sealed abstract class Statement {
    }
    case class Dinst(value: String) extends Statement
    case class Keyword(value: String) extends Statement

    trait InstructionParser extends JavaTokenParsers {
        def directOpcode: Parser[Statement] = j | ldlp | pfix

        private def j: Parser[Dinst]     = """(?i)J""".r     ^^ ( x => Dinst(x.toUpperCase) )
        private def ldlp: Parser[Dinst]  = """(?i)LDLP""".r  ^^ ( x => Dinst(x.toUpperCase) )
        private def pfix: Parser[Dinst]  = """(?i)PFIX""".r  ^^ ( x => Dinst(x.toUpperCase) )
    }

    trait InstructionParser2 extends JavaTokenParsers {
        def directOpcode2: Parser[Statement] = j | ldlp | pfix

        private def j: Parser[Dinst]     = """(?i)J""".r     ^^ ( x => Dinst(x.toUpperCase) )
        private def ldlp: Parser[Dinst]  = """(?i)LDLP""".r  ^^ ( x => Dinst(x.toUpperCase) )
        private def pfix: Parser[Dinst]  = """(?i)PFIX""".r  ^^ ( x => Dinst(x.toUpperCase) )
    }

    class KeywordParser extends JavaTokenParsers 
    with InstructionParser 
    with InstructionParser2 {
        def program: Parser[Statement] = keys | instruction // the main, top-level parser

        def keys: Parser[Keyword] = start | end

        private def start: Parser[Keyword]  = """(?i)START""".r  ^^ ( x => Keyword(x.toUpperCase) )
        private def end: Parser[Keyword]  = """(?i)END""".r  ^^ ( x => Keyword(x.toUpperCase) )

        private def instruction: Parser[Statement] = {
            if (math.random < 0.5) directOpcode else directOpcode2 
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...