LCOV - code coverage report
Current view: top level - src/lisp - lex.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 86 0.0 %
Date: 2016-12-21 02:12:01 Functions: 0 8 0.0 %

          Line data    Source code
       1             : #include <assert.h>
       2             : #include <ctype.h>
       3             : #include <string.h>
       4             : #include "libstephen/lisp.h"
       5             : #include "libstephen/cb.h"
       6             : 
       7             : typedef struct {
       8             :   lisp_value *result;
       9             :   int index;
      10             : } result;
      11             : 
      12             : result lisp_parse_value(lisp_runtime *rt, char *input, int index);
      13             : 
      14           0 : result lisp_parse_integer(lisp_runtime *rt, char *input, int index)
      15             : {
      16             :   //printf("lisp_parse_integer(%s, %d)\n", input, index);
      17             :   int n;
      18           0 :   lisp_integer *v = (lisp_integer*)lisp_new(rt, type_integer);
      19           0 :   sscanf(input + index, "%d%n", &v->x, &n);
      20           0 :   return (result){(lisp_value*)v, index + n};
      21             : }
      22             : 
      23           0 : char lisp_escape(char escape)
      24             : {
      25           0 :   switch (escape) {
      26             :   case 'a':
      27           0 :     return '\a';
      28             :   case 'b':
      29           0 :     return '\b';
      30             :   case 'f':
      31           0 :     return '\f';
      32             :   case 'n':
      33           0 :     return '\n';
      34             :   case 'r':
      35           0 :     return '\b';
      36             :   case 't':
      37           0 :     return '\t';
      38             :   case 'v':
      39           0 :     return '\v';
      40             :   default:
      41           0 :     return escape;
      42             :   }
      43             : }
      44             : 
      45           0 : result lisp_parse_string(lisp_runtime *rt, char *input, int index)
      46             : {
      47           0 :   int i = index + 1;
      48             :   cbuf cb;
      49           0 :   cb_init(&cb, 16);
      50           0 :   while (input[i] && input[i] != '"') {
      51           0 :     if (input[i] == '\\') {
      52           0 :       cb_append(&cb, lisp_escape(input[++i]));
      53             :     } else {
      54           0 :       cb_append(&cb, input[i]);
      55             :     }
      56           0 :     i++;
      57             :   }
      58           0 :   cb_trim(&cb);
      59           0 :   lisp_string *str = (lisp_string*)lisp_new(rt, type_string);
      60           0 :   str->s = cb.buf;
      61           0 :   return (result){(lisp_value*)str, ++i};
      62             : }
      63             : 
      64           0 : result lisp_parse_list_or_sexp(lisp_runtime *rt, char *input, int index)
      65             : {
      66           0 :   while (isspace(input[index])) {index++;}
      67           0 :   if (input[index] == ')') {
      68           0 :     return (result){(lisp_value*)lisp_nil_new(rt), index + 1};
      69             :   }
      70             : 
      71           0 :   result r = lisp_parse_value(rt, input, index);
      72           0 :   index = r.index;
      73           0 :   lisp_list *rv = (lisp_list*)lisp_new(rt, type_list);
      74           0 :   rv->left = r.result;
      75           0 :   lisp_list *l = rv;
      76             : 
      77             :   while (true) {
      78           0 :     while (isspace(input[index])) {
      79           0 :       index++;
      80             :     }
      81             : 
      82           0 :     if (input[index] == '.') {
      83           0 :       index++;
      84           0 :       result r = lisp_parse_value(rt, input, index);
      85           0 :       index = r.index;
      86           0 :       l->right = r.result;
      87           0 :       return (result){(lisp_value*)rv, index};
      88           0 :     } else if (input[index] == ')') {
      89           0 :       index++;
      90           0 :       l->right = lisp_nil_new(rt);
      91           0 :       return (result){(lisp_value*)rv, index};
      92             :     } else {
      93           0 :       result r = lisp_parse_value(rt, input, index);
      94           0 :       l->right = lisp_new(rt, type_list);
      95           0 :       l = (lisp_list*)l->right;
      96           0 :       l->left = r.result;
      97           0 :       index = r.index;
      98             :     }
      99           0 :   }
     100             : }
     101             : 
     102           0 : result lisp_parse_symbol(lisp_runtime *rt, char *input, int index)
     103             : {
     104           0 :   int n = 0;
     105           0 :   while (input[index + n] && !isspace(input[index + n]) &&
     106           0 :          input[index + n] != ')' && input[index + n] != '.' &&
     107           0 :          input[index + n] != '\'') {
     108           0 :     n++;
     109             :   }
     110           0 :   lisp_symbol *s = (lisp_symbol*)lisp_new(rt, type_symbol);
     111           0 :   s->sym = malloc(n + 1);
     112           0 :   strncpy(s->sym, input + index, n);
     113           0 :   s->sym[n] = '\0';
     114           0 :   return (result){(lisp_value*)s, index + n};
     115             : }
     116             : 
     117           0 : result lisp_parse_quote(lisp_runtime *rt, char *input, int index)
     118             : {
     119           0 :   result r = lisp_parse_value(rt, input, index + 1);
     120           0 :   r.result = lisp_quote(rt, r.result);
     121           0 :   return r;
     122             : }
     123             : 
     124           0 : result lisp_parse_value(lisp_runtime *rt, char *input, int index)
     125             : {
     126           0 :   while (isspace(input[index])) {
     127           0 :     index++;
     128             :   }
     129             : 
     130           0 :   if (input[index] == '"') {
     131           0 :     return lisp_parse_string(rt, input, index);
     132             :   }
     133           0 :   if (input[index] == '\0') {
     134           0 :     return (result){NULL, index};
     135             :   }
     136           0 :   if (input[index] == ')') {
     137           0 :     return (result){lisp_nil_new(rt), index + 1};
     138             :   }
     139           0 :   if (input[index] == '(') {
     140           0 :     return lisp_parse_list_or_sexp(rt, input, index + 1);
     141             :   }
     142           0 :   if (input[index] == '\'') {
     143           0 :     return lisp_parse_quote(rt, input, index);
     144             :   }
     145           0 :   if (isdigit(input[index])) {
     146           0 :     return lisp_parse_integer(rt, input, index);
     147             :   }
     148           0 :   return lisp_parse_symbol(rt, input, index);
     149             : }
     150             : 
     151           0 : lisp_value *lisp_parse(lisp_runtime *rt, char *input)
     152             : {
     153           0 :   return lisp_parse_value(rt, input, 0).result;
     154             : }

Generated by: LCOV version 1.11