ys2-intro/loader/tools/exomizer-3.1/src/asm.yy
2025-11-13 19:07:39 +03:00

289 lines
6 KiB
Plaintext

/*
* Copyright (c) 2002 - 2005 Magnus Lind.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software, alter it and re-
* distribute it freely for any non-commercial, non-profit purpose subject to
* the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any distribution.
*
* 4. The names of this software and/or it's copyright holders may not be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
*/
/* scanner for a simple assembler */
%{
#include <stdio.h>
#include <string.h>
#include "int.h"
#include "buf.h"
#include "parse.h"
#include "asm.tab.h"
#define MAX_SRC_BUFFER_DEPTH 10
static YY_BUFFER_STATE src_buffers[MAX_SRC_BUFFER_DEPTH];
static int src_buffer_depth = 0;
static char *strdupped_get(char *text);
static int strdupped_cmp(const void *a, const void *b);
static void strdupped_free(void *a);
int num_lines = 1;
int push_state_skip = 0;
int push_state_init = 0;
int push_state_macro = 0;
struct vec strdupped[1];
%}
%x SKIP SKIP_ALL QUOTED_STRING SKIP_LINE MACROO
%option noyywrap
%option case-insensitive
%option stack
%%
if(push_state_init)
{push_state_init = 0; yy_push_state(INITIAL); }
if(push_state_skip)
{push_state_skip = 0; yy_push_state(SKIP); }
if(push_state_macro)
{push_state_macro = 0; yy_push_state(MACROO); }
\.if return IF;
\.elif BEGIN(SKIP_ALL);
\.else BEGIN(SKIP);
\.endif yy_pop_state();
\.include return INCLUDE;
\.macro return MACRO;
\.defined return DEFINED;
\.org return ORG;
\.error return ERROR;
\.echo return ECHO1;
\.incbin return INCBIN;
\.inclen return INCLEN;
\.incword return INCWORD;
\.res return RES;
\.word return WORD;
\.byte return BYTE;
\" BEGIN(QUOTED_STRING);
\; BEGIN(SKIP_LINE);
lda return LDA;
ldx return LDX;
ldy return LDY;
sta return STA;
stx return STX;
sty return STY;
and return AND;
ora return ORA;
eor return EOR;
adc return ADC;
sbc return SBC;
cmp return CMP;
cpx return CPX;
cpy return CPY;
tsx return TSX;
txs return TXS;
pha return PHA;
pla return PLA;
php return PHP;
plp return PLP;
sei return SEI;
cli return CLI;
nop return NOP;
tya return TYA;
tay return TAY;
txa return TXA;
tax return TAX;
clc return CLC;
sec return SEC;
rts return RTS;
clv return CLV;
cld return CLD;
sed return SED;
jsr return JSR;
jmp return JMP;
beq return BEQ;
bne return BNE;
bcc return BCC;
bcs return BCS;
bpl return BPL;
bmi return BMI;
bvc return BVC;
bvs return BVS;
inx return INX;
dex return DEX;
iny return INY;
dey return DEY;
inc return INC;
dec return DEC;
lsr return LSR;
asl return ASL;
ror return ROR;
rol return ROL;
bit return BIT;
[0-9]+ { yylval.num = atoi(yytext); return NUMBER; }
$[0-9a-f]+ { yylval.num = strtol(yytext + 1, NULL, 16); return NUMBER; }
\< return LT;
\> return GT;
== return EQ;
!= return NEQ;
! return LNOT;
\&\& return LAND;
\|\| return LOR;
\( return LPAREN;
\) return RPAREN;
\, return COMMA;
\: return COLON;
\# return HASH;
\+ return PLUS;
\- return MINUS;
\* return MULT;
\/ return DIV;
\% return MOD;
\= return ASSIGN;
\?= return GUESS;
x return X;
y return Y;
[a-z][_a-z0-9]*/: { yylval.str = strdupped_get(yytext); return LABEL; }
[a-z][_a-z0-9]* { yylval.str = strdupped_get(yytext); return SYMBOL; }
\r\n|\n ++num_lines;
[ \t] /* eat whitespace */
. printf("unknown character found %s\n", yytext);
<SKIP>\.if yy_push_state(SKIP_ALL);
<SKIP>\.elif { yy_pop_state(); return IF; }
<SKIP>\.else BEGIN(INITIAL);
<SKIP>\.endif yy_pop_state();
<SKIP>\r\n|\n ++num_lines;
<SKIP>.
<MACROO>\.endmacro yy_pop_state();
<MACROO>\.+ { yylval.str = yytext; return MACRO_STRING; }
<MACROO>[^\.]+ { yylval.str = yytext; return MACRO_STRING; }
<SKIP_ALL>\.if yy_push_state(SKIP_ALL);
<SKIP_ALL>\.endif yy_pop_state();
<SKIP_ALL>\r\n|\n ++num_lines;
<SKIP_ALL>.
<QUOTED_STRING>[^\"]* {
/* multi-line string with correct line count */
char *p = strdupped_get(yytext);
yylval.str = p;
while (*p != '\0')
{
if (*p++ == '\n')
{
++num_lines;
}
}
return STRING;
}
<QUOTED_STRING>\" BEGIN(INITIAL);
<SKIP_LINE>\r\n|\n { ++num_lines; BEGIN(INITIAL); }
<SKIP_LINE>.
<<EOF>> {
if(--src_buffer_depth == 0)
{
yyterminate();
}
else
{
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(src_buffers[src_buffer_depth]);
}
}
%%
void scanner_init(void)
{
vec_init(strdupped, sizeof(char*));
}
void asm_src_buffer_push(struct buf *buffer)
{
if(src_buffer_depth == MAX_SRC_BUFFER_DEPTH)
{
fprintf(stderr, "source buffers nested too deep\n");
exit(1);
}
src_buffers[src_buffer_depth++] = YY_CURRENT_BUFFER;
yy_scan_bytes(buf_data(buffer), buf_size(buffer));
}
static char *strdupped_get(char *text)
{
char **pp;
/*printf("get \"%s\" => ", text);*/
if(vec_insert_uniq(strdupped, strdupped_cmp, &text, (void*)&pp))
{
/* replace the pointer to <text> since <text> will be reused */
*pp = strdup(text);
}
/*printf("%p\n", *pp);*/
return *pp;
}
static void strdupped_free(void *a)
{
char *b = *(char**)a;
/*printf("free => %p \"%s\"\n", b, b);*/
free(b);
}
static int strdupped_cmp(const void *a, const void *b)
{
char *c = *(char**)a;
char *d = *(char**)b;
return strcmp(c, d);
}
void scanner_free(void)
{
vec_free(strdupped, strdupped_free);
}
void silence_warnings_about_unused_functions(void)
{
yyunput(0, NULL);
input();
yy_top_state();
}