aboutsummaryrefslogtreecommitdiff
path: root/module/c/lex2.scm
diff options
context:
space:
mode:
Diffstat (limited to 'module/c/lex2.scm')
-rw-r--r--module/c/lex2.scm96
1 files changed, 95 insertions, 1 deletions
diff --git a/module/c/lex2.scm b/module/c/lex2.scm
index 85c9be19..af90dcce 100644
--- a/module/c/lex2.scm
+++ b/module/c/lex2.scm
@@ -4,6 +4,7 @@
:use-module ((hnh util) :select (->))
:use-module (hnh util object)
:use-module (hnh util type)
+ :use-module ((srfi srfi-1) :select (fold))
:use-module (srfi srfi-88)
:use-module ((c trigraph) :select (replace-trigraphs))
:use-module ((c line-fold) :select (fold-lines))
@@ -423,9 +424,102 @@
(cdr (peg:tree result))))))
+
+
+;; (parse-decimals "555" 10)
+;; ⇒ 0.5549999999999999
+;; (parse-decimals "8" 16)
+;; ⇒ 0.5
+(define (parse-decimals str base)
+ (/ (fold (lambda (digit done)
+ (let ((v (string->number digit base)))
+ (+ v (/ done base))))
+ 0.0
+ (map string (string->list str)))
+ base))
+
+;; parse a number on form <digits>.<digits>
+(define (parse-fractional str base)
+ (let* ((pair (string-split str #\.))
+ (integer (list-ref pair 0))
+ (decimals (list-ref pair 1)))
+ (+ (if (string-null? integer)
+ 0 (string->number integer 16))
+ (if (string-null? decimals)
+ 0 (parse-decimals decimals 16)))))
+
+
+(define (parse-float body)
+ (define (fractional-constant x)
+ (case x
+ ((decimal-floating-constant) 'fractional-constant)
+ ((hexadecimal-floating-constant) 'hexadecimal-fractional-constant)))
+
+ (define (exponent-part x)
+ (case x
+ ((decimal-floating-constant) 'exponent-part)
+ ((hexadecimal-floating-constant) 'binary-exponent-part)))
+
+ (define (expt-base x)
+ (case x
+ ((decimal-floating-constant) 10)
+ ((hexadecimal-floating-constant) 2)))
+
+ (define (base x)
+ (case x
+ ((decimal-floating-constant) 10)
+ ((hexadecimal-floating-constant) 16)))
+
+ (let ((type (car body))
+ (body (cdr body)))
+ (* 1.0
+ (cond ((assoc-ref body (fractional-constant type))
+ => (lambda (fc) (parse-fractional (car fc) (base type))))
+ (else (string->number (car body) (base type))))
+ (cond ((assoc-ref body (exponent-part type))
+ => (lambda (x) (expt (expt-base type)
+ (string->number (car x) (base type)))))
+ (else 1)))
+ ;; TODO do something with (possible) suffix
+ ;; (assoc-ref body 'floating-suffix)
+ ))
+
+(define (parse-integer body)
+ (let* (;; (suffix (assoc-ref body 'integer-suffix))
+ (value (cadr (car body)))
+ (value-type (car (car body))))
+ ;; TODO do something with suffix
+ (string->number
+ value
+ (case value-type
+ ((octal-constant) 8)
+ ((decimal-constant) 10)
+ ((hexadecimal-constant) 16)))))
+
+;; (parse-c-number "0x1.8p0")
+;; ⇒ 1.5
+
+;; TODO is "5ul" equivalent to "((unsigned long) 5)"
(define (parse-c-number string)
- (match-pattern constant string))
+ (cond ((match-pattern constant string)
+ => (lambda (m)
+ (let ((m (cadr (peg:tree m)))) ; Strip 'constant wrapper
+ (case (car m)
+ ((floating-constant)
+ (parse-float (cadr m)))
+
+ ((integer-constant)
+ (parse-integer (cdr m)))
+
+ ((enumeration-constant character-constant)
+ (scm-error 'misc-error "parse-c-number"
+ "Couldn't parse [~a] as a /number/ (~s)"
+ (list string m) #f))))))
+
+ (else (scm-error 'misc-error "parse-c-number"
+ "Couldn't parse [~a] as a number"
+ (list string) #f))))