parser.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * parser.c -- part of ZilUtils/ZilAsm
  3. *
  4. * Copyright (C) 2016 Jason Self <j@jxself.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>
  18. *
  19. * SPDX-License-Identifier: AGPL-3.0-or-later
  20. */
  21. #include <stdio.h> /* fopen, fgets */
  22. #include <string.h> /* strlen */
  23. #include "parser.h"
  24. #include "directives.h"
  25. #include "opcodes.h"
  26. #include "labels.h"
  27. #define iscomment(c) ((c) == '#')
  28. #define isbindigit(c) ((c) == '0' || (c) == '1')
  29. /* !!! TODO !!! */
  30. #define fatal_error(errmsg)
  31. #define PC NULL
  32. void checksep(const char *p)
  33. {
  34. if (!*p || iscomment(*p) || isspace(*p)) return;
  35. fatal_error("wrong chars");
  36. }
  37. const char *pass_spaces(const char *p)
  38. {
  39. while(p && isspace(*p)) p++;
  40. return (p && *p) ? p : NULL;
  41. }
  42. const char *pass_alnums(const char *p)
  43. {
  44. while(p && isalnum(*p)) p++;
  45. return (p && *p) ? p : NULL;
  46. }
  47. int tryparse_directive(const char *p)
  48. {
  49. if (*p != '.')
  50. return 0;
  51. const char *a = p+1;
  52. const char *b = pass_alnums(a);
  53. checksep(b);
  54. Directive_handler f = directive_lookup(a, b - a);
  55. if (!f) return 0;
  56. return (*f)(b);
  57. }
  58. int tryparse_assignment(const char *a, const char *b, const char *c)
  59. {
  60. return 0;
  61. }
  62. int tryparse_label(const char *a, const char *b, const char *c)
  63. {
  64. if (*(c+1) != ':') {
  65. symtable_add2(Local_labels, a, b - a, PC);
  66. } else if (*(c+2) != ':') {
  67. symtable_add2(Global_labels, a, b - a, PC);
  68. } else {
  69. fatal_error("wrong label type");
  70. }
  71. while (*c++ == ':');
  72. if (*c && ((c = pass_spaces(c)) != NULL) && *c)
  73. return tryparse_instruction(c);
  74. return 1;
  75. }
  76. int tryparse_name(const char *a)
  77. {
  78. const char *b = pass_alnums(a);
  79. const char *c = pass_spaces(b);
  80. if (!c) return 0;
  81. if (*c == '=') return tryparse_assignment(a, b, c + 1);
  82. if (*c == ':') return tryparse_label(a, b, c);
  83. return 0;
  84. }
  85. int tryparse_instruction(const char *a)
  86. {
  87. const char *b = pass_alnums(a);
  88. ZOpcode *op = symtable_lookup2(Opcodes, a, b - a);
  89. if (!op) return 0;
  90. ZOpcode_flags flags = op->flags;
  91. /* !!! TODO !!! */
  92. return 0;
  93. }
  94. /*
  95. * Line can be one from: Comment, Global label, Local label, Directive, Name=Value, Instruction
  96. */
  97. int parse_line(const char *p)
  98. {
  99. for (; *p; p++) {
  100. char c = *p;
  101. int n;
  102. if (isspace(c)) continue;
  103. if (iscomment(c)) return 0;
  104. if (n = tryparse_directive(p)) return n;
  105. if (n = tryparse_name(p)) return n; // ..label or assignment
  106. if (n = tryparse_instruction(p)) return n;
  107. fatal_error("wrong line");
  108. }
  109. return 0;
  110. }
  111. int parse_file(const char *filename)
  112. {
  113. FILE *fp = fopen(filename, "r");
  114. if (!fp) fatal_error("wrong file");
  115. const int MAX_LINESIZE = 1024;
  116. char line[MAX_LINESIZE];
  117. int newline_missing = 0;
  118. while (fgets(line, MAX_LINESIZE, fp)) {
  119. if (newline_missing) fatal_error("line too long");
  120. int n = strlen(line);
  121. if (!n) continue;
  122. parse_line(line);
  123. newline_missing = (line[n-1] != '\n');
  124. }
  125. close(fp);
  126. }
  127. /*
  128. line_passed() {
  129. skip_spaces();
  130. return (current_token == LINE_END || current_token == LINE_COMMENT);
  131. }
  132. if (line_passed()) continue;
  133. if (current_token == DIRECTIVE) {
  134. if (!try_next_token(NAME))
  135. fatal_error("directive contains incorrect chars")
  136. handler = get_directive_handler(current_token);
  137. if (!handler)
  138. fatal error("unknown directive");
  139. (*handler)(remaining_line);
  140. if (line_passed()) continue;
  141. fatal_error("unexpected line tail");
  142. } else if (current_token == NAME) {
  143. skip_spaces();
  144. if (current_token == ASSIGNMENT)
  145. }
  146. */