changeset 213:e00a8bc6361b

Implement match:yield macro
author Mike Pavone <pavone@retrodev.com>
date Mon, 02 Dec 2013 00:50:16 -0800
parents 32080f96c3a0
children e01137a97654
files interp.js modules/parser.tp
diffstat 2 files changed, 77 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/interp.js	Sat Nov 30 15:05:24 2013 -0800
+++ b/interp.js	Mon Dec 02 00:50:16 2013 -0800
@@ -295,7 +295,11 @@
 	if (val) {
 		var newnode = makeASTNode(val);
 		if (!(newnode instanceof symbol)) {
-			newnode = newnode.quote(env);
+			if ('quote' in newnode) {
+				newnode = newnode.quote(env);
+			} else {
+				throw new Error('Symbol ' + this.name + ' is not bound to a valid AST value, instead it is bound to an object with keys ' + JSON.stringify(Object.keys(newnode)));
+			}
 		}
 		return newnode;
 	} else {
--- a/modules/parser.tp	Sat Nov 30 15:05:24 2013 -0800
+++ b/modules/parser.tp	Mon Dec 02 00:50:16 2013 -0800
@@ -16,6 +16,8 @@
 					#{
 						matched? <- { true }
 						matchlen <- { str length }
+						basicYield? <- { true }
+						yield <- { str }
 					}
 				} else: {
 					#{
@@ -71,6 +73,8 @@
 											#{
 												matched? <- { true }
 												matchlen <- { total }
+												basicYield? <- { true }
+												yield <- { tomatch from: 0 withLen: total }
 											}
 										} else: {
 											rm
@@ -188,6 +192,8 @@
 						#{
 							matched? <- { true }
 							matchlen <- { 1 }
+							basicYield? <- { true }
+							yield <- { tomatch from: 0 withLength: 1 }
 						}
 					}
 				} else: {
@@ -212,19 +218,42 @@
 				n <- tomatch byte_length
 				orig <- tomatch
 				match <- true
+				allBasic? <- true
+				yieldvals <- []
 				while: { match && cur < n } do: {
 					res <- mcall
 					match <- res matched?
 					if: match {
 						//TODO: Use some kind of lightweight substring wrapper here
 						tomatch <- tomatch from: (res matchlen)
+						if: allBasic? {
+							ifnot: (res basicYield?) {
+								allBasic? <- false
+								yieldvals <- (orig from: 0 withLength: cur) | yieldvals
+							}
+						} else: {
+							yieldvals <- (res yield) | yieldvals
+						}
+						allBasic? <- allBasic? && (res basicYield?)
 						cur <- cur + (res matchlen)
 					}
 				}
 				if: cur > 0 {
-					#{
-						matched? <- { true }
-						matchlen <- { cur }
+					if: allBasic? {
+						#{
+							matched? <- { true }
+							matchlen <- { cur }
+							basicYield? <- { true }
+							yield <- { orig from: 0 withLength: cur }
+						}
+					} else: {
+						yieldvals <- yieldvals reverse
+						#{
+							matched? <- { true }
+							matchlen <- { cur }
+							basicYield? <- { false }
+							yield <- { yieldvals }
+						}
 					}
 				} else: {
 					#{
@@ -257,6 +286,28 @@
 		}
 	}
 
+	match:yield <- macro: :matchexpr :ylambda {
+		mc <- _makeMatchCall: matchexpr
+		if: (mc valid?) {
+			mcall <- mc matchcall
+			quote: :tomatch {
+				res <- mcall
+				if: (res matched?) {
+					#{
+						matched? <- { true }
+						matchlen <- { res matchlen }
+						basicYield? <- { false }
+						yield <- ylambda
+					}
+				} else: {
+					res
+				}
+			}
+		} else: {
+			print: "#error Invalid macth:yield macro call: " . (mc message) . "\n"
+		}
+	}
+
 
 	_alpha <- charClass: "a-zA-Z"
 	alpha <- zeroPlus: _alpha
@@ -266,6 +317,18 @@
 		"/*" . (zeroPlus: (matchOne: [(charClass: "^*") "*" . (charClass: "^/")])) . "*/"
 	])
 
+	digit <- matchOne: [
+		(match: "0" yield: {0})
+		(match: "1" yield: {1})
+		(match: "2" yield: {2})
+		(match: "3" yield: {3})
+		(match: "4" yield: {4})
+		(match: "5" yield: {5})
+		(match: "6" yield: {6})
+		(match: "7" yield: {7})
+		(match: "8" yield: {8})
+		(match: "9" yield: {9})
+	]
 
 	main <- {
 		cmatch <- alpha: "czx0123"
@@ -293,5 +356,11 @@
 		} else: {
 			print: stuff . " did not match hws rule\n"
 		}
+		tmatch <- digit: "3"
+		if: (tmatch matched?) {
+			print: "3 matched with yield " . (tmatch yield) . ", yield + 1 = " . ((tmatch yield) + 1) . "\n"
+		} else: {
+			print: "3 did not match\n"
+		}
 	}
 }