diff --git a/packages/generator-langium/langium-template/src/language-server/language-id.langium b/packages/generator-langium/langium-template/src/language-server/language-id.langium index 82158a90c..d0b82a1d2 100644 --- a/packages/generator-langium/langium-template/src/language-server/language-id.langium +++ b/packages/generator-langium/langium-template/src/language-server/language-id.langium @@ -1,13 +1,13 @@ grammar <%= LanguageName %> -Model: +entry Model: (persons+=Person | greetings+=Greeting)*; Person: 'person' name=ID; Greeting: - 'Hello' person=[Person|ID] '!'; + 'Hello' person=[Person:ID] '!'; hidden terminal WS: /\s+/; terminal ID: /[_a-zA-Z][\w_]*/; diff --git a/packages/langium-cli/src/generator/textmate-generator.ts b/packages/langium-cli/src/generator/textmate-generator.ts index d4fb91402..81a6f0b67 100644 --- a/packages/langium-cli/src/generator/textmate-generator.ts +++ b/packages/langium-cli/src/generator/textmate-generator.ts @@ -118,12 +118,45 @@ function getControlKeywords(grammar: langium.Grammar, pack: LangiumConfig): Patt const regex = /[A-Za-z]/; const controlKeywords = collectKeywords(grammar).filter(kw => regex.test(kw)); const keywords = controlKeywords.map(escapeRegExp); + const groups = groupKeywords(keywords); return { 'name': `keyword.control.${pack.languageId}`, - 'match': `\\b(${keywords.join('|')})\\b` + 'match': groups.join('|') }; } +function groupKeywords(keywords: string[]): string[] { + const groups: { + letter: string[], + leftSpecial: string[], + rightSpecial: string[], + special: string[] + } = {letter: [], leftSpecial: [], rightSpecial: [], special: []}; + + keywords.forEach(keyword => { + if (/\w/.test(keyword[0])) { + if (/\w/.test(keyword[keyword.length - 1])) { + groups.letter.push(keyword); + } else { + groups.rightSpecial.push(keyword); + } + } else { + if ((/\w/).test(keyword[keyword.length - 1])) { + groups.leftSpecial.push(keyword); + } else { + groups.special.push(keyword); + } + } + }); + + const res = []; + if (groups.letter.length) res.push(`\\b(${groups.letter.join('|')})\\b`); + if (groups.leftSpecial.length) res.push(`\\B(${groups.leftSpecial.join('|')})\\b`); + if (groups.rightSpecial.length) res.push(`\\b(${groups.rightSpecial.join('|')})\\B`); + if (groups.special.length) res.push(`\\B(${groups.special.join('|')})\\B`); + return res; +} + function getStringPatterns(grammar: langium.Grammar, pack: LangiumConfig): Pattern[] { const terminals = langium.stream(grammar.rules).filter(langium.isTerminalRule); const stringTerminal = terminals.find(e => e.name.toLowerCase() === 'string');