Mercurial > hg > Members > anatofuz > 9cc
view 9cc.c @ 3:3cdf1d015159 default tip
fix error msg position
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 25 Jul 2019 11:05:58 +0900 |
parents | 75f25ab4022c |
children |
line wrap: on
line source
#include <ctype.h> #include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // kind of token typedef enum { TK_RESERVED, // 記号 TK_NUM, // 整数トークン TK_EOF, // 終端トークン } TokenKind; typedef struct Token Token; struct Token { TokenKind kind; // トークンの型 Token *next; // 次の入力トークン int val; // kindがTK_NUMのときに入る char *str; // トークン文字列 }; Token *token; char *user_input; // エラー報告用の関数 // printfと同じ引数を取る void error(char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); exit(1); } void error_at(char *loc, char *fmt, ...) { va_list ap; va_start(ap, fmt); int pos = loc - user_input; fprintf(stderr, "%s\n",user_input); fprintf(stderr, "%*s",pos, ""); // pos個の空白を出力 fprintf(stderr, "^ "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); exit(1); } // 次のトークンが予想している記号ならtrue bool consume(char op) { if (token->kind != TK_RESERVED || token->str[0] != op) return false; token = token->next; return true; } // 予想している記号じゃないとエラーになる void expect(char op) { if (token->kind != TK_RESERVED || token->str[0] != op) error_at(token->str, "'%c'ではありません",op); token = token->next; } // 数値なら数値を返す int expect_number() { if (token->kind != TK_NUM) error_at(token->str, "数ではないです"); int val = token->val; token = token->next; return val; } bool at_eof() { return token->kind == TK_EOF; } Token *new_token(TokenKind kind, Token*cur, char *str) { Token *tok = calloc(1, sizeof(Token)); tok->kind = kind; tok->str = str; cur->next = tok; return tok; } Token *tokenize(char *p) { Token head; head.next = NULL; Token *cur = &head; while (*p) { if (isspace(*p)) { p++; continue; } if (*p == '+' || *p == '-') { cur = new_token(TK_RESERVED, cur, p++); continue; } if (isdigit(*p)) { cur = new_token(TK_NUM, cur, p); cur->val = strtol(p, &p, 10); continue; } error_at(p, "トーカナイズできないです"); } new_token(TK_EOF, cur, p); return head.next; } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr,"invalid arguments number\n"); return 1; } user_input = argv[1]; token = tokenize(user_input); printf(".intel_syntax noprefix\n"); printf(".global main\n"); printf("main:\n"); // 最初は数をチェックする printf(" mov rax, %d\n",expect_number()); while (!at_eof()) { if (consume('+')) { printf(" add rax, %d\n", expect_number()); continue; } expect('-'); printf(" sub rax, %d\n", expect_number()); } printf(" ret\n"); return 0; }