-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: value converter for strings & ints (#655)
### Summary of Changes Add conversion for ints and strings, including proper handling of escape sequences. --------- Co-authored-by: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com>
- Loading branch information
1 parent
594c2c8
commit aafa2e3
Showing
10 changed files
with
275 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,77 @@ | ||
import { convertString, CstNode, DefaultValueConverter, GrammarAST, ValueType } from 'langium'; | ||
import { convertBigint, CstNode, DefaultValueConverter, GrammarAST, ValueType } from 'langium'; | ||
|
||
export class SafeDsValueConverter extends DefaultValueConverter { | ||
protected override runConverter(rule: GrammarAST.AbstractRule, input: string, cstNode: CstNode): ValueType { | ||
switch (rule.name.toUpperCase()) { | ||
case 'ID': | ||
return input.replaceAll('`', ''); | ||
case 'INT': | ||
return convertBigint(input); | ||
case 'STRING': | ||
return convertString(input, 1, 1); | ||
case 'TEMPLATE_STRING_START': | ||
return convertString(input.substring(0, input.length - 1)); | ||
return convertString(input, 1, 2); | ||
case 'TEMPLATE_STRING_INNER': | ||
return convertString(input.substring(1, input.length - 1)); | ||
return convertString(input, 2, 2); | ||
case 'TEMPLATE_STRING_END': | ||
return convertString(input.substring(1)); | ||
return convertString(input, 2, 1); | ||
default: | ||
return super.runConverter(rule, input, cstNode); | ||
} | ||
} | ||
} | ||
|
||
const convertString = (input: string, openingDelimiterLength: number, closingDelimiterLength: number): string => { | ||
let result = ''; | ||
const endIndex = input.length - 1 - closingDelimiterLength; | ||
|
||
for (let i = openingDelimiterLength; i <= endIndex; i++) { | ||
const current = input.charAt(i); | ||
if (current === '\\' && i < endIndex) { | ||
const [stringToAdd, newIndex] = handleEscapeSequence(input, i + 1, endIndex); | ||
result += stringToAdd; | ||
i = newIndex - 1; // -1 because the loop will increment it | ||
} else { | ||
result += current; | ||
} | ||
} | ||
|
||
return result; | ||
}; | ||
|
||
/** | ||
* Handle an escape sequence. | ||
* | ||
* @param input The entire input string. | ||
* @param index The index of the escape sequence (after the slash). | ||
* @param endIndex The index of the last character of the input string, excluding delimiters. | ||
* @returns An array containing the string to add to the result and the new index. | ||
*/ | ||
const handleEscapeSequence = (input: string, index: number, endIndex: number): [string, number] => { | ||
const current = input.charAt(index); | ||
switch (current) { | ||
case 'b': | ||
return ['\b', index + 1]; | ||
case 'f': | ||
return ['\f', index + 1]; | ||
case 'n': | ||
return ['\n', index + 1]; | ||
case 'r': | ||
return ['\r', index + 1]; | ||
case 't': | ||
return ['\t', index + 1]; | ||
case 'v': | ||
return ['\v', index + 1]; | ||
case '0': | ||
return ['\0', index + 1]; | ||
} | ||
|
||
if (current === 'u' && index + 4 <= endIndex) { | ||
const code = input.substring(index + 1, index + 5); | ||
if (code.match(/[0-9a-fA-F]{4}/gu)) { | ||
return [String.fromCharCode(parseInt(code, 16)), index + 5]; | ||
} | ||
} | ||
|
||
return [current, index + 1]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.