Remove old lexer+parser implementation
This commit is contained in:
parent
d5632e9217
commit
a4ec29f084
15 changed files with 0 additions and 706 deletions
|
@ -1,137 +0,0 @@
|
|||
package parser
|
||||
|
||||
import lexer.Token
|
||||
import lexer.TokenType
|
||||
import parser.errors.ParsingError
|
||||
import parser.errors.ParsingErrorType
|
||||
import parser.state.ParserPosition
|
||||
import prolog.ast.logic.Clause
|
||||
import prolog.ast.logic.Fact
|
||||
import prolog.ast.logic.Rule
|
||||
import prolog.ast.terms.Atom
|
||||
import prolog.ast.terms.Structure
|
||||
import prolog.ast.terms.Term
|
||||
|
||||
class Parser(private val tokens: List<Token>) {
|
||||
private val position: ParserPosition = ParserPosition(0)
|
||||
|
||||
fun parse(): List<Term> {
|
||||
val terms = mutableListOf<Term>()
|
||||
|
||||
while (hasNext()) {
|
||||
position.save()
|
||||
|
||||
var term: Term? = null
|
||||
|
||||
while (term == null) {
|
||||
// Try each parser rule in order
|
||||
|
||||
}
|
||||
|
||||
require(term != null) {
|
||||
ParsingError(ParsingErrorType.UNEXPECTED_TOKEN, "Expected a term", position)
|
||||
}
|
||||
|
||||
terms.add(term)
|
||||
}
|
||||
|
||||
return terms
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the current token with any of the expected types.
|
||||
* If it matches, it consumes the token and returns true.
|
||||
*
|
||||
* @param types The list of expected token types.
|
||||
* @return True if the current token matches any of the expected types, false otherwise.
|
||||
*/
|
||||
private fun match(types: List<TokenType>): Boolean {
|
||||
for (type in types) {
|
||||
if (check(type)) {
|
||||
next()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current token matches the expected type.
|
||||
*/
|
||||
private fun check(type: TokenType): Boolean {
|
||||
return hasNext() && peek().type == type
|
||||
}
|
||||
|
||||
private fun hasNext(): Boolean {
|
||||
// Check if the position is within the tokens list
|
||||
// TODO Check for EOF instead?
|
||||
return position.offset < tokens.size
|
||||
}
|
||||
|
||||
private fun peek(): Token {
|
||||
require(hasNext()) { "Unexpected end of input" }
|
||||
|
||||
return tokens[position.offset]
|
||||
}
|
||||
|
||||
private fun next(): Token {
|
||||
val token = peek()
|
||||
position.offset++
|
||||
return token
|
||||
}
|
||||
|
||||
private fun previous(): Token {
|
||||
require(0 < position.offset) { "No previous token" }
|
||||
return tokens[position.offset - 1]
|
||||
}
|
||||
|
||||
/* * * * * *
|
||||
* Parsers *
|
||||
* * * * * */
|
||||
|
||||
private fun parseWithTry(parseRule: () -> Term): Term {
|
||||
try {
|
||||
return parseRule()
|
||||
} catch (e: Exception) {
|
||||
throw ParsingError(ParsingErrorType.UNEXPECTED_TOKEN, "Unexpected token", position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseClause(): Clause {
|
||||
return try {
|
||||
Fact(parseStructure())
|
||||
} catch (e: Exception) {
|
||||
Fact(parseAtom())
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseStructure(): Structure {
|
||||
val name = parseAtom()
|
||||
val args = mutableListOf<Term>()
|
||||
|
||||
require(match(listOf(TokenType.PARENTHESIS_LEFT))) {
|
||||
ParsingError(ParsingErrorType.UNEXPECTED_TOKEN, "Expected '(' after structure name", position)
|
||||
}
|
||||
|
||||
// TODO Handle arguments
|
||||
|
||||
require(match(listOf(TokenType.PARENTHESIS_RIGHT))) {
|
||||
ParsingError(ParsingErrorType.UNEXPECTED_TOKEN, "Expected ')' after structure arguments", position)
|
||||
}
|
||||
|
||||
return Structure(name, args)
|
||||
}
|
||||
|
||||
private fun parseAtom(): Atom {
|
||||
return Atom(parseLetterDigit())
|
||||
}
|
||||
|
||||
private fun parseLetterDigit(): String {
|
||||
require(match(listOf(TokenType.ALPHANUMERIC)) && previous().value[0].isLowerCase()) {
|
||||
ParsingError(ParsingErrorType.UNEXPECTED_TOKEN, "Expected lowercase letter", position)
|
||||
}
|
||||
|
||||
return previous().value
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package parser.errors
|
||||
|
||||
import parser.state.ParserPosition
|
||||
|
||||
class ParsingError(private val type: ParsingErrorType, override val message: String, private val position: ParserPosition) :
|
||||
Throwable() {
|
||||
override fun toString(): String {
|
||||
return """
|
||||
($position) ${type}: $message
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package parser.errors
|
||||
|
||||
enum class ParsingErrorType {
|
||||
UNEXPECTED_TOKEN,
|
||||
|
||||
INTERNAL_ERROR,
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package parser.state
|
||||
|
||||
import parser.errors.ParsingError
|
||||
import parser.errors.ParsingErrorType
|
||||
|
||||
data class ParserPosition(var offset: Int) {
|
||||
private val checkpoints: ArrayDeque<ParserPosition> = ArrayDeque()
|
||||
|
||||
fun save() {
|
||||
checkpoints.addLast(this.copy())
|
||||
}
|
||||
|
||||
fun reload() {
|
||||
require(checkpoints.isNotEmpty()) {
|
||||
ParsingError(ParsingErrorType.INTERNAL_ERROR, "No checkpoint to reload from", this)
|
||||
}
|
||||
|
||||
val checkpoint = checkpoints.removeLast()
|
||||
offset = checkpoint.offset
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "at $offset"
|
||||
}
|
||||
}
|
Reference in a new issue