summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby Bingham <koorogi@koorogi.info>2017-01-12 20:05:45 -0600
committerBobby Bingham <koorogi@koorogi.info>2017-01-15 23:18:52 -0600
commitcf366387449dcf9d34875a7d76f3b79c1e231d6f (patch)
treeb892febf08e3c5791e414c9cdc011477a9420ae1
parent239ee7648658b77b217f5c8142ef887612516af4 (diff)
nqasm: Initial stab at a lexer and parser
So far, this only understands instructions, but no operands or labels. It doesn't handle bad input gracefully. It's just enough to test the basics.
-rw-r--r--Makefile30
-rw-r--r--lexer.l61
-rw-r--r--nqasm.c20
-rw-r--r--nqasm.h11
-rw-r--r--parser.y156
5 files changed, 278 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..554c540
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+OPTFLAGS = -Os
+CFLAGS = -std=c99 -D_POSIX_C_SOURCE=200809L $(OPTFLAGS)
+
+GENSRCS = lexer.c parser.c
+GENHDRS = lexer.h parser.h
+SRCS = $(sort $(wildcard *.c) $(GENSRCS))
+OBJS = $(SRCS:.c=.o)
+TARGET = nqasm
+
+all: $(TARGET)
+
+clean:
+ rm -f $(GENSRCS) $(GENHDRS) $(OBJS) $(TARGET)
+
+lexer.c lexer.h: lexer.l
+ flex $<
+
+parser.c parser.h: parser.y
+ bison $<
+
+lexer.o: parser.h
+parser.o: lexer.h
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+$(TARGET): $(OBJS)
+ $(CC) $(CFLAGS) $^ -o $@
+
+.PHONY: all clean
diff --git a/lexer.l b/lexer.l
new file mode 100644
index 0000000..9a34d66
--- /dev/null
+++ b/lexer.l
@@ -0,0 +1,61 @@
+%{
+
+#include "parser.h"
+
+%}
+
+%option outfile="lexer.c" header-file="lexer.h"
+%option noyywrap never-interactive
+
+%s inst
+%s args
+
+COMMENT #[^\n]*
+SP [ \t]
+EOI [ \t\n#]
+
+%%
+
+<INITIAL>{SP}+ { BEGIN(inst); return T_SPACE; }
+
+<inst>add/{EOI} { BEGIN(args); return T_ADD; }
+<inst>sub/{EOI} { BEGIN(args); return T_SUB; }
+<inst>mul/{EOI} { BEGIN(args); return T_MUL; }
+<inst>div/{EOI} { BEGIN(args); return T_DIV; }
+<inst>and/{EOI} { BEGIN(args); return T_AND; }
+<inst>or/{EOI} { BEGIN(args); return T_OR; }
+<inst>xor/{EOI} { BEGIN(args); return T_XOR; }
+<inst>lsl/{EOI} { BEGIN(args); return T_LSL; }
+<inst>lsr/{EOI} { BEGIN(args); return T_LSR; }
+<inst>asl/{EOI} { BEGIN(args); return T_ASL; }
+<inst>asr/{EOI} { BEGIN(args); return T_ASR; }
+<inst>rol/{EOI} { BEGIN(args); return T_ROL; }
+<inst>ror/{EOI} { BEGIN(args); return T_ROR; }
+<inst>not/{EOI} { BEGIN(args); return T_NOT; }
+<inst>neg/{EOI} { BEGIN(args); return T_NEG; }
+<inst>btc/{EOI} { BEGIN(args); return T_BTC; }
+<inst>bts/{EOI} { BEGIN(args); return T_BTS; }
+<inst>mov/{EOI} { BEGIN(args); return T_MOV; }
+<inst>st\.b/{EOI} { BEGIN(args); return T_ST_B; }
+<inst>st\.w/{EOI} { BEGIN(args); return T_ST_W; }
+<inst>ld\.bl/{EOI} { BEGIN(args); return T_LD_BL; }
+<inst>ld\.bh/{EOI} { BEGIN(args); return T_LD_BH; }
+<inst>ld\.w/{EOI} { BEGIN(args); return T_LD_W; }
+<inst>ldi\.bl/{EOI} { BEGIN(args); return T_LDI_BL; }
+<inst>ldi\.bh/{EOI} { BEGIN(args); return T_LDI_BH; }
+<inst>beq/{EOI} { BEGIN(args); return T_BEQ; }
+<inst>bne/{EOI} { BEGIN(args); return T_BNE; }
+<inst>bgt/{EOI} { BEGIN(args); return T_BGT; }
+<inst>bge/{EOI} { BEGIN(args); return T_BGE; }
+<inst>blt/{EOI} { BEGIN(args); return T_BLT; }
+<inst>ble/{EOI} { BEGIN(args); return T_BLE; }
+<inst>bra/{EOI} { BEGIN(args); return T_BRA; }
+<inst>jmp/{EOI} { BEGIN(args); return T_JMP; }
+<inst>addpc/{EOI} { BEGIN(args); return T_ADDPC; }
+<inst>nop/{EOI} { BEGIN(args); return T_NOP; }
+
+{SP}*{COMMENT}?\n { BEGIN(INITIAL); return T_EOL; }
+{SP}*{COMMENT} { BEGIN(INITIAL); return T_SPACE; }
+{SP}+ { return T_SPACE; }
+
+%%
diff --git a/nqasm.c b/nqasm.c
new file mode 100644
index 0000000..a42f8f4
--- /dev/null
+++ b/nqasm.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+#include "mnemonics.h"
+#include "nqasm.h"
+
+#include "lexer.h"
+#include "parser.h"
+
+void add_instruction(const struct instruction *i)
+{
+ const struct mnemonic *m = &mnemonics[i->mnem];
+ printf("%04x\n", m->bits);
+}
+
+int main(int argc, char **argv)
+{
+ yyparse();
+ return 0;
+}
+
diff --git a/nqasm.h b/nqasm.h
new file mode 100644
index 0000000..3712849
--- /dev/null
+++ b/nqasm.h
@@ -0,0 +1,11 @@
+#ifndef NQ_NQASM_H
+#define NQ_NQASM_H
+
+struct instruction {
+ int mnem;
+};
+
+void add_instruction(const struct instruction *);
+
+#endif
+
diff --git a/parser.y b/parser.y
new file mode 100644
index 0000000..78bf123
--- /dev/null
+++ b/parser.y
@@ -0,0 +1,156 @@
+%{
+
+#include <stdio.h>
+
+#include "lexer.h"
+#include "mnemonics.h"
+
+void yyerror(const char *msg)
+{
+ fprintf(stderr, "%s\n", msg);
+}
+
+#define INSTRUCTION(mnem) (struct instruction) { MNEM_ ## mnem }
+
+%}
+
+%output "parser.c"
+%defines "parser.h"
+
+%code requires {
+ #include "nqasm.h"
+}
+
+%union {
+ struct instruction inst;
+}
+
+%token END 0 "end of file"
+
+%token T_SPACE
+%token T_EOL
+
+%token T_ADD
+%token T_SUB
+%token T_MUL
+%token T_DIV
+%token T_AND
+%token T_OR
+%token T_XOR
+%token T_LSL
+%token T_LSR
+%token T_ASL
+%token T_ASR
+%token T_ROL
+%token T_ROR
+%token T_NOT
+%token T_NEG
+%token T_BTC
+%token T_BTS
+%token T_MOV
+%token T_ST_B
+%token T_ST_W
+%token T_LD_BL
+%token T_LD_BH
+%token T_LD_W
+%token T_LDI_BL
+%token T_LDI_BH
+%token T_BEQ
+%token T_BNE
+%token T_BGT
+%token T_BGE
+%token T_BLT
+%token T_BLE
+%token T_BRA
+%token T_JMP
+%token T_ADDPC
+%token T_NOP
+
+%type <inst> inst
+%%
+
+input: %empty
+ | input line
+ ;
+
+line: T_SPACE inst eol
+ { add_instruction(&$2); }
+ | eol
+ ;
+
+inst: T_ADD
+ { $$ = INSTRUCTION(ADD); }
+ | T_SUB
+ { $$ = INSTRUCTION(SUB); }
+ | T_MUL
+ { $$ = INSTRUCTION(MUL); }
+ | T_DIV
+ { $$ = INSTRUCTION(DIV); }
+ | T_AND
+ { $$ = INSTRUCTION(AND); }
+ | T_OR
+ { $$ = INSTRUCTION(OR); }
+ | T_XOR
+ { $$ = INSTRUCTION(XOR); }
+ | T_LSL
+ { $$ = INSTRUCTION(LSL); }
+ | T_LSR
+ { $$ = INSTRUCTION(LSR); }
+ | T_ASL
+ { $$ = INSTRUCTION(ASL); }
+ | T_ASR
+ { $$ = INSTRUCTION(ASR); }
+ | T_ROL
+ { $$ = INSTRUCTION(ROL); }
+ | T_ROR
+ { $$ = INSTRUCTION(ROR); }
+ | T_NOT
+ { $$ = INSTRUCTION(NOT); }
+ | T_NEG
+ { $$ = INSTRUCTION(NEG); }
+ | T_BTC
+ { $$ = INSTRUCTION(BTC); }
+ | T_BTS
+ { $$ = INSTRUCTION(BTS); }
+ | T_MOV
+ { $$ = INSTRUCTION(MOV); }
+ | T_ST_B
+ { $$ = INSTRUCTION(ST_B); }
+ | T_ST_W
+ { $$ = INSTRUCTION(ST_W); }
+ | T_LD_BL
+ { $$ = INSTRUCTION(LD_BL); }
+ | T_LD_BH
+ { $$ = INSTRUCTION(LD_BH); }
+ | T_LD_W
+ { $$ = INSTRUCTION(LD_W); }
+ | T_LDI_BL
+ { $$ = INSTRUCTION(LDI_BL); }
+ | T_LDI_BH
+ { $$ = INSTRUCTION(LDI_BH); }
+ | T_BEQ
+ { $$ = INSTRUCTION(BEQ); }
+ | T_BNE
+ { $$ = INSTRUCTION(BNE); }
+ | T_BGT
+ { $$ = INSTRUCTION(BGT); }
+ | T_BGE
+ { $$ = INSTRUCTION(BGE); }
+ | T_BLT
+ { $$ = INSTRUCTION(BLT); }
+ | T_BLE
+ { $$ = INSTRUCTION(BLE); }
+ | T_BRA
+ { $$ = INSTRUCTION(BRA); }
+ | T_JMP
+ { $$ = INSTRUCTION(JMP); }
+ | T_ADDPC
+ { $$ = INSTRUCTION(ADDPC); }
+ | T_NOP
+ { $$ = INSTRUCTION(NOP); }
+ ;
+
+eol: T_EOL
+ | T_SPACE END
+ | END
+ ;