diff options
author | Bobby Bingham <koorogi@koorogi.info> | 2017-01-12 20:05:45 -0600 |
---|---|---|
committer | Bobby Bingham <koorogi@koorogi.info> | 2017-01-15 23:18:52 -0600 |
commit | cf366387449dcf9d34875a7d76f3b79c1e231d6f (patch) | |
tree | b892febf08e3c5791e414c9cdc011477a9420ae1 | |
parent | 239ee7648658b77b217f5c8142ef887612516af4 (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-- | Makefile | 30 | ||||
-rw-r--r-- | lexer.l | 61 | ||||
-rw-r--r-- | nqasm.c | 20 | ||||
-rw-r--r-- | nqasm.h | 11 | ||||
-rw-r--r-- | parser.y | 156 |
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 @@ -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; } + +%% @@ -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; +} + @@ -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 + ; |