diff options
-rw-r--r-- | lex.c | 21 | ||||
-rw-r--r-- | output.c | 2 | ||||
-rw-r--r-- | test/Makefile | 2 | ||||
-rw-r--r-- | test/full-pipeline/001-nop.test | 1 | ||||
-rwxr-xr-x | test/full-pipeline/run-full-pipeline.sh | 75 |
5 files changed, 94 insertions, 7 deletions
@@ -63,6 +63,13 @@ static int add_token(struct token t) { return 0; } +static struct token last_token(void) { + if (tokens_count) + return tokens[tokens_count - 1]; + else + return (struct token){ .type = TOKEN_EOL }; +} + static int lex_comma(struct token *t) { if (expect(',')) return 1; @@ -251,11 +258,6 @@ static int lex_misc(struct token *t) { int i = 0; int j = 0; - if (!isalpha(buffer[column])) { - emit("Error: '%c' cannot start an identifier\n", buffer[column]); - return 1; - } - for (i = column; isalnum(buffer[i]); i++) { ; } @@ -278,6 +280,12 @@ static int lex_misc(struct token *t) { /* skip over colon, but don't have included it in the name */ if (t->type == TOKEN_LABEL) { column++; + } else { + /* non-labels must start with an alpha */ + if (!isalpha(t->s_val[0])) { + emit("Error: '%c' cannot start an identifier\n", t->s_val[0]); + return 1; + } } return 0; } @@ -356,7 +364,8 @@ int lex_line(void) { break; /* FIXME add support for expressions like `addi $0, $0, (1+2*3) */ default: - if (isdigit(buffer[column])) { + /* allow numerical to start label only when at start of line */ + if (isdigit(buffer[column]) && last_token().type != TOKEN_EOL) { ret = lex_num(&tok); } else { ret = lex_misc(&tok); @@ -165,7 +165,7 @@ int output_single(FILE *f, struct label *labels, size_t labels_count, struct ins } if (len == 2) { -//#define RAW +#define RAW #ifdef RAW fputc(0xFF & (i >> 24), f); fputc(0xFF & (i >> 16), f); diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..c2407c7 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,2 @@ +test: + ./full-pipeline/run-full-pipeline.sh diff --git a/test/full-pipeline/001-nop.test b/test/full-pipeline/001-nop.test new file mode 100644 index 0000000..c27745a --- /dev/null +++ b/test/full-pipeline/001-nop.test @@ -0,0 +1 @@ +nop diff --git a/test/full-pipeline/run-full-pipeline.sh b/test/full-pipeline/run-full-pipeline.sh new file mode 100755 index 0000000..34d4ff0 --- /dev/null +++ b/test/full-pipeline/run-full-pipeline.sh @@ -0,0 +1,75 @@ +#!/bin/bash -e + +# +# Script for running all of the automated which will go from source to binary, +# to source to binary, and compare the two binaries. +# These tests won't find symmetrical errors (e.g. incorrectly translating 'add' +# into the wrong opcode, and that same opcode back to 'add'), but provide some +# level of confidence that the disassembler and assembler at least have parity. +# Checking lower level things is the job of other tests. +# + +fail() { + echo -e '[\e[1;31mFAIL\e[0m] '"$1:" "$2" +} + +pass() { + echo -e '[\e[0;32mPASS\e[0m] '"$1" +} + +clean() { + echo "Removing work dir $WORK" + rm -r "$WORK" +} + +trap clean EXIT + +check_expected() +{ + [ -z "$1" ] && echo WARN: check_expected called with no argument + if [ -f "$1.expected" ] ; then + if ! diff "$1.expected" "$1.tmp" >/dev/null; then + fail "$1 didn't match expected" + fi + fi +} + +WORK=$(mktemp -d) +pushd $(dirname "$0") >/dev/null +export ASM="$PWD/../../assembler" +export DISASM="$PWD/../../disassembler" +has_failure=0 + +for first_stage_asm in *.test ; do + first_stage_bin="$WORK/first_stage.bin" + second_stage_asm="$WORK/second_stage.asm" + second_stage_bin="$WORK/second_stage.bin" + + # Assemble test code + if ! "$ASM" "$first_stage_asm" "$first_stage_bin" ; then + fail "$first_stage_asm" "first stage assembly failed" + continue + fi + + # Disassemble test code and re-assemble that disassembly + if ! "$DISASM" "$first_stage_bin" > "$second_stage_asm" ; then + fail "$first_stage_asm" "first stage disassembly failed" + continue + fi + if ! "$ASM" "$second_stage_asm" "$second_stage_bin" ; then + fail "$first_stage_asm" "second stage assembly failed" + continue + fi + + # first stage bin and second stage identical for test pass + if diff "$first_stage_bin" "$second_stage_bin"; then + pass "$first_stage_asm" + else + fail "$first_stage_asm" "binary mismatch" + has_failure=1 + fi + +done +popd >/dev/null + +exit "$has_failure" |