From cf366387449dcf9d34875a7d76f3b79c1e231d6f Mon Sep 17 00:00:00 2001 From: Bobby Bingham Date: Thu, 12 Jan 2017 20:05:45 -0600 Subject: 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. --- Makefile | 30 ++++++++++++ lexer.l | 61 +++++++++++++++++++++++++ nqasm.c | 20 ++++++++ nqasm.h | 11 +++++ parser.y | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 278 insertions(+) create mode 100644 Makefile create mode 100644 lexer.l create mode 100644 nqasm.c create mode 100644 nqasm.h create mode 100644 parser.y 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#] + +%% + +{SP}+ { BEGIN(inst); return T_SPACE; } + +add/{EOI} { BEGIN(args); return T_ADD; } +sub/{EOI} { BEGIN(args); return T_SUB; } +mul/{EOI} { BEGIN(args); return T_MUL; } +div/{EOI} { BEGIN(args); return T_DIV; } +and/{EOI} { BEGIN(args); return T_AND; } +or/{EOI} { BEGIN(args); return T_OR; } +xor/{EOI} { BEGIN(args); return T_XOR; } +lsl/{EOI} { BEGIN(args); return T_LSL; } +lsr/{EOI} { BEGIN(args); return T_LSR; } +asl/{EOI} { BEGIN(args); return T_ASL; } +asr/{EOI} { BEGIN(args); return T_ASR; } +rol/{EOI} { BEGIN(args); return T_ROL; } +ror/{EOI} { BEGIN(args); return T_ROR; } +not/{EOI} { BEGIN(args); return T_NOT; } +neg/{EOI} { BEGIN(args); return T_NEG; } +btc/{EOI} { BEGIN(args); return T_BTC; } +bts/{EOI} { BEGIN(args); return T_BTS; } +mov/{EOI} { BEGIN(args); return T_MOV; } +st\.b/{EOI} { BEGIN(args); return T_ST_B; } +st\.w/{EOI} { BEGIN(args); return T_ST_W; } +ld\.bl/{EOI} { BEGIN(args); return T_LD_BL; } +ld\.bh/{EOI} { BEGIN(args); return T_LD_BH; } +ld\.w/{EOI} { BEGIN(args); return T_LD_W; } +ldi\.bl/{EOI} { BEGIN(args); return T_LDI_BL; } +ldi\.bh/{EOI} { BEGIN(args); return T_LDI_BH; } +beq/{EOI} { BEGIN(args); return T_BEQ; } +bne/{EOI} { BEGIN(args); return T_BNE; } +bgt/{EOI} { BEGIN(args); return T_BGT; } +bge/{EOI} { BEGIN(args); return T_BGE; } +blt/{EOI} { BEGIN(args); return T_BLT; } +ble/{EOI} { BEGIN(args); return T_BLE; } +bra/{EOI} { BEGIN(args); return T_BRA; } +jmp/{EOI} { BEGIN(args); return T_JMP; } +addpc/{EOI} { BEGIN(args); return T_ADDPC; } +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 + +#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 + +#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 +%% + +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 + ; -- cgit v1.2.3