1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-05-31 18:41:30 +00:00

Character literals

This commit is contained in:
Karol Stasiak 2018-04-02 21:06:18 +02:00
parent 95375378ed
commit d6995091cf
4 changed files with 59 additions and 3 deletions

View File

@ -6,6 +6,8 @@
* Added multiple new text codecs.
* Added character literals.
* Fixed several bugs, most importantly invalid offsets for branching instructions.
* Other improvements.

View File

@ -36,7 +36,7 @@ Currently available encodings:
* `bbc` BBC Micro and ZX Spectrum character set
* `jis` JIS X 0201
* `jis` or `jisx` JIS X 0201
* `iso_de`, `iso_no`, `iso_se`, `iso_yu` various variants of ISO/IEC-646
@ -46,6 +46,13 @@ When programming for Commodore,
use `pet` for strings you're printing using standard I/O routines
and `scr` for strings you're copying to screen memory directly.
## Character literals
Character literals are surrounded by single quotes and followed by the name of the encoding:
'x' ascii
From the type system point of view, they are constants of type byte.
## Array initialisers

View File

@ -53,6 +53,28 @@ case class MfParser(filename: String, input: String, currentDirectory: String, o
// def operator: P[String] = P(CharsWhileIn("!-+*/><=~|&^", min=1).!) // TODO: only valid operators
private val invalidCharLiteralTypes = Set[Int](
Character.LINE_SEPARATOR,
Character.PARAGRAPH_SEPARATOR,
Character.CONTROL,
Character.PRIVATE_USE,
Character.SURROGATE,
Character.UNASSIGNED)
def charAtom: P[LiteralExpression] = for {
p <- position()
c <- "'" ~/ CharPred(c => c >= ' ' && !invalidCharLiteralTypes(Character.getType(c))).! ~/ "'"
co <- HWS ~ codec
} yield {
co.encode(Some(p), c.charAt(0)) match {
case List(value) =>
LiteralExpression(value, 1)
case _ =>
ErrorReporting.error(s"Character `$c` cannot be encoded as one byte", Some(p))
LiteralExpression(0, 1)
}
}
// TODO: 3-byte types
def size(value: Int, wordLiteral: Boolean, longLiteral: Boolean): Int =
if (value > 255 || value < -128 || wordLiteral)
@ -120,7 +142,7 @@ case class MfParser(filename: String, input: String, currentDirectory: String, o
LiteralExpression(value, size(value, s.length > 4, s.length > 8)).pos(p)
}
val literalAtom: P[LiteralExpression] = binaryAtom | hexAtom | octalAtom | quaternaryAtom | decimalAtom
val literalAtom: P[LiteralExpression] = charAtom | binaryAtom | hexAtom | octalAtom | quaternaryAtom | decimalAtom
val atom: P[Expression] = P(literalAtom | (position() ~ identifier).map { case (p, i) => VariableExpression(i).pos(p) })
@ -200,7 +222,7 @@ case class MfParser(filename: String, input: String, currentDirectory: String, o
val doubleQuotedString: P[List[Char]] = P("\"" ~/ CharsWhile(c => c != '\"' && c != '\n' && c != '\r').! ~ "\"").map(_.toList)
val codec: P[TextCodec] = P(position() ~ identifier).map {
def codec: P[TextCodec] = P(position() ~ identifier).map {
case (_, "ascii") => TextCodec.Ascii
case (_, "petscii") => TextCodec.Petscii
case (_, "pet") => TextCodec.Petscii

View File

@ -0,0 +1,25 @@
package millfork.test
import millfork.test.emu.{EmuBenchmarkRun, EmuUnoptimizedRun}
import org.scalatest.{FunSuite, Matchers}
/**
* @author Karol Stasiak
*/
class TextCodecSuite extends FunSuite with Matchers {
test("Char literals") {
val m = EmuUnoptimizedRun(
"""
| void main() {
| if 'a'ascii != 'a' ascii { poke($bfff, 0) }
| if '¥'jis != '\' ascii { poke($bffe, 0) }
| if '£'pet != '\' ascii { poke($bffd, 0) }
| if '£'bbc != 'é' iso_se { poke($bffc, 0) }
| }
| macro asm void poke(word const addr, byte a) {
| STA addr
| }
""".stripMargin)
}
}