#!/usr/bin/env ascript
tokenize(str:string):dynamic_scope {`block} = {
	import(re)
	entriesDict = dict()
	parseBlock(block:expr) = block.each():xlist {|expr|
		if (!expr.isdictassign()) {
			raise(SyntaxError, "invalid element")
		} elsif (expr.left().isquote()) {
			exprLeft = expr.left().unquote()
			entriesDict[exprLeft.getsymbol()] = parseBlock(expr.right())
			nil
		} else {
			[re.pattern('^' + expr.left().getstring()), expr.right().tofunction()]
		}
	}
	entriesDict[`start] = parseBlock(block)
	pos = 0
	_mode = `start
	setMode(mode:symbol) = {
		_mode = mode
	}
	repeat {
		matchFlag = false
		for ([regex, func] in entriesDict[_mode]) {
			if (m = regex.match(str, pos)) {
				func(m)
				pos = m.end(0)
				matchFlag = true
				break
			}
		}
		if (!matchFlag) {
			#raise(ValueError, "unrecognizable token")
			break
		}
	}
}

if (__name__ == "__main__") {
	x = 1
	tokenize('func(1, 2, "abcdefg", 3, 4)') {
		r'[a-zA-Z]\w+' => {|m|
			println(m.group(0))
		}
		r'\d+' => {|m|
			println(m.group(0))
		}
		r'"' => {
			setMode(`string)
		}
		r'\(' => {
			println('lpar')
		}
		r'\)' => {
			println('rpar')
		}
		r',' => {|m|
			println(m.group(0))
		}
		r'\s+' => {|m|
		}
		`string => {
			r'[^"]+' => {|m|
				println(m.group(0))
			}
			r'"' => {
				setMode(`start)
			}
		}
	}
}
