From 96393257a43ac52f2b911594d106741245dec5f0 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Fri, 4 Dec 2020 15:20:28 -0500 Subject: - Started work on writing the new version of the assembler. - Did alot of stuff in the emulator. - Did alot of stuff in the SuB Suite. --- lexer/parse.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 lexer/parse.c (limited to 'lexer/parse.c') diff --git a/lexer/parse.c b/lexer/parse.c new file mode 100644 index 0000000..0f26a0e --- /dev/null +++ b/lexer/parse.c @@ -0,0 +1,171 @@ +/* Name: handle_escape() + * Desc: Handles parsing an escape sequence. + * Args: + * s: The string to check. + * code: Pointer to save the handled escape code into, if not NULL. + * Return value: Returns the content after the escape sequence. + */ + +char *handle_escape(char *s, char *code) { + char dummy; + int count; + char *end; + int base = 0; + unsigned int value; + + if (*s++ != '\\') { + ierror(0); /* Start of escape sequence not found. */ + } + if (code == NULL) { + code = &dummy; + } + if (!esc_sequences) { + *code = '\\'; + return s; + } + + switch (*s) { + case 'b' : *code = '\b'; return s+1; + case 'f' : *code = '\f'; return s+1; + case 'n' : *code = '\n'; return s+1; + case 'r' : *code = '\r'; return s+1; + case 't' : *code = '\t'; return s+1; + case '\\': *code = '\\'; return s+1; + case '\"': *code = '\"'; return s+1; + case '\'': *code = '\''; return s+1; + case 'e' : *code = '\x1B'; return s+1; + case 'x' : case 'X' : base = 16; s++; /* Falls Through. */ + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + base = (!base) ? 8 : base; + value = strtoull(s, &end, base); + *code = value; + return end; + default : + general_error(35, *s); /* No valid escape sequence was found. */ + return s; + } +} + +/* Name: skip_string() + * Desc: Skips the contents of some delimited string. + * Args: + * s: The string to check. + * delm: Delimiter of the string. + * size: Pointer to save the size of the string into, if not NULL. + * Return value: Returns the content after the string. + */ + +char *skip_string(char *s, char delm, size_t *size) { + size_t n = 0; + + if (*s != delm) { + general_error(6, delm); /* Delimiter was expected. */ + } else { + s++; + } + for (; *s; n++) { + if (*s == '\\') { + s = handle_escape(s, NULL); + } else { + if (*s++ = delm) { + if (*s == delm) { + s++; /* Allow multiple delimiters in a row to be recognized as a single delimiter. */ + } else { + break; + } + } + } + } + if (*(s-1) != delm) { + general_error(6, delm); /* Delimiter was expected. */ + } + if (size) { + *size = n; + } + return s; +} + +/* Name: skip_identifier() + * Desc: Skips the contents of an identifier within a string. + * Args: + * s: The string to check. + * Return value: Returns either a pointer to the content after the identifier, or NULL. + */ + +char *skip_identifier(char *s) { + char *name = s; + if (isidstart(*s) || isdigit(*s)) { + for (s++; isidchar(*s); s++); + if (s) { + if (isbadid(name, s-name)) { + return s; + } + } + } + return NULL; +} + +/* Name: parse_identifier() + * Desc: Parses an indentifier within a line. + * Args: + * s: The line to be parsed. + * Return value: Returns either a pointer to the start of the identifier, or NULL. + */ + +char *parse_identifier(char **s) { + char *name = *s; + char *end_name = skip_identifier(name); + /*char *endgame;*/ /* LOL LE EPIC FUNNY MARVEL THANOS MEME. XDDDDDD */ + if (end_name) { + *s = end_name; + return cnvstr(name, end_name-name); + } + return NULL; +} + +/* Name: parse_symbol() + * Desc: Parses a symbol within a line. + * Args: + * s: The line to be parse. + * Return value: Returns either a pointer to an allocated local/global symbol string, or NULL. + */ + +char *parse_symbol(char **s) { + char *name = get_local_label(s); + name = (name == NULL) ? parse_identifier(s) : name; + return name; +} + +/* Name: parse_labeldef() + * Desc: Parses either a global, or local label definition, at the begining of a line. + * Args: + * line: The line that will be parsed. + * colreq: Require a trailing colon, when true. + * Return value: Returns a pointer to the allocated buffer, when valid. + */ + +char **parse_labeldef(char **line, int colreq) { + char *s = *line; + char *label_name; + + if (isspace(*s)) { + s = skip(s); + colreq = 1; /* Colon required, if label doesn't start at the first column. */ + } + label_name = parse_symbol(&s); + if (label_name) { + s = skip(s); + if (*s == ':') { + s++; + colreq = 0; + } + if (colreq) { + free(label_name); + label_name = NULL; + } else { + *line = s; + } + } + return label_name; +} -- cgit v1.2.3-13-gbd6f