Skip to content

Commit

Permalink
Add Identifier support
Browse files Browse the repository at this point in the history
  • Loading branch information
vldF committed Aug 30, 2021
1 parent 128bf83 commit a8f4b73
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/main/antlr/org/jetbrains/research/libsl/LibSL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ assignmentRight
;

callAutomatonConstructorWithNamedArgs
: name=Identifier '(' (namedArgs)? ')'
: name=periodSeparatedFullName '(' (namedArgs)? ')'
;

namedArgs
Expand Down
66 changes: 33 additions & 33 deletions src/main/kotlin/org/jetbrains/research/libsl/visitors/ASGBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ import org.jetbrains.research.libsl.asg.Function
class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
override fun visitFile(ctx: LibSLParser.FileContext): Library {
val header = ctx.header()
val libraryName = header.libraryName?.text ?: error("no library name specified")
val language = header.lang?.text?.removeSurrounding("\"", "\"")
val libraryVersion = header.ver?.text?.removeSurrounding("\"", "\"")
val lslVersion = header.lslver?.text?.removeSurrounding("\"", "\"")?.split(".")?.let {
val libraryName = header.libraryName?.processIdentifier() ?: error("no library name specified")
val language = header.lang?.processIdentifier()?.removeSurrounding("\"", "\"")
val libraryVersion = header.ver?.processIdentifier()?.removeSurrounding("\"", "\"")
val lslVersion = header.lslver?.processIdentifier()?.removeSurrounding("\"", "\"")?.split(".")?.let {
val parts = it.map { part -> part.toUInt() }
Triple(parts[0], parts[1], parts[2])
}
val url = header?.link?.text?.removeSurrounding("\"", "\"")
val url = header?.link?.processIdentifier()?.removeSurrounding("\"", "\"")

val meta = MetaNode(libraryName, libraryVersion, language, url, lslVersion)
val imports = ctx.globalStatement().mapNotNull { it.ImportStatement() }.map {
parseStringTokenStringSemicolon(it.text, "import")
parseStringTokenStringSemicolon(it.processIdentifier(), "import")
}.toList()
val includes = ctx.globalStatement().mapNotNull { it.IncludeStatement() }.map {
parseStringTokenStringSemicolon(it.text, "include")
parseStringTokenStringSemicolon(it.processIdentifier(), "include")
}.toList()

val automata = ctx.globalStatement()
Expand Down Expand Up @@ -55,20 +55,20 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
}

override fun visitAutomatonDecl(ctx: LibSLParser.AutomatonDeclContext): Automaton {
val name = ctx.name.text
val name = ctx.name.processIdentifier()
val automaton = context.resolveAutomaton(name)
val states = automaton!!.states
val shifts = ctx.automatonStatement()?.filter { it.automatonShiftDecl() != null }?.flatMap { shiftCtx ->
val parsedShift = shiftCtx.automatonShiftDecl()
val toName = parsedShift.to?.text!!
val toName = parsedShift.to?.processIdentifier()!!
if (parsedShift.identifierList() != null) {
parsedShift.identifierList().Identifier().map { fromIdentifier ->
val fromName = fromIdentifier.text!!
val fromName = fromIdentifier.processIdentifier()!!

processShift(fromName, toName, shiftCtx, states, automatonName = name)
}
} else {
val fromName = parsedShift.from.text!!
val fromName = parsedShift.from.processIdentifier()!!
listOf(processShift(fromName, toName, shiftCtx, states, automatonName = name))
}
}.orEmpty()
Expand Down Expand Up @@ -107,9 +107,9 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
}

val functions = parsedShift.functionsList()?.functionsListPart()?.map { part ->
val functionName = part.name.text
val functionName = part.name.processIdentifier()
val functionArgs = part.Identifier().drop(1).map { type ->
context.resolveType(type.processIdentifier()) ?: error("unresolved type: ${type.text}")
context.resolveType(type.processIdentifier()) ?: error("unresolved type: ${type.processIdentifier()}")
}

context.resolveFunction(functionName, automatonName = automatonName, argsType=functionArgs)
Expand All @@ -135,11 +135,11 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
}

override fun visitCallAutomatonConstructorWithNamedArgs(ctx: LibSLParser.CallAutomatonConstructorWithNamedArgsContext): Atomic {
val calleeName = ctx.name.text
val calleeName = ctx.name.processIdentifier()
val calleeAutomaton = context.resolveAutomaton(calleeName) ?: error("can't resolve automaton $calleeName")

val args = ctx.namedArgs()?.argPair()?.mapNotNull { pair ->
val name = pair.name.text
val name = pair.name.processIdentifier()
if (name == "state") {
null
} else {
Expand All @@ -149,7 +149,7 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
}
}.orEmpty()

val stateName = ctx.namedArgs()?.argPair()?.firstOrNull { it.name.text == "state" }?.expressionAtomic()?.text
val stateName = ctx.namedArgs()?.argPair()?.firstOrNull { it.name.processIdentifier() == "state" }?.expressionAtomic()?.text
val state = calleeAutomaton.states.firstOrNull { it.name == stateName } ?: error("unresolved state: $stateName")

return CallAutomatonConstructor(calleeAutomaton, args, state)
Expand All @@ -159,8 +159,8 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
val (ownerAutomatonName, functionName) = parseFunctionName(ctx)
var argIndex = 0
val args = ctx.functionDeclArgList()?.parameter()?.map { arg ->
val argName = arg.name.text
val argType = context.resolveType(arg.type.text) ?: error("unresolved type")
val argName = arg.name.processIdentifier()
val argType = context.resolveType(arg.type.processIdentifier()) ?: error("unresolved type")
val annotation = arg.annotation()?.let { anno ->
Annotation(anno.Identifier().processIdentifier(), anno.valuesAndIdentifiersList()?.expression()?.map { atomic ->
visitExpression(atomic)
Expand All @@ -169,18 +169,18 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {

FunctionArgument(argName, argType, argIndex++, annotation)
}.orEmpty()
val typeName = ctx.functionType?.text
val typeName = ctx.functionType?.processIdentifier()
val type = if (typeName != null) context.resolveType(typeName) ?: error("unresolved type: $typeName") else null

val preamble = ctx.functionPreamble()?.preamblePart()?.map { part ->
when {
part.requiresContract() != null -> {
val contractName = part.requiresContract().name?.text
val contractName = part.requiresContract().name?.processIdentifier()
val contractExpression = visitExpression(part.requiresContract().expression())
Contract(contractName, contractExpression, ContractKind.REQUIRES)
}
part.ensuresContract() != null -> {
val contractName = part.ensuresContract().name?.text
val contractName = part.ensuresContract().name?.processIdentifier()
val contractExpression = visitExpression(part.ensuresContract().expression())
Contract(contractName, contractExpression, ContractKind.ENSURES)
}
Expand Down Expand Up @@ -242,15 +242,15 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {

override fun visitEnsuresContract(ctx: LibSLParser.EnsuresContractContext): Contract {
return Contract(
name = ctx.name?.text,
name = ctx.name?.processIdentifier(),
expression = visitExpression(ctx.expression()),
kind = ContractKind.ENSURES
)
}

override fun visitRequiresContract(ctx: LibSLParser.RequiresContractContext): Contract {
return Contract(
name = ctx.name?.text,
name = ctx.name?.processIdentifier(),
expression = visitExpression(ctx.expression()),
kind = ContractKind.REQUIRES
)
Expand All @@ -275,7 +275,7 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
else -> {
val left = visitExpression(ctx.expression(0))
val right = visitExpression(ctx.expression(1))
val op = ArithmeticBinaryOps.fromString(ctx.op.text)
val op = ArithmeticBinaryOps.fromString(ctx.op.processIdentifier())

BinaryOpExpression(left, right, op)
}
Expand All @@ -295,8 +295,8 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
override fun visitExpressionAtomic(ctx: LibSLParser.ExpressionAtomicContext): Atomic = when {
ctx.primitiveLiteral()?.integerNumber() != null -> IntegerLiteral(ctx.primitiveLiteral().integerNumber().text.toInt())
ctx.primitiveLiteral()?.floatNumber() != null -> FloatLiteral(ctx.primitiveLiteral().floatNumber().text.toFloat())
ctx.primitiveLiteral()?.DoubleQuotedString() != null -> StringLiteral(ctx.primitiveLiteral().DoubleQuotedString().text.removeDoubleQuotes())
ctx.primitiveLiteral()?.bool != null -> BoolLiteral(ctx.primitiveLiteral()!!.bool!!.text.toBoolean())
ctx.primitiveLiteral()?.DoubleQuotedString() != null -> StringLiteral(ctx.primitiveLiteral().DoubleQuotedString().processIdentifier().removeDoubleQuotes())
ctx.primitiveLiteral()?.bool != null -> BoolLiteral(ctx.primitiveLiteral()!!.bool!!.processIdentifier().toBoolean())
ctx.qualifiedAccess() != null -> visitQualifiedAccess(ctx.qualifiedAccess())
else -> error("unknown atomic type")
}
Expand Down Expand Up @@ -418,11 +418,11 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
null
}
ctx is LibSLParser.FunctionDeclContext -> {
val automatonName = resolveFunctionByCtx(ctx)?.automatonName ?: error("can't resolve function: ${ctx.name.text}")
val automatonName = resolveFunctionByCtx(ctx)?.automatonName ?: error("can't resolve function: ${ctx.name.processIdentifier()}")
context.resolveAutomaton(automatonName) ?: error("can't resolve automaton: $automatonName")
}
ctx is LibSLParser.AutomatonDeclContext -> {
val name = ctx.name.text
val name = ctx.name.processIdentifier()
context.resolveAutomaton(name) ?: error("can't resolve automaton: $name")
}
else -> {
Expand All @@ -434,8 +434,8 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
private fun resolveFunctionByCtx(ctx: LibSLParser.FunctionDeclContext): Function? {
var argumentIndex = 0
val args = ctx.functionDeclArgList()?.parameter()?.map { arg ->
val argName = arg.name.text
val argType = context.resolveType(arg.type.text) ?: error("unresolved type")
val argName = arg.name.processIdentifier()
val argType = context.resolveType(arg.type.processIdentifier()) ?: error("unresolved type")
val annotation = arg.annotation()?.let { anno ->
Annotation(anno.Identifier().processIdentifier(), anno.valuesAndIdentifiersList().expression().map { atomic ->
visitExpression(atomic)
Expand All @@ -447,14 +447,14 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
return if (ctx.name.Identifier().size > 1) {
// an extension function case
val automatonName = ctx.name.Identifier(0)?.processIdentifier()
val funcName = ctx.name.text.removePrefix("$automatonName.")
val funcName = ctx.name.processIdentifier().removePrefix("$automatonName.")
context.resolveFunction(funcName, automatonName, args)
} else {
// a standalone function case
val funcName = ctx.name.Identifier().first().processIdentifier()
val automaton = ctx.parent?.parent as? LibSLParser.AutomatonDeclContext
?: error("non-extension function $funcName not in automaton")
val automatonName = automaton.name.text
val automatonName = automaton.name.processIdentifier()
context.resolveFunction(funcName, automatonName, args)
}
}
Expand All @@ -473,7 +473,7 @@ class ASGBuilder(private val context: LslContext) : LibSLBaseVisitor<Node>() {
}
}
is LibSLParser.AutomatonDeclContext -> {
val automatonName = ctx.name.text
val automatonName = ctx.name.processIdentifier()
val automaton = context.resolveAutomaton(automatonName)!!
automaton.variables.firstOrNull { it.name == variableName }
}
Expand Down
28 changes: 14 additions & 14 deletions src/main/kotlin/org/jetbrains/research/libsl/visitors/Resolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ class Resolver(

val automata = ctx.globalStatement().mapNotNull { it.declaration()?.automatonDecl() }
for (automatonCtx in automata) {
val typeName = automatonCtx.type.text
val typeName = automatonCtx.type.processIdentifier()
val type = context.resolveType(typeName) ?: error("unresolved type: $typeName")

val variables = automatonCtx.automatonStatement().mapNotNull { it.variableDeclaration() }.map { variable ->
val variableName = variable.nameWithType().name.text
val variableName = variable.nameWithType().name.processIdentifier()
val variableTypeName = variable.nameWithType().type.text
val variableType = context.resolveType(variableTypeName) ?: error("unresolved type $variableTypeName")

Expand All @@ -50,7 +50,7 @@ class Resolver(
}

val constructorVariables = automatonCtx.nameWithType().map { cVar ->
val argName = cVar.name.text
val argName = cVar.name.processIdentifier()
val argTypeName = cVar.type.text
val argType = context.resolveType(argTypeName) ?: error("unresolved type $argTypeName")

Expand All @@ -62,7 +62,7 @@ class Resolver(

val states = automatonCtx.automatonStatement()?.filter { it.automatonStateDecl() != null }?.flatMap { statesCtx ->
statesCtx.automatonStateDecl().identifierList().Identifier().map { stateCtx ->
val keyword = statesCtx.start.text
val keyword = statesCtx.start.processIdentifier()
val stateName = stateCtx.processIdentifier()
val stateKind = StateKind.fromString(keyword)
State(stateName, stateKind)
Expand Down Expand Up @@ -95,7 +95,7 @@ class Resolver(
}

val variable = GlobalVariableDeclaration(
nameWithType.name.text,
nameWithType.name.processIdentifier(),
type,
init
)
Expand Down Expand Up @@ -125,7 +125,7 @@ class Resolver(
}
semanticTypeContext.blockType() != null -> {
val blockType = semanticTypeContext.blockType()
val semanticType = blockType.semanticName.text
val semanticType = blockType.semanticName.processIdentifier()
val realName = blockType.realName
val resolvedRealType = context.resolveType(realName.text)
?: processRealTypeIdentifier(realName)
Expand Down Expand Up @@ -166,7 +166,7 @@ class Resolver(
}

val entries = ctx.typeDefBlockStatement().map { statement ->
statement.nameWithType().let { it.name.text to processRealTypeIdentifier(it.type) }
statement.nameWithType().let { it.name.processIdentifier() to processRealTypeIdentifier(it.type) }
}

context.storeResolvedType(StructuredType(
Expand All @@ -181,14 +181,14 @@ class Resolver(
private fun resolvePrimitiveLiteral(primitiveLiteralContext: LibSLParser.PrimitiveLiteralContext): Atomic {
return when {
primitiveLiteralContext.bool != null -> {
if (primitiveLiteralContext.bool.text == "true") {
if (primitiveLiteralContext.bool.processIdentifier() == "true") {
BoolLiteral(true)
} else {
BoolLiteral(false)
}
}
primitiveLiteralContext.DoubleQuotedString() != null -> {
val literal = primitiveLiteralContext.DoubleQuotedString().text.removeDoubleQuotes()
val literal = primitiveLiteralContext.DoubleQuotedString().processIdentifier().removeDoubleQuotes()
StringLiteral(literal)
}
primitiveLiteralContext.floatNumber() != null -> {
Expand All @@ -202,7 +202,7 @@ class Resolver(
}

private fun processRealTypeIdentifier(ctx: LibSLParser.TypeIdentifierContext): Type {
val name = ctx.periodSeparatedFullName().Identifier().map { it.text }
val name = ctx.periodSeparatedFullName().Identifier().map { it.processIdentifier() }
val generic = ctx.generic?.let { processRealTypeIdentifier(it) }
val isPointer = ctx.asterisk != null

Expand Down Expand Up @@ -231,7 +231,7 @@ class Resolver(
ctx.automatonStatement()
.mapNotNull { it.variableDeclaration() }
.forEach { decl ->
val variableName = decl.nameWithType().name.text
val variableName = decl.nameWithType().name.processIdentifier()
val automatonVariable = automaton.internalVariables.first { it.name == variableName }

if (decl.assignmentRight() != null) {
Expand All @@ -250,13 +250,13 @@ class Resolver(
val (automatonName, name) = parseFunctionName(ctx)
automatonName ?: error("automaton name not specified for function: $name")

val typeName = ctx.functionType?.text
val typeName = ctx.functionType?.processIdentifier()
val returnType = if (typeName != null) context.resolveType(typeName)
?: error("unresolved type: $typeName") else null

var argumentIndex = 0
val args = ctx.functionDeclArgList()?.parameter()?.map { arg ->
val argType = context.resolveType(arg.type.text) ?: error("unresolved type")
val argType = context.resolveType(arg.type.processIdentifier()) ?: error("unresolved type")
FunctionArgument(arg.name.processIdentifier(), argType, argumentIndex++,null)
}?.toList().orEmpty()

Expand Down Expand Up @@ -286,7 +286,7 @@ class Resolver(

private fun processImportStatement(terminal: TerminalNode) {
// todo: forbid a recursive imports
val importString = parseStringTokenStringSemicolon(terminal.text, "import")
val importString = parseStringTokenStringSemicolon(terminal.processIdentifier(), "import")
val filePath = "$basePath/$importString.lsl"
val file = File(filePath)

Expand Down

0 comments on commit a8f4b73

Please sign in to comment.