mirror of
				https://github.com/GayPizzaSpecifications/pork.git
				synced 2025-11-04 09:59:39 +00:00 
			
		
		
		
	parser: fix bug in ide support
This commit is contained in:
		@ -1,4 +1,5 @@
 | 
				
			|||||||
export func main() {
 | 
					export func main() {
 | 
				
			||||||
  let pi = 3.141592653589793
 | 
					  let pi = 3.141592653589793
 | 
				
			||||||
  println(pi)
 | 
					  println(pi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
 | 
				
			|||||||
@ -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 {
 | 
				
			||||||
 | 
				
			|||||||
@ -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}'"
 | 
				
			||||||
 | 
				
			|||||||
@ -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")
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user