Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <regex.h>
- #include <assert.h>
- static const char *tokens[] = {
- "[[:blank:][:cntrl:][:space:]]+",
- "[\\+\\-]?[0-9]+\\.[0-9]+([eE][\\+\\-]?[0-9]+)?",
- "[\\+\\-]?[0-9]+",
- "\\+",
- "\\-",
- "\\*",
- "\\/",
- "\\(",
- "\\)",
- NULL
- };
- enum {
- TOK_SPACE,
- TOK_REAL,
- TOK_INT,
- TOK_PLUS,
- TOK_MINUS,
- TOK_MUL,
- TOK_DIV,
- TOK_LPAREN,
- TOK_RPAREN,
- TOK_INVALID
- };
- typedef unsigned short token_t;
- const char *tokdesc[] = {
- "TOK_SPACE",
- "TOK_REAL",
- "TOK_INT",
- "TOK_PLUS",
- "TOK_MINUS",
- "TOK_MUL",
- "TOK_DIV",
- "TOK_LPAREN",
- "TOK_RPAREN",
- "TOK_INVALID"
- };
- static int matches_regex(const char *regex, const char *str, regmatch_t *match)
- {
- regex_t regex_obj;
- int error;
- error = regcomp(®ex_obj, regex, REG_EXTENDED); // TODO: move dis outta loop
- if (error)
- return 0;
- error = regexec(®ex_obj, str, 1, match, 0);
- regfree(®ex_obj);
- return !error;
- }
- static char *__strndup(const char *s, size_t n)
- {
- size_t l, i;
- char *r;
- l = strlen(s);
- if (l < n)
- n = l;
- r = malloc(n + 1);
- if (r != NULL)
- {
- i = 0;
- while(n--)
- {
- r[i] = s[i];
- i++;
- }
- r[i] = 0;
- }
- return r;
- }
- int __strncnt(const char *haystack, const char *needle, size_t n)
- {
- const char *orig;
- const char *next;
- int i;
- size_t len;
- orig = haystack;
- i = 0;
- len = strlen(needle);
- while ((next = strstr(haystack, needle)) != NULL && (haystack - orig < n))
- {
- haystack = next + len;
- i++;
- }
- return i;
- }
- static char *getfile(const char *filename)
- {
- ssize_t size;
- FILE *f;
- char *result;
- f = fopen(filename, "r");
- if (f == NULL)
- {
- return NULL;
- }
- fseek(f, 0, SEEK_END);
- size = ftell(f);
- fseek(f, 0, SEEK_SET);
- result = malloc(size + 1);
- if (size != fread(result, sizeof(*result), size, f))
- {
- free(result);
- return NULL;
- }
- fclose(f);
- result[size] = 0;
- return result;
- }
- /**
- * Helper function for the lexer
- */
- static char *curr_tok_str = NULL;
- static char *stream = NULL;
- static char *orig = NULL;
- static token_t curr_tok = TOK_INVALID;
- static token_t get_next_token()
- {
- token_t i;
- regmatch_t match;
- i = 0;
- while (tokens[i] != NULL)
- {
- if (matches_regex(tokens[i], stream, &match))
- {
- if (match.rm_so == 0)
- {
- free(curr_tok_str);
- curr_tok_str = __strndup(stream, match.rm_eo);
- stream += match.rm_eo;
- return curr_tok = i;
- }
- }
- i++;
- }
- free(curr_tok_str);
- curr_tok_str = NULL;
- return curr_tok = TOK_INVALID;
- }
- static token_t lex()
- {
- token_t tok;
- while ((tok = get_next_token()) == TOK_SPACE)
- ;
- return tok;
- }
- static void init_parser(const char *src)
- {
- stream = src;
- orig = stream;
- }
- static void cleanup_parser()
- {
- free(orig);
- }
- static int parser_is_at_end()
- {
- return !*stream;
- }
- static unsigned int parser_lineno()
- {
- return __strncnt(orig, "\n", stream - orig) + 1;
- }
- /********************************/
- static double expr();
- static double term()
- {
- double d;
- if (curr_tok == TOK_REAL) {
- d = strtod(curr_tok_str, NULL);
- lex();
- return d;
- } else if (curr_tok == TOK_INT) {
- d = strtod(curr_tok_str, NULL);
- lex();
- return d;
- } else if (curr_tok == TOK_LPAREN) {
- lex();
- d = expr();
- if (curr_tok != TOK_RPAREN) abort();
- lex();
- return d;
- } else {
- fprintf(stderr, "\nInvalid term: `%s'\n", curr_tok_str);
- abort();
- }
- return 0.0;
- }
- static double multiplicative_expr()
- {
- double a, b;
- a = term();
- while (curr_tok == TOK_MUL || curr_tok == TOK_DIV)
- {
- token_t action = curr_tok;
- lex();
- b = term();
- (action == TOK_MUL) ? (a *= b) : (a /= b);
- }
- return a;
- }
- static double additive_expr()
- {
- double a, b;
- a = multiplicative_expr();
- while (curr_tok == TOK_PLUS || curr_tok == TOK_MINUS)
- {
- token_t action = curr_tok;
- lex();
- b = multiplicative_expr();
- (action == TOK_PLUS) ? (a += b) : (a -= b);
- }
- return a;
- }
- static double expr()
- {
- return additive_expr();
- }
- static double parse()
- {
- lex();
- return expr();
- }
- int main(int argc, char **argv)
- {
- unsigned lineno;
- token_t tokid;
- char *src;
- src = getfile(argv[1]);
- init_parser(src);
- printf("Parsing string...\n");
- double val = parse();
- lineno = parser_lineno();
- if (parser_is_at_end())
- printf("Parsing succeeded, result: %lf\n", val);
- else
- fprintf(stderr, "Parsing failed: syntax error on line %u\n", lineno);
- cleanup_parser();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement