parser: fix bug in ide support

This commit is contained in:
2023-09-13 19:50:23 -07:00
parent 2307fdc0ed
commit 63e7203db9
6 changed files with 25 additions and 18 deletions

View File

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

View File

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

View File

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

View File

@ -23,7 +23,7 @@ internal object ParserHelpers {
TokenType.GreaterEqual -> InfixOperator.GreaterEqual TokenType.GreaterEqual -> InfixOperator.GreaterEqual
TokenType.And -> InfixOperator.BooleanAnd TokenType.And -> InfixOperator.BooleanAnd
TokenType.Or -> InfixOperator.BooleanOr 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) { fun convertPrefixOperator(token: Token): PrefixOperator = when (token.type) {
@ -31,12 +31,12 @@ internal object ParserHelpers {
TokenType.Plus -> PrefixOperator.UnaryPlus TokenType.Plus -> PrefixOperator.UnaryPlus
TokenType.Minus -> PrefixOperator.UnaryMinus TokenType.Minus -> PrefixOperator.UnaryMinus
TokenType.Tilde -> PrefixOperator.BinaryNot 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) { fun convertSuffixOperator(token: Token): SuffixOperator = when (token.type) {
TokenType.PlusPlus -> SuffixOperator.Increment TokenType.PlusPlus -> SuffixOperator.Increment
TokenType.MinusMinus -> SuffixOperator.Decrement 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.ast.Node
import gay.pizza.pork.parser.ParseError import gay.pizza.pork.parser.ParseError
import gay.pizza.pork.parser.ParserNodeAttribution import gay.pizza.pork.parser.ParserNodeAttribution
import java.util.IdentityHashMap
class PsiBuilderMarkAttribution(val builder: PsiBuilder) : ParserNodeAttribution() { class PsiBuilderMarkAttribution(val builder: PsiBuilder) : ParserNodeAttribution() {
private val map = IdentityHashMap<Node, Node>()
override fun <T : Node> guarded(block: () -> T): T { override fun <T : Node> guarded(block: () -> T): T {
val marker = builder.mark() val marker = builder.mark()
try { val result = try {
val item = super.guarded(block) val item = super.guarded(block)
marker.done(PorkElementTypes.elementTypeFor(item.type)) marker.done(PorkElementTypes.elementTypeFor(item.type))
return item item
} catch (e: PsiBuilderTokenSource.BadCharacterError) { } catch (e: PsiBuilderTokenSource.BadCharacterError) {
marker.error("Bad character.") marker.error("Bad character.")
while (!builder.eof()) { while (!builder.eof()) {
@ -32,5 +35,10 @@ class PsiBuilderMarkAttribution(val builder: PsiBuilder) : ParserNodeAttribution
} }
throw PorkParser.ExitParser() throw PorkParser.ExitParser()
} }
if (map[result] != null) {
marker.drop()
}
map[result] = result
return result
} }
} }