diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt index 1f1378495..118f5f5e2 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt @@ -288,8 +288,10 @@ private fun Prog8ANTLRParser.FunctioncallContext.toAst(): FunctionCall { FunctionCall(location, expression_list().toAst().toMutableList(), toPosition()) } -private fun Prog8ANTLRParser.InlineasmContext.toAst() = - InlineAssembly(INLINEASMBLOCK().text, toPosition()) +private fun Prog8ANTLRParser.InlineasmContext.toAst(): InlineAssembly { + val text = INLINEASMBLOCK().text + return InlineAssembly(text.substring(2, text.length-2), toPosition()) +} private fun Prog8ANTLRParser.ReturnstmtContext.toAst() : Return { return Return(expression()?.toAst(), toPosition()) @@ -356,8 +358,7 @@ private fun Prog8ANTLRParser.DirectiveargContext.toAst() : DirectiveArg { val str = stringliteral() if(str?.ALT_STRING_ENCODING() != null) throw SyntaxError("can't use alternate string s for directive arguments", toPosition()) - - return DirectiveArg(stringliteral()?.text, identifier()?.text, integerliteral()?.toAst()?.number?.toUInt(), toPosition()) + return DirectiveArg(str?.text?.substring(1, text.length-1), identifier()?.text, integerliteral()?.toAst()?.number?.toUInt(), toPosition()) } private fun Prog8ANTLRParser.IntegerliteralContext.toAst(): NumericLiteral { @@ -480,11 +481,15 @@ private fun Prog8ANTLRParser.ExpressionContext.toAst() : Expression { throw FatalAstException(text) } -private fun Prog8ANTLRParser.CharliteralContext.toAst(): CharLiteral = - CharLiteral(unescape(this.SINGLECHAR().text, toPosition())[0], this.ALT_STRING_ENCODING() != null, toPosition()) +private fun Prog8ANTLRParser.CharliteralContext.toAst(): CharLiteral { + val text = this.SINGLECHAR().text + return CharLiteral(unescape(text.substring(1, text.length-1), toPosition())[0], this.ALT_STRING_ENCODING() != null, toPosition()) +} -private fun Prog8ANTLRParser.StringliteralContext.toAst(): StringLiteralValue = - StringLiteralValue(unescape(this.STRING().text, toPosition()), ALT_STRING_ENCODING()!=null, toPosition()) +private fun Prog8ANTLRParser.StringliteralContext.toAst(): StringLiteralValue { + val text=this.STRING().text + return StringLiteralValue(unescape(text.substring(1, text.length-1), toPosition()), ALT_STRING_ENCODING() != null, toPosition()) +} private fun Prog8ANTLRParser.ArrayindexedContext.toAst(): ArrayIndexedExpression { return ArrayIndexedExpression(scoped_identifier().toAst(), diff --git a/compilerAst/src/prog8/ast/antlr/EscapeChars.kt b/compilerAst/src/prog8/ast/antlr/EscapeChars.kt index 7752272e1..dd800d696 100644 --- a/compilerAst/src/prog8/ast/antlr/EscapeChars.kt +++ b/compilerAst/src/prog8/ast/antlr/EscapeChars.kt @@ -2,6 +2,7 @@ package prog8.ast.antlr import prog8.ast.base.Position import prog8.ast.base.SyntaxError +import kotlin.NumberFormatException fun escape(str: String): String { val es = str.map { @@ -32,12 +33,24 @@ fun unescape(str: String, position: Position): String { '"' -> '"' '\'' -> '\'' 'u' -> { - "${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}".toInt(16).toChar() + try { + "${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}".toInt(16).toChar() + } catch (sb: StringIndexOutOfBoundsException) { + throw SyntaxError("invalid \\u escape sequence", position) + } catch (nf: NumberFormatException) { + throw SyntaxError("invalid \\u escape sequence", position) + } } 'x' -> { // special hack 0x8000..0x80ff will be outputted verbatim without encoding - val hex = ("" + iter.nextChar() + iter.nextChar()).toInt(16) - (0x8000 + hex).toChar() + try { + val hex = ("" + iter.nextChar() + iter.nextChar()).toInt(16) + (0x8000 + hex).toChar() + } catch (sb: StringIndexOutOfBoundsException) { + throw SyntaxError("invalid \\x escape sequence", position) + } catch (nf: NumberFormatException) { + throw SyntaxError("invalid \\x escape sequence", position) + } } else -> throw SyntaxError("invalid escape char in string: \\$ec", position) }) diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt index 1a9981ccc..7ff2b88e9 100644 --- a/compilerAst/src/prog8/ast/statements/AstStatements.kt +++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt @@ -706,6 +706,7 @@ class Subroutine(override val name: String, return KeepAresult(false, saveAonReturn) } + // TODO fix this to also look in asm nodes in subscopes fun amountOfRtsInAsm(): Int = statements .asSequence() .filter { it is InlineAssembly } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index cf98e7348..b336174b5 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,10 @@ TODO For next compiler release (7.5) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +fix: cx16.r0 isn't seen as zeropage so @(cx16.r0) still copies it to temp zp +fix: when statements generate unneeded branches to choice_end? +fix: amountOfRtsInAsm() look in subscopes too + Blocked by an official Commander-x16 v39 release diff --git a/examples/test.p8 b/examples/test.p8 index d804ba571..8b4250111 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,28 +4,13 @@ main { sub start() { - ubyte num_banks = cx16.numbanks() - txt.print("number of ram banks ") - txt.print_ub(num_banks) - txt.print(" = ") - txt.print_uw($0008*num_banks) - txt.print("kb\n") - print_banks() - cx16.rambank(55) - cx16.rombank(3) - print_banks() - } - - sub print_banks() { - ubyte rambank = cx16.getrambank() - ubyte rombank = cx16.getrombank() - cx16.rombank(0) ; enable kernal - txt.print("ram bank ") - txt.print_ub(rambank) - txt.nl() - txt.print("rom bank ") - txt.print_ub(rombank) - txt.nl() - cx16.rombank(rombank) + str text = "hello" + txt.print(text) + txt.print("hello2\u0032") + ubyte chr1 = '\x33' + txt.chrout(chr1) + %asm {{ + nop + }} } } diff --git a/parser/antlr/Prog8ANTLR.g4 b/parser/antlr/Prog8ANTLR.g4 index cda2a1f27..9308f125e 100644 --- a/parser/antlr/Prog8ANTLR.g4 +++ b/parser/antlr/Prog8ANTLR.g4 @@ -33,31 +33,16 @@ ALT_STRING_ENCODING: '@'; FLOAT_NUMBER : FNUMBER (('E'|'e') ('+' | '-')? FNUMBER)? ; // sign comes later from unary expression fragment FNUMBER : ('0' .. '9') + ('.' ('0' .. '9') +)? ; -fragment STRING_ESCAPE_SEQ : '\\' . | '\\' EOL; +fragment STRING_ESCAPE_SEQ : '\\' . | '\\x' . . | '\\u' . . . .; STRING : '"' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f"] )* '"' - { - // get rid of the enclosing quotes - String s = getText(); - setText(s.substring(1, s.length() - 1)); - } ; INLINEASMBLOCK : '{{' .+? '}}' - { - // get rid of the enclosing double braces - String s = getText(); - setText(s.substring(2, s.length() - 2)); - } ; SINGLECHAR : - '\'' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f"] ) '\'' - { - // get rid of the enclosing quotes - String s = getText(); - setText(s.substring(1, s.length() - 1)); - } + '\'' ( STRING_ESCAPE_SEQ | ~[\\\r\n\f'] ) '\'' ; ZEROPAGE :