parser: fix bug in ide support

This commit is contained in:
Alex Zenla 2023-09-13 19:50:23 -07:00
parent 2307fdc0ed
commit 63e7203db9
Signed by: alex
GPG Key ID: C0780728420EBFE5
6 changed files with 25 additions and 18 deletions

View File

@ -1,4 +1,5 @@
export func main() {
let pi = 3.141592653589793
println(pi)
}

View File

@ -1,3 +1,3 @@
package gay.pizza.pork.parser
class ParseError(val error: String) : RuntimeException(error)
open class ParseError(val error: String) : RuntimeException(error)

View File

@ -16,7 +16,7 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
Block(items)
}
override fun parseExpression(): Expression {
override fun parseExpression(): Expression = guarded {
val token = peek()
val expression = when (token.type) {
TokenType.NumberLiteral -> parseNumberLiteral()
@ -37,7 +37,7 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
TokenType.None -> parseNoneLiteral()
else -> {
throw gay.pizza.pork.parser.ParseError(
throw ParseError(
"Failed to parse token: ${token.type} '${token.text}' as" +
" expression (index ${source.currentIndex})"
)
@ -45,7 +45,7 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
}
if (expression is SymbolReference && peek(TokenType.Equals)) {
return guarded {
return@guarded guarded {
attribution.adopt(expression)
expect(TokenType.Equals)
val value = parseExpression()
@ -53,7 +53,7 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
}
}
return if (peek(
return@guarded if (peek(
TokenType.Plus,
TokenType.Minus,
TokenType.Multiply,
@ -138,7 +138,7 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
return modifiers
}
fun maybeParseDefinition(): Definition? {
private fun maybeParseDefinition(): Definition? {
try {
storedDefinitionModifiers = parseDefinitionModifiers()
val token = peek()
@ -152,19 +152,19 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
}
}
override fun parseDeclaration(): Declaration {
override fun parseDeclaration(): Declaration = guarded {
val token = peek()
return when (token.type) {
return@guarded when (token.type) {
TokenType.Import -> parseImportDeclaration()
else -> throw gay.pizza.pork.parser.ParseError(
else -> throw ParseError(
"Failed to parse token: ${token.type} '${token.text}' as" +
" declaration (index ${source.currentIndex})"
)
}
}
override fun parseDefinition(): Definition {
return maybeParseDefinition() ?: throw ParseError("Unable to parse definition")
override fun parseDefinition(): Definition = guarded {
maybeParseDefinition() ?: throw ParseError("Unable to parse definition")
}
override fun parseDoubleLiteral(): DoubleLiteral = guarded {

View File

@ -4,8 +4,6 @@ import gay.pizza.pork.ast.Node
import gay.pizza.pork.ast.NodeParser
abstract class ParserBase(val source: TokenSource, val attribution: NodeAttribution) : NodeParser {
open class ParseError(error: String) : RuntimeException(error)
class ExpectedTokenError(got: Token, vararg expectedTypes: TokenType) : ParseError(
"Expected one of ${expectedTypes.joinToString(", ")}" +
" but got type ${got.type} '${got.text}'"

View File

@ -23,7 +23,7 @@ internal object ParserHelpers {
TokenType.GreaterEqual -> InfixOperator.GreaterEqual
TokenType.And -> InfixOperator.BooleanAnd
TokenType.Or -> InfixOperator.BooleanOr
else -> throw ParserBase.ParseError("Unknown Infix Operator")
else -> throw ParseError("Unknown Infix Operator")
}
fun convertPrefixOperator(token: Token): PrefixOperator = when (token.type) {
@ -31,12 +31,12 @@ internal object ParserHelpers {
TokenType.Plus -> PrefixOperator.UnaryPlus
TokenType.Minus -> PrefixOperator.UnaryMinus
TokenType.Tilde -> PrefixOperator.BinaryNot
else -> throw ParserBase.ParseError("Unknown Prefix Operator")
else -> throw ParseError("Unknown Prefix Operator")
}
fun convertSuffixOperator(token: Token): SuffixOperator = when (token.type) {
TokenType.PlusPlus -> SuffixOperator.Increment
TokenType.MinusMinus -> SuffixOperator.Decrement
else -> throw ParserBase.ParseError("Unknown Suffix Operator")
else -> throw ParseError("Unknown Suffix Operator")
}
}

View File

@ -4,14 +4,17 @@ import com.intellij.lang.PsiBuilder
import gay.pizza.pork.ast.Node
import gay.pizza.pork.parser.ParseError
import gay.pizza.pork.parser.ParserNodeAttribution
import java.util.IdentityHashMap
class PsiBuilderMarkAttribution(val builder: PsiBuilder) : ParserNodeAttribution() {
private val map = IdentityHashMap<Node, Node>()
override fun <T : Node> guarded(block: () -> T): T {
val marker = builder.mark()
try {
val result = try {
val item = super.guarded(block)
marker.done(PorkElementTypes.elementTypeFor(item.type))
return item
item
} catch (e: PsiBuilderTokenSource.BadCharacterError) {
marker.error("Bad character.")
while (!builder.eof()) {
@ -32,5 +35,10 @@ class PsiBuilderMarkAttribution(val builder: PsiBuilder) : ParserNodeAttribution
}
throw PorkParser.ExitParser()
}
if (map[result] != null) {
marker.drop()
}
map[result] = result
return result
}
}