position and parent moved out of data class constructor

This commit is contained in:
Irmen de Jong 2018-08-12 20:57:29 +02:00
parent 30c5550ece
commit 20d5eb79d0
5 changed files with 598 additions and 265 deletions

View File

@ -1,11 +1,18 @@
~ main $c000 {
const byte hopla=55-33
const byte hopla2=55-hopla
A = "derp" * %000100
~ main $c003 {
memory byte derp = $ffdd1
const byte hopla=55-33
; const byte hopla2=55-hopla
const float zwop = -1.7014118345e+38
const float zwop = -1.7014118346e+38
%import maghierniet
A = "derp" * %000100
return 1+999
%import maghierniet
%import maghierniet
%import maghierniet
%import maghierniet
return 1+999
}
%import imported1, 33, aaa

View File

@ -11,7 +11,6 @@ fun Module.checkValid() : List<SyntaxError> {
class AstChecker : IAstProcessor {
private val checkResult: MutableList<SyntaxError> = mutableListOf()
fun result(): List<SyntaxError> {
@ -26,6 +25,73 @@ class AstChecker : IAstProcessor {
return expr
}
override fun process(block: Block): IStatement {
if(block.address!=null && (block.address<0 || block.address>65535)) {
checkResult.add(SyntaxError("block memory address must be valid 0..\$ffff", block))
}
block.statements.forEach { it.process(this) }
return block
}
/**
* Check the variable declarations (values within range etc)
*/
override fun process(decl: VarDecl): IStatement {
fun err(msg: String) {
if(decl.value?.position == null)
throw AstException("declvalue no pos!")
checkResult.add(SyntaxError(msg, decl))
}
when(decl.type) {
VarDeclType.VAR, VarDeclType.CONST -> {
val value = decl.value as? LiteralValue
if(value==null)
err("need a compile-time constant initializer value, found: ${decl.value!!::class.simpleName}")
else
when(decl.datatype) {
DataType.FLOAT -> {
val number = value.asFloat()
if(number==null)
err("need a const float initializer value")
else if(number > 1.7014118345e+38 || number < -1.7014118345e+38)
err("floating point value out of range for MFLPT format")
}
DataType.BYTE -> {
val number = value.asInt()
if(number==null)
err("need a const integer initializer value")
else if(number < 0 || number > 255)
err("value out of range for unsigned byte")
}
DataType.WORD -> {
val number = value.asInt()
if(number==null)
err("need a const integer initializer value")
else if(number < 0 || number > 65535)
err("value out of range for unsigned word")
}
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
val str = value.strvalue
if(str==null)
err("need a const string initializer value")
else if(str.isEmpty() || str.length>65535)
err("string length must be 1..65535")
}
}
}
VarDeclType.MEMORY -> {
val value = decl.value as LiteralValue
if(value.intvalue==null || value.intvalue<0 || value.intvalue>65535) {
err("memory address must be valid 0..\$ffff")
}
}
}
decl.arrayspec?.process(this)
decl.value?.process(this)
return decl
}
/**
* check the arguments of the directive
*/
@ -35,14 +101,17 @@ class AstChecker : IAstProcessor {
}
when(directive.directive) {
"%output" -> {
if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 || directive.args[0].name != "raw" && directive.args[0].name != "prg")
err("invalid output directive type, expected raw or prg")
}
"%launcher" -> {
if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 || directive.args[0].name != "basic" && directive.args[0].name != "none")
err("invalid launcher directive type, expected basic or none")
}
"%zp" -> {
if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 ||
directive.args[0].name != "compatible" &&
directive.args[0].name != "full" &&
@ -50,10 +119,12 @@ class AstChecker : IAstProcessor {
err("invalid zp directive style, expected compatible, full or full-restore")
}
"%address" -> {
if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 || directive.args[0].int == null)
err("invalid address directive, expected numeric address argument")
}
"%import" -> {
if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 || directive.args[0].name==null)
err("invalid import directive, expected module name argument")
}

View File

@ -26,6 +26,17 @@ class AstOptimizer : IAstProcessor {
optimizationsDone = 0
}
override fun process(block: Block): IStatement {
block.statements = block.statements.map { it.process(this) }
return block
}
override fun process(decl: VarDecl): IStatement {
decl.value = decl.value?.process(this)
decl.arrayspec?.process(this)
return decl
}
/**
* Try to process a unary prefix expression.
* Compile-time constant sub expressions will be evaluated on the spot.
@ -37,39 +48,41 @@ class AstOptimizer : IAstProcessor {
val subexpr = expr.expression
if (subexpr is LiteralValue) {
// process prefixed literal values (such as -3, not true)
return when {
val result = when {
expr.operator == "+" -> subexpr
expr.operator == "-" -> return when {
expr.operator == "-" -> when {
subexpr.intvalue != null -> {
optimizationsDone++
LiteralValue(intvalue = subexpr.intvalue, position = subexpr.position)
LiteralValue(intvalue = subexpr.intvalue)
}
subexpr.floatvalue != null -> {
optimizationsDone++
LiteralValue(floatvalue = -subexpr.floatvalue, position = subexpr.position)
LiteralValue(floatvalue = -subexpr.floatvalue)
}
else -> throw UnsupportedOperationException("can only take negative of int or float")
}
expr.operator == "~" -> return when {
expr.operator == "~" -> when {
subexpr.intvalue != null -> {
optimizationsDone++
LiteralValue(intvalue = subexpr.intvalue.inv(), position = subexpr.position)
LiteralValue(intvalue = subexpr.intvalue.inv())
}
else -> throw UnsupportedOperationException("can only take bitwise inversion of int")
}
expr.operator == "not" -> return when {
expr.operator == "not" -> when {
subexpr.intvalue != null -> {
optimizationsDone++
LiteralValue(intvalue = if (subexpr.intvalue == 0) 1 else 0, position = subexpr.position)
LiteralValue(intvalue = if (subexpr.intvalue == 0) 1 else 0)
}
subexpr.floatvalue != null -> {
optimizationsDone++
LiteralValue(intvalue = if (subexpr.floatvalue == 0.0) 1 else 0, position = subexpr.position)
LiteralValue(intvalue = if (subexpr.floatvalue == 0.0) 1 else 0)
}
else -> throw UnsupportedOperationException("can not take logical not of $subexpr")
}
else -> throw UnsupportedOperationException(expr.operator)
}
result.position = subexpr.position
return result
}
return expr
}
@ -98,7 +111,6 @@ class AstOptimizer : IAstProcessor {
}
override fun process(directive: Directive): IStatement {
println("directove OPT $directive")
return directive
}
}
@ -135,7 +147,9 @@ class ConstExprEvaluator {
private fun comparenotequal(left: LiteralValue, right: LiteralValue): LiteralValue {
val leq = compareequal(left, right)
return LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1, position = left.position)
val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1)
litval.position = left.position
return litval
}
private fun compareequal(left: LiteralValue, right: LiteralValue): LiteralValue {
@ -153,159 +167,164 @@ class ConstExprEvaluator {
right.arrayvalue!=null -> right.arrayvalue
else -> throw AstException("missing literal value")
}
return LiteralValue(intvalue = if(leftvalue==rightvalue) 1 else 0, position = left.position)
val litval = LiteralValue(intvalue = if(leftvalue==rightvalue) 1 else 0)
litval.position = left.position
return litval
}
private fun comparegreaterequal(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left >= $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.intvalue >= right.intvalue) 1 else 0,
position = left.position)
intvalue = if (left.intvalue >= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue >= right.floatvalue) 1 else 0,
position = left.position)
intvalue = if (left.intvalue >= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue >= right.intvalue) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue >= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue >= right.floatvalue) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue >= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun comparelessequal(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left >= $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.intvalue <= right.intvalue) 1 else 0,
position = left.position)
intvalue = if (left.intvalue <= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue <= right.floatvalue) 1 else 0,
position = left.position)
intvalue = if (left.intvalue <= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue <= right.intvalue) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue <= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue <= right.floatvalue) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue <= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun comparegreater(left: LiteralValue, right: LiteralValue): LiteralValue {
val leq = comparelessequal(left, right)
return LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1, position = left.position)
val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1)
litval.position = left.position
return litval
}
private fun compareless(left: LiteralValue, right: LiteralValue): LiteralValue {
val leq = comparegreaterequal(left, right)
return LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1, position = left.position)
val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1)
litval.position = left.position
return litval
}
private fun logicalxor(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left locical-xor $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if ((left.intvalue!=0).xor(right.intvalue!=0)) 1 else 0,
position = left.position)
intvalue = if ((left.intvalue!=0).xor(right.intvalue!=0)) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if ((left.intvalue!=0).xor(right.floatvalue!=0.0)) 1 else 0,
position = left.position)
intvalue = if ((left.intvalue!=0).xor(right.floatvalue!=0.0)) 1 else 0)
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if ((left.floatvalue!=0.0).xor(right.intvalue!=0)) 1 else 0,
position = left.position)
intvalue = if ((left.floatvalue!=0.0).xor(right.intvalue!=0)) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if ((left.floatvalue!=0.0).xor(right.floatvalue!=0.0)) 1 else 0,
position = left.position)
intvalue = if ((left.floatvalue!=0.0).xor(right.floatvalue!=0.0)) 1 else 0)
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun logicalor(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left locical-or $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.intvalue!=0 || right.intvalue!=0) 1 else 0,
position = left.position)
intvalue = if (left.intvalue!=0 || right.intvalue!=0) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue!=0 || right.floatvalue!=0.0) 1 else 0,
position = left.position)
intvalue = if (left.intvalue!=0 || right.floatvalue!=0.0) 1 else 0)
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue!=0.0 || right.intvalue!=0) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue!=0.0 || right.intvalue!=0) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue!=0.0 || right.floatvalue!=0.0) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue!=0.0 || right.floatvalue!=0.0) 1 else 0)
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun logicaland(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left locical-and $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.intvalue!=0 && right.intvalue!=0) 1 else 0,
position = left.position)
intvalue = if (left.intvalue!=0 && right.intvalue!=0) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue!=0 && right.floatvalue!=0.0) 1 else 0,
position = left.position)
intvalue = if (left.intvalue!=0 && right.floatvalue!=0.0) 1 else 0)
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue!=0.0 && right.intvalue!=0) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue!=0.0 && right.intvalue!=0) 1 else 0)
right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue!=0.0 && right.floatvalue!=0.0) 1 else 0,
position = left.position)
intvalue = if (left.floatvalue!=0.0 && right.floatvalue!=0.0) 1 else 0)
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun bitwisexor(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.intvalue!=null && right.intvalue !=null)
return LiteralValue(intvalue = left.intvalue.xor(right.intvalue), position = left.position)
if(left.intvalue!=null && right.intvalue !=null) {
val litval = LiteralValue(intvalue = left.intvalue.xor(right.intvalue))
litval.position = left.position
return litval
}
throw ExpressionException("cannot calculate $left ^ $right")
}
private fun bitwiseor(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.intvalue!=null && right.intvalue !=null)
return LiteralValue(intvalue = left.intvalue.or(right.intvalue), position = left.position)
if(left.intvalue!=null && right.intvalue !=null) {
val litval = LiteralValue(intvalue = left.intvalue.or(right.intvalue))
litval.position = left.position
return litval
}
throw ExpressionException("cannot calculate $left | $right")
}
private fun bitwiseand(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.intvalue!=null && right.intvalue !=null)
return LiteralValue(intvalue = left.intvalue.and(right.intvalue), position = left.position)
if(left.intvalue!=null && right.intvalue !=null) {
val litval = LiteralValue(intvalue = left.intvalue.and(right.intvalue))
litval.position = left.position
return litval
}
throw ExpressionException("cannot calculate $left & $right")
}
@ -318,122 +337,138 @@ class ConstExprEvaluator {
}
private fun shiftright(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.intvalue!=null && right.intvalue !=null)
return LiteralValue(intvalue = left.intvalue.shr(right.intvalue), position = left.position)
if(left.intvalue!=null && right.intvalue !=null) {
val litval = LiteralValue(intvalue = left.intvalue.shr(right.intvalue))
litval.position = left.position
return litval
}
throw ExpressionException("cannot calculate $left >> $right")
}
private fun shiftleft(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.intvalue!=null && right.intvalue !=null)
return LiteralValue(intvalue = left.intvalue.shl(right.intvalue), position = left.position)
if(left.intvalue!=null && right.intvalue !=null) {
val litval = LiteralValue(intvalue = left.intvalue.shl(right.intvalue))
litval.position = left.position
return litval
}
throw ExpressionException("cannot calculate $left << $right")
}
private fun power(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot calculate $left ** $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue.toDouble().pow(right.intvalue).toInt(), position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue.toDouble().pow(right.floatvalue), position = left.position)
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue.toDouble().pow(right.intvalue).toInt())
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue.toDouble().pow(right.floatvalue))
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.intvalue), position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue), position = left.position)
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.intvalue))
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue))
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun plus(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot add $left and $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue + right.intvalue, position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue + right.floatvalue, position = left.position)
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue + right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue + right.floatvalue)
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.intvalue, position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue, position = left.position)
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue)
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun minus(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot subtract $left and $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue - right.intvalue, position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue - right.floatvalue, position = left.position)
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue - right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue - right.floatvalue)
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.intvalue, position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue, position = left.position)
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue)
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun multiply(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot multiply $left and $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue * right.intvalue, position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue * right.floatvalue, position = left.position)
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue * right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue * right.floatvalue)
right.strvalue!=null -> {
if(right.strvalue.length * left.intvalue > 65535) throw ExpressionException("string too large")
LiteralValue(strvalue = right.strvalue.repeat(left.intvalue), position = left.position)
LiteralValue(strvalue = right.strvalue.repeat(left.intvalue))
}
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.intvalue, position = left.position)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue, position = left.position)
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue)
else -> throw ExpressionException(error)
}
left.strvalue!=null -> when {
right.intvalue!=null -> {
if(left.strvalue.length * right.intvalue > 65535) throw ExpressionException("string too large")
LiteralValue(strvalue = left.strvalue.repeat(right.intvalue), position=left.position)
LiteralValue(strvalue = left.strvalue.repeat(right.intvalue))
}
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
private fun divide(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot divide $left by $right"
return when {
val litval = when {
left.intvalue!=null -> when {
right.intvalue!=null -> {
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero")
LiteralValue(intvalue = left.intvalue / right.intvalue, position = left.position)
LiteralValue(intvalue = left.intvalue / right.intvalue)
}
right.floatvalue!=null -> {
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero")
LiteralValue(floatvalue = left.intvalue / right.floatvalue, position = left.position)
LiteralValue(floatvalue = left.intvalue / right.floatvalue)
}
else -> throw ExpressionException(error)
}
left.floatvalue!=null -> when {
right.intvalue!=null -> {
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero")
LiteralValue(floatvalue = left.floatvalue / right.intvalue, position = left.position)
LiteralValue(floatvalue = left.floatvalue / right.intvalue)
}
right.floatvalue!=null -> {
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero")
LiteralValue(floatvalue = left.floatvalue / right.floatvalue, position = left.position)
LiteralValue(floatvalue = left.floatvalue / right.floatvalue)
}
else -> throw ExpressionException(error)
}
else -> throw ExpressionException(error)
}
litval.position = left.position
return litval
}
}

View File

@ -50,12 +50,14 @@ fun loadModule(filename: String) : Module {
// TODO the comments:
// tokens.commentTokens().forEach { println(it) }
// convert to Ast (optimizing this is done as a final step)
var moduleAst = parseTree.toAst(fileName.toString(),true)
// convert to Ast and optimize
var moduleAst = parseTree.toAst(fileName.toString(),true).optimized()
moduleAst.linkParents()
val checkResult = moduleAst.checkValid()
checkResult.forEach { it.printError() }
if(checkResult.isNotEmpty())
throw ParsingFailedError("There are ${checkResult.size} syntax errors in '$fileName'.")
throw ParsingFailedError("There are ${checkResult.size} errors in '$fileName'.")
// process imports
val lines = moduleAst.lines.toMutableList()
@ -65,7 +67,7 @@ fun loadModule(filename: String) : Module {
.map { Pair(it.first, executeImportDirective(it.second as Directive)) }
imports.reversed().forEach {
println("IMPORT [in ${moduleAst.name}]: $it")
println("IMPORT [in ${moduleAst.name}]: $it") // TODO
}
moduleAst.lines = lines
@ -77,14 +79,15 @@ fun executeImportDirective(import: Directive): Module {
if(import.directive!="%import" || import.args.size!=1 || import.args[0].name==null)
throw SyntaxError("invalid import directive", import)
return Module("???", emptyList(), null) // TODO
return Module("???", emptyList()) // TODO
}
fun main(args: Array<String>) {
println("Reading source file: ${args[0]}")
try {
val moduleAst = loadModule(args[0]).optimized()
val moduleAst = loadModule(args[0]).optimized() // one final global optimization
moduleAst.linkParents() // re-link parents in final configuration
moduleAst.lines.map {
println(it)

View File

@ -51,11 +51,15 @@ interface IAstProcessor {
fun process(expr: PrefixExpression): IExpression
fun process(expr: BinaryExpression): IExpression
fun process(directive: Directive): IStatement
fun process(block: Block): IStatement
fun process(decl: VarDecl): IStatement
}
interface Node {
val position: Position? // optional for the sake of easy unit testing
var parent: Node? // will be linked correctly later
fun linkParents(parent: Node)
}
@ -65,39 +69,84 @@ interface IStatement : Node {
data class Module(val name: String,
var lines: List<IStatement>,
override val position: Position? = null) : Node {
var lines: List<IStatement>) : Node {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent=parent
}
fun linkParents() {
parent = null
lines.forEach {it.linkParents(this)}
}
fun process(processor: IAstProcessor): Module {
lines = lines.map { it.process(processor) }
return this
}
}
data class Block(val name: String, val address: Int?, var statements: List<IStatement>,
override val position: Position? = null) : IStatement {
override fun process(processor: IAstProcessor) : IStatement {
statements = statements.map { it.process(processor) }
return this
data class Block(val name: String,
val address: Int?,
var statements: List<IStatement>) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
statements.forEach {it.linkParents(this)}
}
override fun process(processor: IAstProcessor) = processor.process(this)
}
data class Directive(val directive: String, val args: List<DirectiveArg>) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
args.forEach{it.linkParents(this)}
}
override fun process(processor: IAstProcessor) = processor.process(this)
}
data class DirectiveArg(val str: String?, val name: String?, val int: Int?) : Node {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
}
}
data class Directive(val directive: String, val args: List<DirectiveArg>,
override val position: Position? = null) : IStatement {
override fun process(processor: IAstProcessor) : IStatement {
return processor.process(this)
data class Label(val name: String) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
}
}
data class DirectiveArg(val str: String?, val name: String?, val int: Int?,
override val position: Position? = null) : Node
data class Label(val name: String,
override val position: Position? = null) : IStatement {
override fun process(processor: IAstProcessor) = this
}
data class Return(var values: List<IExpression>,
override val position: Position? = null) : IStatement {
data class Return(var values: List<IExpression>) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
values.forEach {it.linkParents(this)}
}
override fun process(processor: IAstProcessor): IStatement {
values = values.map { it.process(processor) }
return this
@ -105,52 +154,57 @@ data class Return(var values: List<IExpression>,
}
interface IVarDecl : IStatement {
val datatype: DataType
val arrayspec: ArraySpec?
val name: String
var value: IExpression?
}
data class ArraySpec(var x: IExpression, var y: IExpression?) : Node {
override var position: Position? = null
override var parent: Node? = null
data class ArraySpec(var x: IExpression,
var y: IExpression?,
override val position: Position? = null) : Node
override fun linkParents(parent: Node) {
this.parent = parent
x.linkParents(this)
y?.linkParents(this)
}
data class VarDecl(override val datatype: DataType,
override val arrayspec: ArraySpec?,
override val name: String,
override var value: IExpression?,
override val position: Position? = null) : IVarDecl {
override fun process(processor: IAstProcessor): IStatement {
value = value?.process(processor)
return this
fun process(processor: IAstProcessor) {
x = x.process(processor)
y = y?.process(processor)
}
}
data class ConstDecl(override val datatype: DataType,
override val arrayspec: ArraySpec?,
override val name: String,
override var value: IExpression?,
override val position: Position? = null) : IVarDecl {
override fun process(processor: IAstProcessor): IStatement {
value = value?.process(processor)
return this
}
enum class VarDeclType {
VAR,
CONST,
MEMORY
}
data class MemoryVarDecl(override val datatype: DataType,
override val arrayspec: ArraySpec?,
override val name: String,
override var value: IExpression?,
override val position: Position? = null) : IVarDecl {
override fun process(processor: IAstProcessor): IStatement {
value = value?.process(processor)
return this
data class VarDecl(val type: VarDeclType,
val datatype: DataType,
val arrayspec: ArraySpec?,
val name: String,
var value: IExpression?) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
arrayspec?.linkParents(this)
value?.linkParents(this)
}
override fun process(processor: IAstProcessor) = processor.process(this)
}
data class Assignment(var target: AssignTarget, val aug_op : String?, var value: IExpression,
override val position: Position? = null) : IStatement {
data class Assignment(var target: AssignTarget, val aug_op : String?, var value: IExpression) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
target.linkParents(this)
value.linkParents(this)
}
override fun process(processor: IAstProcessor): IStatement {
target = target.process(processor)
value = value.process(processor)
@ -158,8 +212,15 @@ data class Assignment(var target: AssignTarget, val aug_op : String?, var value:
}
}
data class AssignTarget(val register: Register?, val identifier: Identifier?,
override val position: Position? = null) : Node {
data class AssignTarget(val register: Register?, val identifier: Identifier?) : Node {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
identifier?.linkParents(this)
}
fun process(processor: IAstProcessor) = this // for now
}
@ -172,8 +233,15 @@ interface IExpression: Node {
// note: some expression elements are mutable, to be able to rewrite/process the expression tree
data class PrefixExpression(val operator: String, var expression: IExpression,
override val position: Position? = null) : IExpression {
data class PrefixExpression(val operator: String, var expression: IExpression) : IExpression {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
expression.linkParents(this)
}
override fun constValue(): LiteralValue? {
throw ExpressionException("should have been optimized away before const value was asked")
}
@ -182,8 +250,16 @@ data class PrefixExpression(val operator: String, var expression: IExpression,
}
data class BinaryExpression(var left: IExpression, val operator: String, var right: IExpression,
override val position: Position? = null) : IExpression {
data class BinaryExpression(var left: IExpression, val operator: String, var right: IExpression) : IExpression {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
left.linkParents(this)
right.linkParents(this)
}
override fun constValue(): LiteralValue? {
throw ExpressionException("should have been optimized away before const value was asked")
}
@ -194,15 +270,54 @@ data class BinaryExpression(var left: IExpression, val operator: String, var rig
data class LiteralValue(val intvalue: Int? = null,
val floatvalue: Double? = null,
val strvalue: String? = null,
val arrayvalue: List<IExpression>? = null,
override val position: Position? = null) : IExpression {
val arrayvalue: List<IExpression>? = null) : IExpression {
override var position: Position? = null
override var parent: Node? = null
fun asInt(): Int? {
return when {
intvalue!=null -> intvalue
floatvalue!=null -> floatvalue.toInt()
else -> {
if(strvalue!=null || arrayvalue!=null)
throw AstException("attempt to get int value from non-integer $this")
else null
}
}
}
fun asFloat(): Double? {
return when {
floatvalue!=null -> floatvalue
intvalue!=null -> intvalue.toDouble()
else -> {
if(strvalue!=null || arrayvalue!=null)
throw AstException("attempt to get float value from non-integer $this")
else null
}
}
}
override fun linkParents(parent: Node) {
this.parent = parent
arrayvalue?.forEach {it.linkParents(this)}
}
override fun constValue(): LiteralValue? = this
override fun process(processor: IAstProcessor) = this
}
data class RangeExpr(var from: IExpression, var to: IExpression,
override val position: Position? = null) : IExpression {
data class RangeExpr(var from: IExpression, var to: IExpression) : IExpression {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
from.linkParents(this)
to.linkParents(this)
}
override fun constValue(): LiteralValue? = null
override fun process(processor: IAstProcessor): IExpression {
from = from.process(processor)
@ -212,15 +327,27 @@ data class RangeExpr(var from: IExpression, var to: IExpression,
}
data class RegisterExpr(val register: Register,
override val position: Position? = null) : IExpression {
data class RegisterExpr(val register: Register) : IExpression {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
}
override fun constValue(): LiteralValue? = null
override fun process(processor: IAstProcessor) = this
}
data class Identifier(val name: String, val scope: List<String>,
override val position: Position? = null) : IExpression {
data class Identifier(val name: String, val scope: List<String>) : IExpression {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
}
override fun constValue(): LiteralValue? {
// @todo should look up the identifier and return its value if that is a compile time const
return null
@ -230,14 +357,28 @@ data class Identifier(val name: String, val scope: List<String>,
}
data class CallTarget(val address: Int?, val identifier: Identifier?,
override val position: Position? = null) : Node {
data class CallTarget(val address: Int?, val identifier: Identifier?) : Node {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
identifier?.linkParents(this)
}
fun process(processor: IAstProcessor) = this
}
data class PostIncrDecr(var target: AssignTarget, val operator: String,
override val position: Position? = null) : IStatement {
data class PostIncrDecr(var target: AssignTarget, val operator: String) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
target.linkParents(this)
}
override fun process(processor: IAstProcessor): IStatement {
target = target.process(processor)
return this
@ -245,8 +386,15 @@ data class PostIncrDecr(var target: AssignTarget, val operator: String,
}
data class Jump(var target: CallTarget,
override val position: Position? = null) : IStatement {
data class Jump(var target: CallTarget) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
target.linkParents(this)
}
override fun process(processor: IAstProcessor): IStatement {
target = target.process(processor)
return this
@ -254,8 +402,16 @@ data class Jump(var target: CallTarget,
}
data class FunctionCall(var target: CallTarget, var arglist: List<IExpression>,
override val position: Position? = null) : IExpression {
data class FunctionCall(var target: CallTarget, var arglist: List<IExpression>) : IExpression {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
target.linkParents(this)
arglist.forEach { it.linkParents(this) }
}
override fun constValue(): LiteralValue? {
// if the function is a built-in function and the args are consts, should evaluate!
return null
@ -269,8 +425,14 @@ data class FunctionCall(var target: CallTarget, var arglist: List<IExpression>,
}
data class InlineAssembly(val assembly: String,
override val position: Position? = null) : IStatement {
data class InlineAssembly(val assembly: String) : IStatement {
override var position: Position? = null
override var parent: Node? = null
override fun linkParents(parent: Node) {
this.parent = parent
}
override fun process(processor: IAstProcessor) = this
}
@ -279,14 +441,18 @@ data class InlineAssembly(val assembly: String,
fun ParserRuleContext.toPosition(withPosition: Boolean) : Position? {
return if (withPosition)
// note: be ware of TAB characters in the source text, they count as 1 column...
Position(start.line, start.charPositionInLine, stop.charPositionInLine+stop.text.length)
else
null
}
fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) =
Module(name, modulestatement().map { it.toAst(withPosition) }, toPosition(withPosition))
fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) : Module {
val module = Module(name, modulestatement().map { it.toAst(withPosition) })
module.position = toPosition(withPosition)
return module
}
fun il65Parser.ModulestatementContext.toAst(withPosition: Boolean) : IStatement {
@ -301,89 +467,112 @@ fun il65Parser.ModulestatementContext.toAst(withPosition: Boolean) : IStatement
fun il65Parser.BlockContext.toAst(withPosition: Boolean) : IStatement {
return Block(identifier().text,
val block= Block(identifier().text,
integerliteral()?.toAst(),
statement().map { it.toAst(withPosition) },
toPosition(withPosition))
statement().map { it.toAst(withPosition) })
block.position = toPosition(withPosition)
return block
}
fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
val vardecl = vardecl()
if(vardecl!=null) {
return VarDecl(vardecl.datatype().toAst(),
val decl= VarDecl(VarDeclType.VAR,
vardecl.datatype().toAst(),
vardecl.arrayspec()?.toAst(withPosition),
vardecl.identifier().text,
null,
vardecl.toPosition(withPosition))
null)
decl.position = vardecl.toPosition(withPosition)
return decl
}
val varinit = varinitializer()
if(varinit!=null) {
return VarDecl(varinit.datatype().toAst(),
val decl= VarDecl(VarDeclType.VAR,
varinit.datatype().toAst(),
varinit.arrayspec()?.toAst(withPosition),
varinit.identifier().text,
varinit.expression().toAst(withPosition),
varinit.toPosition(withPosition))
varinit.expression().toAst(withPosition))
decl.position = varinit.toPosition(withPosition)
return decl
}
val constdecl = constdecl()
if(constdecl!=null) {
val cvarinit = constdecl.varinitializer()
return ConstDecl(cvarinit.datatype().toAst(),
val decl = VarDecl(VarDeclType.CONST,
cvarinit.datatype().toAst(),
cvarinit.arrayspec()?.toAst(withPosition),
cvarinit.identifier().text,
cvarinit.expression().toAst(withPosition),
cvarinit.toPosition(withPosition))
cvarinit.expression().toAst(withPosition))
decl.position = cvarinit.toPosition(withPosition)
return decl
}
val memdecl = memoryvardecl()
if(memdecl!=null) {
val mvarinit = memdecl.varinitializer()
return MemoryVarDecl(mvarinit.datatype().toAst(),
val decl = VarDecl(VarDeclType.MEMORY,
mvarinit.datatype().toAst(),
mvarinit.arrayspec()?.toAst(withPosition),
mvarinit.identifier().text,
mvarinit.expression().toAst(withPosition),
mvarinit.toPosition(withPosition))
mvarinit.expression().toAst(withPosition))
decl.position = mvarinit.toPosition(withPosition)
return decl
}
val assign = assignment()
if (assign!=null) {
return Assignment(assign.assign_target().toAst(withPosition),
null, assign.expression().toAst(withPosition),
assign.toPosition(withPosition))
val ast =Assignment(assign.assign_target().toAst(withPosition),
null, assign.expression().toAst(withPosition))
ast.position = assign.toPosition(withPosition)
return ast
}
val augassign = augassignment()
if (augassign!=null)
return Assignment(augassign.assign_target().toAst(withPosition),
if (augassign!=null) {
val aug= Assignment(augassign.assign_target().toAst(withPosition),
augassign.operator.text,
augassign.expression().toAst(withPosition),
augassign.toPosition(withPosition))
augassign.expression().toAst(withPosition))
aug.position = augassign.toPosition(withPosition)
return aug
}
val post = postincrdecr()
if(post!=null)
return PostIncrDecr(post.assign_target().toAst(withPosition),
post.operator.text, post.toPosition(withPosition))
if(post!=null) {
val ast = PostIncrDecr(post.assign_target().toAst(withPosition), post.operator.text)
ast.position = post.toPosition(withPosition)
return ast
}
val directive = directive()?.toAst(withPosition)
if(directive!=null) return directive
val label=labeldef()
if(label!=null)
return Label(label.text, label.toPosition(withPosition))
if(label!=null) {
val lbl = Label(label.text)
lbl.position = label.toPosition(withPosition)
return lbl
}
val jump = unconditionaljump()
if(jump!=null)
return Jump(jump.call_location().toAst(withPosition), jump.toPosition(withPosition))
if(jump!=null) {
val ast = Jump(jump.call_location().toAst(withPosition))
ast.position = jump.toPosition(withPosition)
return ast
}
val returnstmt = returnstmt()
if(returnstmt!=null)
return Return(returnstmt.expression_list().toAst(withPosition))
val asm = inlineasm()
if(asm!=null)
return InlineAssembly(asm.INLINEASMBLOCK().text, asm.toPosition(withPosition))
if(asm!=null) {
val ast = InlineAssembly(asm.INLINEASMBLOCK().text)
ast.position = asm.toPosition(withPosition)
return ast
}
throw UnsupportedOperationException(text)
}
@ -392,20 +581,23 @@ fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
fun il65Parser.Call_locationContext.toAst(withPosition: Boolean) : CallTarget {
val address = integerliteral()?.toAst()
val identifier = identifier()
return if(identifier!=null)
CallTarget(address, identifier.toAst(withPosition), toPosition(withPosition))
else
CallTarget(address, scoped_identifier().toAst(withPosition), toPosition(withPosition))
val result =
if(identifier!=null) CallTarget(address, identifier.toAst(withPosition))
else CallTarget(address, scoped_identifier().toAst(withPosition))
result.position = toPosition(withPosition)
return result
}
fun il65Parser.Assign_targetContext.toAst(withPosition: Boolean) : AssignTarget {
val register = register()?.toAst()
val identifier = identifier()
return if(identifier!=null)
AssignTarget(register, identifier.toAst(withPosition), toPosition(withPosition))
val result = if(identifier!=null)
AssignTarget(register, identifier.toAst(withPosition))
else
AssignTarget(register, scoped_identifier()?.toAst(withPosition), toPosition(withPosition))
AssignTarget(register, scoped_identifier()?.toAst(withPosition))
result.position = toPosition(withPosition)
return result
}
@ -415,22 +607,29 @@ fun il65Parser.RegisterContext.toAst() = Register.valueOf(text.toUpperCase())
fun il65Parser.DatatypeContext.toAst() = DataType.valueOf(text.toUpperCase())
fun il65Parser.ArrayspecContext.toAst(withPosition: Boolean) = ArraySpec(
expression(0).toAst(withPosition),
if (expression().size > 1) expression(1).toAst(withPosition) else null,
toPosition(withPosition)
)
fun il65Parser.ArrayspecContext.toAst(withPosition: Boolean) : ArraySpec {
val spec = ArraySpec(
expression(0).toAst(withPosition),
if (expression().size > 1) expression(1).toAst(withPosition) else null)
spec.position = toPosition(withPosition)
return spec
}
fun il65Parser.DirectiveContext.toAst(withPosition: Boolean) =
Directive(directivename.text, directivearg().map { it.toAst(withPosition) }, toPosition(withPosition))
fun il65Parser.DirectiveContext.toAst(withPosition: Boolean) : Directive {
val dir = Directive(directivename.text, directivearg().map { it.toAst(withPosition) })
dir.position = toPosition(withPosition)
return dir
}
fun il65Parser.DirectiveargContext.toAst(withPosition: Boolean) =
DirectiveArg(stringliteral()?.text,
identifier()?.text,
integerliteral()?.toAst(),
toPosition(withPosition))
fun il65Parser.DirectiveargContext.toAst(withPosition: Boolean) : DirectiveArg {
val darg = DirectiveArg(stringliteral()?.text,
identifier()?.text,
integerliteral()?.toAst())
darg.position = toPosition(withPosition)
return darg
}
fun il65Parser.IntegerliteralContext.toAst(): Int {
@ -449,18 +648,23 @@ fun il65Parser.ExpressionContext.toAst(withPosition: Boolean) : IExpression {
val litval = literalvalue()
if(litval!=null) {
val booleanlit = litval.booleanliteral()?.toAst()
if(booleanlit!=null)
return LiteralValue(intvalue = if(booleanlit) 1 else 0)
return LiteralValue(litval.integerliteral()?.toAst(),
litval.floatliteral()?.toAst(),
litval.stringliteral()?.text,
litval.arrayliteral()?.toAst(withPosition),
litval.toPosition(withPosition)
)
val value =
if(booleanlit!=null)
LiteralValue(intvalue = if(booleanlit) 1 else 0)
else
LiteralValue(litval.integerliteral()?.toAst(),
litval.floatliteral()?.toAst(),
litval.stringliteral()?.text,
litval.arrayliteral()?.toAst(withPosition))
value.position = litval.toPosition(withPosition)
return value
}
if(register()!=null)
return RegisterExpr(register().toAst(), register().toPosition(withPosition))
if(register()!=null) {
val reg = RegisterExpr(register().toAst())
reg.position = register().toPosition(withPosition)
return reg
}
if(identifier()!=null)
return identifier().toAst(withPosition)
@ -468,28 +672,37 @@ fun il65Parser.ExpressionContext.toAst(withPosition: Boolean) : IExpression {
if(scoped_identifier()!=null)
return scoped_identifier().toAst(withPosition)
if(bop!=null)
return BinaryExpression(left.toAst(withPosition),
if(bop!=null) {
val expr = BinaryExpression(left.toAst(withPosition),
bop.text,
right.toAst(withPosition),
toPosition(withPosition))
right.toAst(withPosition))
expr.position = toPosition(withPosition)
return expr
}
if(prefix!=null)
return PrefixExpression(prefix.text,
expression(0).toAst(withPosition),
toPosition(withPosition))
if(prefix!=null) {
val expr = PrefixExpression(prefix.text,
expression(0).toAst(withPosition))
expr.position = toPosition(withPosition)
return expr
}
val funcall = functioncall()
if(funcall!=null) {
val location = funcall.call_location().toAst(withPosition)
return if(funcall.expression_list()==null)
FunctionCall(location, emptyList(), funcall.toPosition(withPosition))
val fcall = if(funcall.expression_list()==null)
FunctionCall(location, emptyList())
else
FunctionCall(location, funcall.expression_list().toAst(withPosition), funcall.toPosition(withPosition))
FunctionCall(location, funcall.expression_list().toAst(withPosition))
fcall.position = funcall.toPosition(withPosition)
return fcall
}
if (rangefrom!=null && rangeto!=null)
return RangeExpr(rangefrom.toAst(withPosition), rangeto.toAst(withPosition), toPosition(withPosition))
if (rangefrom!=null && rangeto!=null) {
val rexp = RangeExpr(rangefrom.toAst(withPosition), rangeto.toAst(withPosition))
rexp.position = toPosition(withPosition)
return rexp
}
if(childCount==3 && children[0].text=="(" && children[2].text==")")
return expression(0).toAst(withPosition) // expression within ( )
@ -502,7 +715,9 @@ fun il65Parser.Expression_listContext.toAst(withPosition: Boolean) = expression(
fun il65Parser.IdentifierContext.toAst(withPosition: Boolean) : Identifier {
return Identifier(text, emptyList(), toPosition(withPosition))
val ident = Identifier(text, emptyList())
ident.position = toPosition(withPosition)
return ident
}
@ -510,7 +725,9 @@ fun il65Parser.Scoped_identifierContext.toAst(withPosition: Boolean) : Identifie
val names = NAME()
val name = names.last().text
val scope = names.take(names.size-1)
return Identifier(name, scope.map { it.text }, toPosition(withPosition))
val ident = Identifier(name, scope.map { it.text })
ident.position = toPosition(withPosition)
return ident
}