ometa multiword{ isKeyword :x = ?multiword._isKeyword(x), isKeywordPart :x = ?multiword._isKeywordPart(x), letters = letter+:l -> l.join(''), word = letters:w -> {kind: 'word', value: w}, scanner = space* word, token :k = scanner:t ?(t.kind==k) -> t.value, keywordRest :p = "word":w {p + ' ' + w}:n (isKeyword(n) -> ['keyword', n] | isKeywordPart(n) keywordRest(n):a -> a), keyword = "word":w (isKeyword(w) -> ['keyword', w] | isKeywordPart(w) keywordRest(w):a -> a), verb = ("word":k ~isKeyword(k) -> k):v -> ['verb', v], expr = keyword:k verb+:v {alert(v)} keyword:e -> [k, v, e] } multiword.keywords = {} keywords = ["one", "two or more"] for (var idx = 0; idx < keywords.length; idx++){multiword.keywords[keywords[idx]] = true} multiword._isKeyword = function(k) { return this.keywords.hasOwnProperty(k) } multiword.keywordParts = {} keywordParts = ["two", "two or"] for (var idx = 0; idx < keywords.length; idx++){multiword.keywordParts[keywordParts[idx]] = true} multiword._isKeywordPart = function(k) { return this.keywordParts.hasOwnProperty(k) } sentence = 'one can have two or more' multiword.matchAll(sentence, 'expr') [[keyword, one], [verb, canhave], [keyword, two or more]]