ometa multiword{ word = letter+:w -> {kind: 'word', value: w.join('')}, scanner = space* word, token :k = scanner:t ?(t.kind==k) -> t.value, isKeyword :x = ?multiword._isKeyword(x), isKeywordStart :p :q = &(space seq(q) "word":w) {q != '' ? q + ' ' + w : w}:w {p + ' ' + w}:n (isKeyword(n) -> true | isKeywordStart(p, w) -> true), keywordR :p = "word":w {p!=''?p+' '+w:w}:w (isKeyword(w) -> w | keywordR(w):a -> a), keyword = keywordR(''):k -> [#keyword, k], text = ("word":k ~isKeyword(k) ~isKeywordStart(k,'') -> k)*:t -> ['text', t.join(' ')], expr = keyword:k text:t keyword:e -> [k, t, e] } multiword.keywords = {} keywords = ["one thing", "two or more things"] for (var idx = 0; idx < keywords.length; idx++){multiword.keywords[keywords[idx]] = true} multiword._isKeyword = function(k) { return this.keywords.hasOwnProperty(k) } sentence = 'one thing can have two or more things' multiword.matchAll(sentence, 'expr')