-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fab7827
commit cbf9203
Showing
6 changed files
with
167 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { lex } from './lexer'; | ||
import { Identifier } from '../shared/tokens'; | ||
import { ThenI, SaveThe, IntoTheFile } from './tokens'; | ||
|
||
test('that lexing works', async () => { | ||
// Given I have a contract with filesystem statements in it | ||
const contract = `Rule unknown ignore | ||
Given I have a 'string' named 'stringToWrite' | ||
and I have a 'string' named 'nameOfTheFile' | ||
Then I save the 'stringToWrite' into the file 'nameOfTheFile' | ||
`; | ||
// When I lex it | ||
const lexed = await lex(contract, { data: { stringToWrite: 'foo', nameOfTheFile: 'bar' } }); | ||
// Then the result must have no errors | ||
expect(lexed.errors).toHaveLength(0); | ||
// and it must have 5 tokens | ||
expect(lexed.tokens).toHaveLength(5); | ||
// and those tokens must be these: | ||
expect(lexed.tokens[0].tokenType).toStrictEqual(ThenI); | ||
expect(lexed.tokens[1].tokenType).toStrictEqual(SaveThe); | ||
expect(lexed.tokens[2].tokenType).toStrictEqual(Identifier); | ||
expect(lexed.tokens[3].tokenType).toStrictEqual(IntoTheFile); | ||
expect(lexed.tokens[4].tokenType).toStrictEqual(Identifier); | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ZenroomParams } from '../shared/zenroom'; | ||
import { vocab } from './tokens'; | ||
import { getIgnoredStatements } from '../ignored'; | ||
|
||
import { Lexer } from 'chevrotain'; | ||
|
||
const FsLexer = new Lexer(vocab); | ||
|
||
/** | ||
* Lexes the input text for filesystem statements. | ||
* | ||
* @param contract the zencode contract to be lexed. | ||
* @returns the lexed result. | ||
*/ | ||
export const lex = async (contract: string, params?: ZenroomParams) => { | ||
const ignored = await getIgnoredStatements(contract, params); | ||
return FsLexer.tokenize(ignored.join('\n')); | ||
}; |
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 |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Identifier } from '../shared/tokens'; | ||
import { ZenroomParams } from '../shared/zenroom'; | ||
import { IntoTheFile, SaveThe, ThenI, vocab } from './tokens'; | ||
import { lex } from './lexer'; | ||
|
||
import { CstParser, IToken } from 'chevrotain'; | ||
|
||
export type FileOverrideStatementCtx = { | ||
ThenI: [IToken]; | ||
SaveThe: [IToken]; | ||
content: [IToken]; | ||
IntoTheFile: [IToken]; | ||
filename: [IToken]; | ||
}; | ||
|
||
class Parser extends CstParser { | ||
constructor() { | ||
super(vocab); | ||
this.performSelfAnalysis(); | ||
} | ||
|
||
public fileOverrideStatement = this.RULE('fileOverrideStatement', () => { | ||
this.CONSUME(ThenI); | ||
this.CONSUME(SaveThe); | ||
this.CONSUME(Identifier, { LABEL: 'content' }); | ||
this.CONSUME(IntoTheFile); | ||
this.CONSUME2(Identifier, { LABEL: 'filename' }); | ||
}); | ||
} | ||
|
||
export const FsParser = new Parser(); | ||
export const BaseFsVisitor = FsParser.getBaseCstVisitorConstructor(); | ||
|
||
export const parse = async (contract: string, params?: ZenroomParams) => { | ||
const lexed = await lex(contract, params); | ||
FsParser.input = lexed.tokens; | ||
return FsParser.fileOverrideStatement(); | ||
}; |
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 |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Whitespace, Comment, Identifier } from '../shared/tokens'; | ||
|
||
import { createToken } from 'chevrotain'; | ||
|
||
// TODO: maybe this should be put in shared and/or the "I" part should be split up. | ||
/** | ||
* The "Then I" statement. | ||
*/ | ||
export const ThenI = createToken({ | ||
name: 'ThenI', | ||
pattern: /Then I/ | ||
}); | ||
|
||
/** | ||
* The "save the" statement, used to write files to the filesystems. | ||
*/ | ||
export const SaveThe = createToken({ | ||
name: 'SaveThe', | ||
pattern: /save the/ | ||
}); | ||
|
||
/** | ||
* The "into the file" statement, used to indicate the file to which to | ||
* write. | ||
*/ | ||
export const IntoTheFile = createToken({ | ||
name: 'IntoTheFile', | ||
pattern: /into the file/ | ||
}); | ||
|
||
/** | ||
* Vocabulary to perform filesystems actions. | ||
*/ | ||
export const vocab = [Whitespace, Comment, ThenI, SaveThe, IntoTheFile, Identifier]; |
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 |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { visit } from './visitor'; | ||
|
||
test('that', async () => { | ||
// Given I have a contract with filesystem statements in it | ||
const contract = `Rule unknown ignore | ||
Given I have a 'string' named 'stringToWrite' | ||
and I have a 'string' named 'nameOfTheFile' | ||
Then I save the 'stringToWrite' into the file 'nameOfTheFile' | ||
`; | ||
const ast = await visit(contract, { | ||
data: { stringToWrite: 'hello world', nameOfTheFile: 'hello-world.txt' } | ||
}); | ||
|
||
expect(true).toStrictEqual(true); | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { ZenroomParams } from '../shared/zenroom'; | ||
import { BaseFsVisitor, parse, type FileOverrideStatementCtx } from './parser'; | ||
|
||
import { type CstNode } from 'chevrotain'; | ||
|
||
export type FileOverrideStatement = { | ||
content: string; | ||
filename: string; | ||
}; | ||
|
||
interface Visitor { | ||
visit(params: CstNode): FileOverrideStatement; | ||
} | ||
|
||
class Visitor extends BaseFsVisitor { | ||
constructor() { | ||
super(); | ||
this.validateVisitor(); | ||
} | ||
|
||
fileOverrideStatement(ctx: FileOverrideStatementCtx) { | ||
const content = ctx.content[0].image; | ||
const filename = ctx.filename[0].image; | ||
return { | ||
content: content, | ||
filename: filename | ||
}; | ||
} | ||
} | ||
|
||
export const FsVisitor = new Visitor(); | ||
|
||
export const visit = async (contract: string, params?: ZenroomParams) => { | ||
const parsed = await parse(contract, params); | ||
return FsVisitor.visit(parsed); | ||
}; |