Skip to content

Commit 7af1a07

Browse files
committed
using createParser to infer the correct Language Version
1 parent 9497e58 commit 7af1a07

6 files changed

Lines changed: 55 additions & 44 deletions

File tree

src/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const slangParserId = 'slang';
2+
export const slangYulParserId = 'slang-yul';
3+
export const antlrParserId = 'antlr';
4+
export const slangAstId = 'slang-ast';
5+
export const antlrAstId = 'antlr-ast';

src/index.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import yulParse from './slangYulParser.js';
1010
import slangPrint from './slangPrinter.js';
1111
import { isBlockComment, isComment } from './slang-utils/is-comment.js';
1212
import { locEnd, locStart } from './slang-utils/loc.js';
13+
import {
14+
slangParserId,
15+
slangYulParserId,
16+
antlrParserId,
17+
slangAstId,
18+
antlrAstId
19+
} from './constants.js';
1320

1421
import type {
1522
Parser,
@@ -19,12 +26,6 @@ import type {
1926
} from 'prettier';
2027
import type { AstNode } from './slang-nodes/types.d.ts';
2128

22-
const slangParserId = 'slang';
23-
const slangYulParserId = 'slang-yul';
24-
const antlrParserId = 'antlr';
25-
const slangAstId = 'slang-ast';
26-
const antlrAstId = 'antlr-ast';
27-
2829
// https://prettier.io/docs/en/plugins.html#languages
2930
// https://github.com/github-linguist/linguist/blob/master/lib/linguist/languages.yml
3031
const languages: SupportLanguage[] = [

src/slang-utils/create-parser.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst';
22
import { Parser } from '@nomicfoundation/slang/parser';
33
import { LanguageFacts } from '@nomicfoundation/slang/utils';
44
import { maxSatisfying } from 'semver';
5+
import { slangParserId, slangYulParserId } from '../constants.js';
56

67
import type { ParseOutput } from '@nomicfoundation/slang/parser';
78
import type { ParserOptions } from 'prettier';
@@ -12,13 +13,25 @@ const supportedLength = supportedVersions.length;
1213

1314
function parserAndOutput(
1415
text: string,
15-
version: string
16+
version: string,
17+
{ parser: optionsParser }: ParserOptions<AstNode>
1618
): { parser: Parser; parseOutput: ParseOutput } {
19+
let rootKind;
20+
switch (optionsParser) {
21+
case slangParserId:
22+
rootKind = NonterminalKind.SourceUnit;
23+
break;
24+
case slangYulParserId:
25+
rootKind = NonterminalKind.YulBlock;
26+
break;
27+
default:
28+
throw new Error(
29+
`Parser '${optionsParser as string}' is not supported for Language Inference.`
30+
);
31+
}
32+
1733
const parser = Parser.create(version);
18-
return {
19-
parser,
20-
parseOutput: parser.parseNonterminal(NonterminalKind.SourceUnit, text)
21-
};
34+
return { parser, parseOutput: parser.parseNonterminal(rootKind, text) };
2235
}
2336

2437
function createError(
@@ -36,7 +49,7 @@ export function createParser(
3649
): { parser: Parser; parseOutput: ParseOutput } {
3750
const compiler = maxSatisfying(supportedVersions, options.compiler);
3851
if (compiler) {
39-
const result = parserAndOutput(text, compiler);
52+
const result = parserAndOutput(text, compiler, options);
4053

4154
if (!result.parseOutput.isValid())
4255
throw createError(
@@ -55,7 +68,8 @@ export function createParser(
5568
if (inferredLength === 0 || inferredLength === supportedLength) {
5669
const result = parserAndOutput(
5770
text,
58-
supportedVersions[supportedLength - 1]
71+
supportedVersions[supportedLength - 1],
72+
options
5973
);
6074

6175
if (!result.parseOutput.isValid())
@@ -70,7 +84,8 @@ export function createParser(
7084

7185
const result = parserAndOutput(
7286
text,
73-
inferredRanges[inferredRanges.length - 1]
87+
inferredRanges[inferredLength - 1],
88+
options
7489
);
7590

7691
if (!result.parseOutput.isValid())

src/slangYulParser.ts

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
// https://prettier.io/docs/en/plugins.html#parsers
22
import { YulBlock as SlangYulBlock } from '@nomicfoundation/slang/ast';
3-
import { NonterminalKind } from '@nomicfoundation/slang/cst';
4-
import { Parser } from '@nomicfoundation/slang/parser';
5-
import { LanguageFacts } from '@nomicfoundation/slang/utils';
6-
import { coerce } from 'semver';
7-
import { clearOffsets } from './slang-utils/metadata.js';
3+
import { clearOffsets } from './slang-nodes/SlangNode.js';
4+
import { createParser } from './slang-utils/create-parser.js';
85
import { YulBlock } from './slang-nodes/YulBlock.js';
96

107
import type { ParserOptions } from 'prettier';
@@ -14,27 +11,14 @@ export default function parse(
1411
text: string,
1512
options: ParserOptions<AstNode>
1613
): AstNode {
17-
// const [parser, parseOutput] = createParser(text, options);
18-
const compiler = coerce(options.compiler);
19-
const supportedVersions = LanguageFacts.allVersions();
14+
const { parser, parseOutput } = createParser(text, options);
2015

21-
const parser = Parser.create(
22-
compiler && supportedVersions.includes(compiler.version)
23-
? compiler.version
24-
: supportedVersions[supportedVersions.length - 1]
16+
// We update the compiler version by the inferred one.
17+
options.compiler = parser.languageVersion;
18+
const parsed = new YulBlock(
19+
new SlangYulBlock(parseOutput.tree.asNonterminalNode()),
20+
options
2521
);
26-
27-
const parseOutput = parser.parseNonterminal(NonterminalKind.YulBlock, text);
28-
29-
if (parseOutput.isValid()) {
30-
// We update the compiler version by the inferred one.
31-
options.compiler = parser.languageVersion;
32-
const parsed = new YulBlock(
33-
new SlangYulBlock(parseOutput.tree.asNonterminalNode()),
34-
options
35-
);
36-
clearOffsets();
37-
return parsed;
38-
}
39-
throw new Error(parseOutput.errors()[0].message);
22+
clearOffsets();
23+
return parsed;
4024
}

tests/format/Yul/__snapshots__/format.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Jest Snapshot v1, https://goo.gl/fbAQLP
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
22

33
exports[`example1.yul format 1`] = `
44
====================================options=====================================

tests/unit/slang-utils/create-parser.test.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { LanguageFacts } from '@nomicfoundation/slang/utils';
22
import { createParser } from '../../../src/slang-utils/create-parser.js';
3+
import { slangParserId } from '../../../src/constants.js';
34

45
describe('inferLanguage', function () {
56
const latestSupportedVersion = LanguageFacts.latestVersion();
6-
const options = { filepath: 'test.sol' };
7+
const options = { parser: slangParserId };
78

89
const fixtures = [
910
{
@@ -97,22 +98,27 @@ describe('inferLanguage', function () {
9798

9899
test('should use compiler option if given', function () {
99100
let { parser } = createParser(`pragma solidity ^0.8.0;`, {
101+
...options,
100102
compiler: '0.8.20'
101103
});
102104
expect(parser.languageVersion).toEqual('0.8.20');
103105

104106
({ parser } = createParser(`pragma solidity ^0.8.0;`, {
107+
...options,
105108
compiler: '0.8.2'
106109
}));
107110
expect(parser.languageVersion).toEqual('0.8.2');
108111

109-
({ parser } = createParser(`pragma solidity ^0.7.0;`, {}));
112+
({ parser } = createParser(`pragma solidity ^0.7.0;`, options));
110113
expect(parser.languageVersion).toEqual('0.7.6');
111114
});
112115

113116
test('should throw if compiler option does not match the syntax', function () {
114117
expect(() =>
115-
createParser(`contract Foo {byte bar;}`, { compiler: '0.8.0' })
118+
createParser(`contract Foo {byte bar;}`, {
119+
...options,
120+
compiler: '0.8.0'
121+
})
116122
).toThrow(
117123
'Based on the compiler option provided, we inferred your code to be using Solidity version'
118124
);

0 commit comments

Comments
 (0)