include and "include as"

This commit is contained in:
Umur Ozkul 2022-08-31 23:54:54 +02:00
parent 68ddf35387
commit 82a4e52384
15 changed files with 732 additions and 241 deletions

View File

@ -0,0 +1,27 @@
@@warning("-44")
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
module Bindings = Reducer_Bindings
open Jest
open Expect
open Expect.Operators
describe("Name Space", () => {
let value = InternalExpressionValue.IEvNumber(1967.0)
let nameSpace = Bindings.emptyNameSpace->Bindings.set("value", value)
test("get", () => {
expect(Bindings.get(nameSpace, "value")) == Some(value)
})
test("chain and get", () => {
let mainNameSpace = Bindings.emptyNameSpace->Bindings.chainTo([nameSpace])
expect(Bindings.get(mainNameSpace, "value")) == Some(value)
})
test("chain and set", () => {
let mainNameSpace0 = Bindings.emptyNameSpace->Bindings.chainTo([nameSpace])
let mainNameSpace =
mainNameSpace0->Bindings.set("value", InternalExpressionValue.IEvNumber(1968.0))
expect(Bindings.get(mainNameSpace, "value")) == Some(InternalExpressionValue.IEvNumber(1968.0))
})
})

View File

@ -7,7 +7,7 @@ open Jest
open Expect open Expect
open Expect.Operators open Expect.Operators
Only.describe("Parse includes", () => { describe("Parse includes", () => {
let project = Project.createProject() let project = Project.createProject()
Project.setSource( Project.setSource(
project, project,
@ -30,4 +30,92 @@ x=1`,
| Error(error) => fail(error->Reducer_ErrorValue.errorToString) | Error(error) => fail(error->Reducer_ErrorValue.errorToString)
} }
}) })
let internalProject = project->Project.T.Private.castToInternalProject
test("past chain", () => {
expect(Project.Private.getPastChain(internalProject, "main")) == ["common"]
})
test("import as variables", () => {
expect(Project.Private.getIncludesAsVariables(internalProject, "main")) == []
})
})
describe("Parse includes", () => {
let project = Project.createProject()
Project.setSource(
project,
"main",
`
#include 'common'
#include 'myModule' as myVariable
x=1`,
)
Project.parseIncludes(project, "main")
test("dependencies", () => {
expect(Project.getDependencies(project, "main")) == ["common", "myModule"]
})
test("dependents", () => {
expect(Project.getDependents(project, "main")) == []
})
test("getIncludes", () => {
let mainIncludes = Project.getIncludes(project, "main")
switch mainIncludes {
| Ok(includes) => expect(includes) == ["common", "myModule"]
| Error(error) => fail(error->Reducer_ErrorValue.errorToString)
}
})
let internalProject = project->Project.T.Private.castToInternalProject
test("direct past chain", () => {
expect(Project.Private.getPastChain(internalProject, "main")) == ["common"]
})
test("direct includes", () => {
expect(Project.Private.getDirectIncludes(internalProject, "main")) == ["common"]
})
test("include as variables", () => {
expect(Project.Private.getIncludesAsVariables(internalProject, "main")) == [
("myVariable", "myModule"),
]
})
})
describe("Parse multiple direct includes", () => {
let project = Project.createProject()
Project.setSource(
project,
"main",
`
#include 'common'
#include 'common2'
#include 'myModule' as myVariable
x=1`,
)
Project.parseIncludes(project, "main")
test("dependencies", () => {
expect(Project.getDependencies(project, "main")) == ["common", "common2", "myModule"]
})
test("dependents", () => {
expect(Project.getDependents(project, "main")) == []
})
test("getIncludes", () => {
let mainIncludes = Project.getIncludes(project, "main")
switch mainIncludes {
| Ok(includes) => expect(includes) == ["common", "common2", "myModule"]
| Error(error) => fail(error->Reducer_ErrorValue.errorToString)
}
})
let internalProject = project->Project.T.Private.castToInternalProject
test("direct past chain", () => {
expect(Project.getPastChain(project, "main")) == ["common", "common2"]
})
test("include as variables", () => {
expect(Project.Private.getIncludesAsVariables(internalProject, "main")) == [
("myVariable", "myModule"),
]
})
}) })

View File

@ -14,11 +14,9 @@ let runFetchResult = (project, sourceId) => {
Project.getResult(project, sourceId)->InternalExpressionValue.toStringResult Project.getResult(project, sourceId)->InternalExpressionValue.toStringResult
} }
let runFetchBindings = (project, sourceId) => { let runFetchFlatBindings = (project, sourceId) => {
Project.run(project, sourceId) Project.run(project, sourceId)
Project.getBindings(project, sourceId) Project.getBindings(project, sourceId)->InternalExpressionValue.toStringBindings
->InternalExpressionValue.IEvBindings
->InternalExpressionValue.toString
} }
test("setting continuation", () => { test("setting continuation", () => {
@ -51,7 +49,7 @@ test("test library", () => {
test("test bindings", () => { test("test bindings", () => {
let project = Project.createProject() let project = Project.createProject()
Project.setSource(project, "variables", "myVariable=666") Project.setSource(project, "variables", "myVariable=666")
runFetchBindings(project, "variables")->expect->toBe("@{myVariable: 666}") runFetchFlatBindings(project, "variables")->expect->toBe("@{myVariable: 666}")
}) })
describe("project1", () => { describe("project1", () => {
@ -59,6 +57,7 @@ describe("project1", () => {
Project.setSource(project, "first", "x=1") Project.setSource(project, "first", "x=1")
Project.setSource(project, "main", "x") Project.setSource(project, "main", "x")
Project.setContinues(project, "main", ["first"]) Project.setContinues(project, "main", ["first"])
let internalProject = project->Project.T.Private.castToInternalProject
test("runOrder", () => { test("runOrder", () => {
expect(Project.getRunOrder(project)) == ["first", "main"] expect(Project.getRunOrder(project)) == ["first", "main"]
@ -75,11 +74,19 @@ describe("project1", () => {
test("dependencies main", () => { test("dependencies main", () => {
expect(Project.getDependencies(project, "main")) == ["first"] expect(Project.getDependencies(project, "main")) == ["first"]
}) })
test("past chain first", () => {
expect(Project.Private.getPastChain(internalProject, "first")) == []
})
test("past chain main", () => {
expect(Project.Private.getPastChain(internalProject, "main")) == ["first"]
})
test("test result", () => { test("test result", () => {
runFetchResult(project, "main")->expect->toBe("Ok(1)") runFetchResult(project, "main")->expect->toBe("Ok(1)")
}) })
test("test bindings", () => { test("test bindings", () => {
runFetchBindings(project, "main")->expect->toBe("@{x: 1}") runFetchFlatBindings(project, "first")->expect->toBe("@{x: 1}")
}) })
}) })
@ -113,7 +120,7 @@ describe("project2", () => {
runFetchResult(project, "main")->expect->toBe("Ok(2)") runFetchResult(project, "main")->expect->toBe("Ok(2)")
}) })
test("test bindings", () => { test("test bindings", () => {
runFetchBindings(project, "main")->expect->toBe("@{x: 1,y: 2}") runFetchFlatBindings(project, "main")->expect->toBe("@{x: 1,y: 2}")
}) })
}) })
@ -169,6 +176,6 @@ describe("project with include", () => {
runFetchResult(project, "main")->expect->toBe("Ok(2)") runFetchResult(project, "main")->expect->toBe("Ok(2)")
}) })
test("test bindings", () => { test("test bindings", () => {
runFetchBindings(project, "main")->expect->toBe("@{common: 0,x: 1,y: 2}") runFetchFlatBindings(project, "main")->expect->toBe("@{common: 0,x: 1,y: 2}")
}) })
}) })

View File

@ -153,4 +153,27 @@ Here we will finally proceed to a real life scenario. */
}) })
}) })
}) })
describe("Includes myFile as myVariable", () => {
/* Instead of including into global space you can also put a module into a record variable */
let project = Project.createProject()
Project.setSource(
project,
"main",
`
#include "common" as common
x=1
`,
)
Project.parseIncludes(project, "main")
test("getDependencies", () => {
Project.getDependencies(project, "main")->expect == ["common"]
})
test("getIncludes", () => {
switch Project.getIncludes(project, "main") {
| Ok(includes) => includes->expect == ["common"]
| Error(err) => err->Reducer_ErrorValue.errorToString->fail
}
})
})
}) })

View File

@ -105,6 +105,11 @@ let getIncludes = (project: reducerProject, sourceId: string): result<
reducerErrorValue, reducerErrorValue,
> => project->T.Private.castToInternalProject->Private.getIncludes(sourceId) > => project->T.Private.castToInternalProject->Private.getIncludes(sourceId)
/* Other sources contributing to the global namespace of this source. */
@genType
let getPastChain = (project: reducerProject, sourceId: string): array<string> =>
project->T.Private.castToInternalProject->Private.getPastChain(sourceId)
/* /*
Answers the source codes after which this source code is continuing Answers the source codes after which this source code is continuing
*/ */
@ -183,7 +188,7 @@ let runAll = (project: reducerProject): unit =>
project->T.Private.castToInternalProject->Private.runAll project->T.Private.castToInternalProject->Private.runAll
/* /*
Get the bindings after running this source file or the project Get the bindings after running this source fil. The bindings are local to the source
*/ */
@genType @genType
let getBindings = (project: reducerProject, sourceId: string): squiggleValue_Module => let getBindings = (project: reducerProject, sourceId: string): squiggleValue_Module =>

View File

@ -1,5 +1,5 @@
// Only Bindings as the global module is supported // Only Bindings as the global module is supported
// Other module operations such as import export will be prepreocessed jobs // Other module operations such as import export will be preprocessed jobs
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module InternalExpressionValue = ReducerInterface_InternalExpressionValue module InternalExpressionValue = ReducerInterface_InternalExpressionValue
@ -13,8 +13,7 @@ type t = ReducerInterface_InternalExpressionValue.nameSpace
let typeAliasesKey = "_typeAliases_" let typeAliasesKey = "_typeAliases_"
let typeReferencesKey = "_typeReferences_" let typeReferencesKey = "_typeReferences_"
let getType = (nameSpace: t, id: string) => { let getType = (NameSpace(container): t, id: string) => {
let NameSpace(container) = nameSpace
Belt.Map.String.get(container, typeAliasesKey)->Belt.Option.flatMap(aliases => Belt.Map.String.get(container, typeAliasesKey)->Belt.Option.flatMap(aliases =>
switch aliases { switch aliases {
| IEvRecord(r) => Belt.Map.String.get(r, id) | IEvRecord(r) => Belt.Map.String.get(r, id)
@ -23,8 +22,7 @@ let getType = (nameSpace: t, id: string) => {
) )
} }
let getTypeOf = (nameSpace: t, id: string) => { let getTypeOf = (NameSpace(container): t, id: string) => {
let NameSpace(container) = nameSpace
Belt.Map.String.get(container, typeReferencesKey)->Belt.Option.flatMap(defs => Belt.Map.String.get(container, typeReferencesKey)->Belt.Option.flatMap(defs =>
switch defs { switch defs {
| IEvRecord(r) => Belt.Map.String.get(r, id) | IEvRecord(r) => Belt.Map.String.get(r, id)
@ -33,44 +31,39 @@ let getTypeOf = (nameSpace: t, id: string) => {
) )
} }
let getWithDefault = (nameSpace: t, id: string, default) => { let getWithDefault = (NameSpace(container): t, id: string, default) =>
let NameSpace(container) = nameSpace switch Belt.Map.String.get(container, id) {
Belt.Map.String.getWithDefault(container, id, default) | Some(v) => v
} | None => default
}
let get = (nameSpace: t, id: string) => { let get = (NameSpace(container): t, id: string) => Belt.Map.String.get(container, id)
let NameSpace(container) = nameSpace
Belt.Map.String.get(container, id)
}
let emptyMap: map = Belt.Map.String.empty let emptyMap: map = Belt.Map.String.empty
let setTypeAlias = (nameSpace: t, id: string, value): t => { let setTypeAlias = (NameSpace(container): t, id: string, value): t => {
let NameSpace(container) = nameSpace
let rValue = Belt.Map.String.getWithDefault(container, typeAliasesKey, IEvRecord(emptyMap)) let rValue = Belt.Map.String.getWithDefault(container, typeAliasesKey, IEvRecord(emptyMap))
let r = switch rValue { let r = switch rValue {
| IEvRecord(r) => r | IEvRecord(r) => r
| _ => emptyMap | _ => emptyMap
} }
let r2 = Belt.Map.String.set(r, id, value)->IEvRecord let r2 = Belt.Map.String.set(r, id, value)->IEvRecord
Belt.Map.String.set(container, typeAliasesKey, r2)->NameSpace NameSpace(Belt.Map.String.set(container, typeAliasesKey, r2))
} }
let setTypeOf = (nameSpace: t, id: string, value): t => { let setTypeOf = (NameSpace(container): t, id: string, value): t => {
let NameSpace(container) = nameSpace
let rValue = Belt.Map.String.getWithDefault(container, typeReferencesKey, IEvRecord(emptyMap)) let rValue = Belt.Map.String.getWithDefault(container, typeReferencesKey, IEvRecord(emptyMap))
let r = switch rValue { let r = switch rValue {
| IEvRecord(r) => r | IEvRecord(r) => r
| _ => emptyMap | _ => emptyMap
} }
let r2 = Belt.Map.String.set(r, id, value)->IEvRecord let r2 = Belt.Map.String.set(r, id, value)->IEvRecord
Belt.Map.String.set(container, typeReferencesKey, r2)->NameSpace NameSpace(Belt.Map.String.set(container, typeReferencesKey, r2))
} }
let set = (nameSpace: t, id: string, value): t => { let set = (NameSpace(container): t, id: string, value): t => NameSpace(
let NameSpace(container) = nameSpace Belt.Map.String.set(container, id, value),
Belt.Map.String.set(container, id, value)->NameSpace )
}
let emptyModule: t = NameSpace(emptyMap) let emptyModule: t = NameSpace(emptyMap)
let emptyBindings = emptyModule let emptyBindings = emptyModule
@ -86,29 +79,28 @@ let fromExpressionValue = (aValue: internalExpressionValue): t =>
| _ => emptyModule | _ => emptyModule
} }
let fromArray = a => Belt.Map.String.fromArray(a)->NameSpace let fromArray = a => NameSpace(Belt.Map.String.fromArray(a))
let merge = (nameSpace: t, other: t): t => { let mergeFrom = (NameSpace(container): t, NameSpace(newContainer): t): t => {
let NameSpace(container) = nameSpace NameSpace(
let NameSpace(otherContainer) = other newContainer->Belt.Map.String.reduce(container, (container, key, value) =>
otherContainer
->Belt.Map.String.reduce(container, (container, key, value) =>
Belt.Map.String.set(container, key, value) Belt.Map.String.set(container, key, value)
),
) )
->NameSpace
} }
let removeOther = (nameSpace: t, other: t): t => { let removeOther = (NameSpace(container): t, NameSpace(otherContainer): t): t => {
let NameSpace(container) = nameSpace
let NameSpace(otherContainer) = other
let keys = Belt.Map.String.keysToArray(otherContainer) let keys = Belt.Map.String.keysToArray(otherContainer)
NameSpace(
Belt.Map.String.keep(container, (key, _value) => { Belt.Map.String.keep(container, (key, _value) => {
let removeThis = Js.Array2.includes(keys, key) let removeThis = Js.Array2.includes(keys, key)
!removeThis !removeThis
})->NameSpace }),
)
} }
external castExpressionToInternalCode: ExpressionT.expressionOrFFI => internalCode = "%identity" external castExpressionToInternalCode: ExpressionT.expressionOrFFI => internalCode = "%identity"
let eLambdaFFIValue = (ffiFn: ExpressionT.ffiFn) => { let eLambdaFFIValue = (ffiFn: ExpressionT.ffiFn) => {
IEvLambda({ IEvLambda({
parameters: [], parameters: [],
@ -153,9 +145,8 @@ let convertOptionToFfiFn = (
} }
// -- Module definition // -- Module definition
let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => { let define = (NameSpace(container): t, identifier: string, ev: internalExpressionValue): t => {
let NameSpace(container) = nameSpace NameSpace(Belt.Map.String.set(container, identifier, ev))
Belt.Map.String.set(container, identifier, ev)->NameSpace
} }
let defineNumber = (nameSpace: t, identifier: string, value: float): t => let defineNumber = (nameSpace: t, identifier: string, value: float): t =>
@ -186,3 +177,9 @@ let defineFunctionReturningResult = (
} }
let emptyStdLib: t = emptyModule->defineBool("_standardLibrary", true) let emptyStdLib: t = emptyModule->defineBool("_standardLibrary", true)
let chainTo = (nameSpace: t, previousNameSpaces: array<t>) => {
previousNameSpaces->Belt.Array.reduce(nameSpace, (topNameSpace, prevNameSpace) =>
mergeFrom(prevNameSpace, topNameSpace)
)
}

View File

@ -21,8 +21,7 @@ let inspectOption = (oNameSpace, label: string) =>
} }
let minus = (NameSpace(thisContainer): t, NameSpace(thatContainer): t) => { let minus = (NameSpace(thisContainer): t, NameSpace(thatContainer): t) => {
Belt.Map.String.removeMany( InternalExpressionValue.NameSpace(
thisContainer, Belt.Map.String.removeMany(thisContainer, Belt.Map.String.keysToArray(thatContainer)),
Belt.Map.String.keysToArray(thatContainer), )
)->InternalExpressionValue.NameSpace
} }

View File

@ -83,6 +83,21 @@ module Private = {
let getIncludes = (project: t, sourceId: string): ProjectItem.T.includesType => let getIncludes = (project: t, sourceId: string): ProjectItem.T.includesType =>
project->getItem(sourceId)->ProjectItem.getIncludes project->getItem(sourceId)->ProjectItem.getIncludes
// let getDirectIncludes = (project: t, sourceId: string): array<string> =>
// project->getItem(sourceId)->ProjectItem.getDirectIncludes
let getPastChain = (project: t, sourceId: string): array<string> =>
project->getItem(sourceId)->ProjectItem.getPastChain
let getIncludesAsVariables = (
project: t,
sourceId: string,
): ProjectItem.T.importAsVariablesType =>
project->getItem(sourceId)->ProjectItem.getIncludesAsVariables
let getDirectIncludes = (project: t, sourceId: string): array<string> =>
project->getItem(sourceId)->ProjectItem.getDirectIncludes
let setContinues = (project: t, sourceId: string, continues: array<string>): unit => { let setContinues = (project: t, sourceId: string, continues: array<string>): unit => {
let newItem = project->getItem(sourceId)->ProjectItem.setContinues(continues) let newItem = project->getItem(sourceId)->ProjectItem.setContinues(continues)
Belt.Map.String.set(project["items"], sourceId, newItem)->T.Private.setFieldItems(project, _) Belt.Map.String.set(project["items"], sourceId, newItem)->T.Private.setFieldItems(project, _)
@ -155,39 +170,63 @@ module Private = {
environment: getEnvironment(project), environment: getEnvironment(project),
} }
let doRunWithContinuation = ( let getContinuationsBefore = (project: t, sourceId: string): array<
project: t, ProjectItem.T.continuation,
sourceId: string, > => {
continuation: ProjectItem.T.continuation, let pastNameSpaces = project->getPastChain(sourceId)->Belt.Array.map(getBindings(project, _))
): unit => { let theLength = Belt.Array.length(pastNameSpaces)
if theLength == 0 {
// `getContinuationBefore ${sourceId}: stdLib`->Js.log
[project->getStdLib]
} else {
// `getContinuationBefore ${sourceId}: ${lastOne} = ${InternalExpressionValue.toStringBindings(
// project->getBindings(lastOne),
// )}`->Js.log
pastNameSpaces
}
}
let linkDependencies = (project: t, sourceId: string): ProjectItem.T.continuation => {
module NameSpace = Reducer_Bindings
let continuationsBefore = project->getContinuationsBefore(sourceId)
let nameSpace = NameSpace.emptyNameSpace->NameSpace.chainTo(continuationsBefore)
let includesAsVariables = project->getIncludesAsVariables(sourceId)
Belt.Array.reduce(includesAsVariables, nameSpace, (currentNameSpace, (variable, includeFile)) =>
Bindings.set(
currentNameSpace,
variable,
getBindings(project, includeFile)->InternalExpressionValue.IEvBindings,
)
)
}
let doLinkAndRun = (project: t, sourceId: string): unit => {
let accessors = buildProjectAccessors(project) let accessors = buildProjectAccessors(project)
let states = accessors.states let states = accessors.states
let continuation = linkDependencies(project, sourceId)
let newItem = project->getItem(sourceId)->ProjectItem.run(continuation, accessors) let newItem = project->getItem(sourceId)->ProjectItem.run(continuation, accessors)
Belt.Map.String.set(project["items"], sourceId, newItem)->T.Private.setFieldItems(project, _) Belt.Map.String.set(project["items"], sourceId, newItem)->T.Private.setFieldItems(project, _)
setContinuation(project, sourceId, states.continuation) setContinuation(project, sourceId, states.continuation)
} }
type runState = (ProjectItem.T.resultArgumentType, ProjectItem.T.continuation) type runState = ProjectItem.T.resultArgumentType
let tryRunWithContinuation = ( let tryRunWithResult = (
project: t, project: t,
sourceId: string, sourceId: string,
(rPrevResult: ProjectItem.T.resultArgumentType, continuation: ProjectItem.T.continuation), rPrevResult: ProjectItem.T.resultArgumentType,
): (ProjectItem.T.resultArgumentType, ProjectItem.T.continuation) => { ): ProjectItem.T.resultArgumentType => {
switch getResultOption(project, sourceId) { switch getResultOption(project, sourceId) {
| Some(result) => (result, getContinuation(project, sourceId)) // already ran | Some(result) => result // already ran
| None => | None =>
switch rPrevResult { switch rPrevResult {
| Error(error) => { | Error(error) => {
setResult(project, sourceId, Error(error)) setResult(project, sourceId, Error(error))
(Error(error), continuation) Error(error)
} }
| Ok(_prevResult) => { | Ok(_prevResult) => {
doRunWithContinuation(project, sourceId, continuation) doLinkAndRun(project, sourceId)
( getResultOption(project, sourceId)->Belt.Option.getWithDefault(rPrevResult)
getResultOption(project, sourceId)->Belt.Option.getWithDefault(rPrevResult),
getContinuation(project, sourceId),
)
} }
} }
} }
@ -195,17 +234,17 @@ module Private = {
let runAll = (project: t): unit => { let runAll = (project: t): unit => {
let runOrder = Topology.getRunOrder(project) let runOrder = Topology.getRunOrder(project)
let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(project)) let initialState = Ok(InternalExpressionValue.IEvVoid)
let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) => let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) =>
tryRunWithContinuation(project, currId, currState) tryRunWithResult(project, currId, currState)
) )
} }
let run = (project: t, sourceId: string): unit => { let run = (project: t, sourceId: string): unit => {
let runOrder = Topology.getRunOrderFor(project, sourceId) let runOrder = Topology.getRunOrderFor(project, sourceId)
let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(project)) let initialState = Ok(InternalExpressionValue.IEvVoid)
let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) => let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) =>
tryRunWithContinuation(project, currId, currState) tryRunWithResult(project, currId, currState)
) )
} }

View File

@ -173,12 +173,14 @@ function peg$parse(input, options) {
var peg$startRuleFunctions = { start: peg$parsestart }; var peg$startRuleFunctions = { start: peg$parsestart };
var peg$startRuleFunction = peg$parsestart; var peg$startRuleFunction = peg$parsestart;
var peg$c0 = "#include"; var peg$c0 = "#";
var peg$c1 = "'"; var peg$c1 = "#include";
var peg$c2 = "\""; var peg$c2 = "as";
var peg$c3 = "//"; var peg$c3 = "'";
var peg$c4 = "/*"; var peg$c4 = "\"";
var peg$c5 = "*/"; var peg$c5 = "//";
var peg$c6 = "/*";
var peg$c7 = "*/";
var peg$r0 = /^[^']/; var peg$r0 = /^[^']/;
var peg$r1 = /^[^"]/; var peg$r1 = /^[^"]/;
@ -186,29 +188,40 @@ function peg$parse(input, options) {
var peg$r3 = /^[ \t]/; var peg$r3 = /^[ \t]/;
var peg$r4 = /^[\n\r]/; var peg$r4 = /^[\n\r]/;
var peg$r5 = /^[^\r\n]/; var peg$r5 = /^[^\r\n]/;
var peg$r6 = /^[_a-z]/;
var peg$r7 = /^[_a-z0-9]/i;
var peg$e0 = peg$literalExpectation("#include", false); var peg$e0 = peg$literalExpectation("#", false);
var peg$e1 = peg$otherExpectation("string"); var peg$e1 = peg$literalExpectation("#include", false);
var peg$e2 = peg$literalExpectation("'", false); var peg$e2 = peg$literalExpectation("as", false);
var peg$e3 = peg$classExpectation(["'"], true, false); var peg$e3 = peg$otherExpectation("string");
var peg$e4 = peg$literalExpectation("\"", false); var peg$e4 = peg$literalExpectation("'", false);
var peg$e5 = peg$classExpectation(["\""], true, false); var peg$e5 = peg$classExpectation(["'"], true, false);
var peg$e6 = peg$literalExpectation("//", false); var peg$e6 = peg$literalExpectation("\"", false);
var peg$e7 = peg$literalExpectation("/*", false); var peg$e7 = peg$classExpectation(["\""], true, false);
var peg$e8 = peg$classExpectation(["*"], true, false); var peg$e8 = peg$otherExpectation("comment");
var peg$e9 = peg$literalExpectation("*/", false); var peg$e9 = peg$literalExpectation("//", false);
var peg$e10 = peg$otherExpectation("white space"); var peg$e10 = peg$literalExpectation("/*", false);
var peg$e11 = peg$classExpectation([" ", "\t"], false, false); var peg$e11 = peg$classExpectation(["*"], true, false);
var peg$e12 = peg$otherExpectation("newline"); var peg$e12 = peg$literalExpectation("*/", false);
var peg$e13 = peg$classExpectation(["\n", "\r"], false, false); var peg$e13 = peg$otherExpectation("white space");
var peg$e14 = peg$classExpectation(["\r", "\n"], true, false); var peg$e14 = peg$classExpectation([" ", "\t"], false, false);
var peg$e15 = peg$otherExpectation("newline");
var peg$e16 = peg$classExpectation(["\n", "\r"], false, false);
var peg$e17 = peg$otherExpectation("code");
var peg$e18 = peg$classExpectation(["\r", "\n"], true, false);
var peg$e19 = peg$otherExpectation("identifier");
var peg$e20 = peg$classExpectation(["_", ["a", "z"]], false, false);
var peg$e21 = peg$classExpectation(["_", ["a", "z"], ["0", "9"]], false, true);
var peg$f0 = function(head, tail) {return [head, ...tail].filter( e => e != '');}; var peg$f0 = function(head, tail) {return [head, ...tail].filter( e => e != '');};
var peg$f1 = function() {return [];}; var peg$f1 = function() {return [];};
var peg$f2 = function(characters) {return characters.join('');}; var peg$f2 = function(file, variable) {return [!variable ? '' : variable, file]};
var peg$f3 = function(characters) {return characters.join('');}; var peg$f3 = function(characters) {return characters.join('');};
var peg$f4 = function() { return '';}; var peg$f4 = function(characters) {return characters.join('');};
var peg$f5 = function() { return '';}; var peg$f5 = function() { return '';};
var peg$f6 = function() { return '';};
var peg$f7 = function() {return text();};
var peg$currPos = 0; var peg$currPos = 0;
var peg$savedPos = 0; var peg$savedPos = 0;
var peg$posDetailsCache = [{ line: 1, column: 1 }]; var peg$posDetailsCache = [{ line: 1, column: 1 }];
@ -369,7 +382,7 @@ function peg$parse(input, options) {
function peg$parsestart() { function peg$parsestart() {
var s0, s1, s2, s3, s4; var s0, s1, s2, s3, s4;
var key = peg$currPos * 10 + 0; var key = peg$currPos * 12 + 0;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -426,7 +439,7 @@ function peg$parse(input, options) {
function peg$parseincludes() { function peg$parseincludes() {
var s0, s1, s2, s3, s4, s5; var s0, s1, s2, s3, s4, s5;
var key = peg$currPos * 10 + 1; var key = peg$currPos * 12 + 1;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -436,7 +449,7 @@ function peg$parse(input, options) {
} }
s0 = peg$currPos; s0 = peg$currPos;
s1 = peg$parseincludeStatement(); s1 = peg$parsedependencyStatement();
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = []; s2 = [];
s3 = peg$currPos; s3 = peg$currPos;
@ -451,7 +464,7 @@ function peg$parse(input, options) {
s4 = peg$FAILED; s4 = peg$FAILED;
} }
if (s4 !== peg$FAILED) { if (s4 !== peg$FAILED) {
s5 = peg$parseincludeStatement(); s5 = peg$parsedependencyStatement();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
s3 = s5; s3 = s5;
} else { } else {
@ -476,7 +489,7 @@ function peg$parse(input, options) {
s4 = peg$FAILED; s4 = peg$FAILED;
} }
if (s4 !== peg$FAILED) { if (s4 !== peg$FAILED) {
s5 = peg$parseincludeStatement(); s5 = peg$parsedependencyStatement();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
s3 = s5; s3 = s5;
} else { } else {
@ -496,9 +509,26 @@ function peg$parse(input, options) {
} }
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
s0 = peg$currPos; s0 = peg$currPos;
s1 = peg$parseignore(); s1 = peg$currPos;
peg$silentFails++;
if (input.charCodeAt(peg$currPos) === 35) {
s2 = peg$c0;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e0); }
}
peg$silentFails--;
if (s2 === peg$FAILED) {
s1 = undefined;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s1 = peg$f1(); s1 = peg$f1();
}
s0 = s1; s0 = s1;
} }
@ -507,10 +537,35 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parseincludeStatement() { function peg$parsedependencyStatement() {
var s0, s1, s2, s3, s4, s5, s6; var s0;
var key = peg$currPos * 10 + 2; var key = peg$currPos * 12 + 2;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
s0 = peg$parseincludeStatement();
if (s0 === peg$FAILED) {
s0 = peg$parsecomment();
if (s0 === peg$FAILED) {
s0 = peg$parsedelimitedComment();
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parseincludeStatement() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
var key = peg$currPos * 12 + 3;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -526,29 +581,99 @@ function peg$parse(input, options) {
s1.push(s2); s1.push(s2);
s2 = peg$parse_(); s2 = peg$parse_();
} }
if (input.substr(peg$currPos, 8) === peg$c0) { if (input.substr(peg$currPos, 8) === peg$c1) {
s2 = peg$c0; s2 = peg$c1;
peg$currPos += 8; peg$currPos += 8;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e0); } if (peg$silentFails === 0) { peg$fail(peg$e1); }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = []; s3 = [];
s4 = peg$parse_(); s4 = peg$parse_();
if (s4 !== peg$FAILED) {
while (s4 !== peg$FAILED) { while (s4 !== peg$FAILED) {
s3.push(s4); s3.push(s4);
s4 = peg$parse_(); s4 = peg$parse_();
} }
} else {
s3 = peg$FAILED;
}
if (s3 !== peg$FAILED) {
s4 = peg$parsestring(); s4 = peg$parsestring();
if (s4 !== peg$FAILED) { if (s4 !== peg$FAILED) {
s5 = []; s5 = peg$currPos;
s6 = peg$parse_(); s6 = [];
while (s6 !== peg$FAILED) { s7 = peg$parse_();
s5.push(s6); if (s7 !== peg$FAILED) {
s6 = peg$parse_(); while (s7 !== peg$FAILED) {
s6.push(s7);
s7 = peg$parse_();
} }
s0 = s4; } else {
s6 = peg$FAILED;
}
if (s6 !== peg$FAILED) {
if (input.substr(peg$currPos, 2) === peg$c2) {
s7 = peg$c2;
peg$currPos += 2;
} else {
s7 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e2); }
}
if (s7 !== peg$FAILED) {
s8 = [];
s9 = peg$parse_();
if (s9 !== peg$FAILED) {
while (s9 !== peg$FAILED) {
s8.push(s9);
s9 = peg$parse_();
}
} else {
s8 = peg$FAILED;
}
if (s8 !== peg$FAILED) {
s9 = peg$parseidentifier();
if (s9 !== peg$FAILED) {
s5 = s9;
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
} else {
peg$currPos = s5;
s5 = peg$FAILED;
}
if (s5 === peg$FAILED) {
s5 = null;
}
s6 = [];
s7 = peg$parse_();
while (s7 !== peg$FAILED) {
s6.push(s7);
s7 = peg$parse_();
}
s7 = peg$currPos;
peg$silentFails++;
s8 = peg$parsenewLine();
peg$silentFails--;
if (s8 !== peg$FAILED) {
peg$currPos = s7;
s7 = undefined;
} else {
s7 = peg$FAILED;
}
if (s7 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f2(s4, s5);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -557,11 +682,13 @@ function peg$parse(input, options) {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
} }
if (s0 === peg$FAILED) { } else {
s0 = peg$parsecomment(); peg$currPos = s0;
if (s0 === peg$FAILED) { s0 = peg$FAILED;
s0 = peg$parsedelimitedComment();
} }
} else {
peg$currPos = s0;
s0 = peg$FAILED;
} }
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -572,7 +699,7 @@ function peg$parse(input, options) {
function peg$parsestring() { function peg$parsestring() {
var s0, s1, s2, s3, s4; var s0, s1, s2, s3, s4;
var key = peg$currPos * 10 + 3; var key = peg$currPos * 12 + 4;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -585,58 +712,7 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
s1 = peg$currPos; s1 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 39) { if (input.charCodeAt(peg$currPos) === 39) {
s2 = peg$c1; s2 = peg$c3;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e2); }
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e3); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e3); }
}
}
if (input.charCodeAt(peg$currPos) === 39) {
s4 = peg$c1;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e2); }
}
if (s4 !== peg$FAILED) {
s1 = s3;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$f2(s1);
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
s2 = peg$c2;
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
@ -644,7 +720,7 @@ function peg$parse(input, options) {
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = []; s3 = [];
if (peg$r1.test(input.charAt(peg$currPos))) { if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos); s4 = input.charAt(peg$currPos);
peg$currPos++; peg$currPos++;
} else { } else {
@ -653,7 +729,7 @@ function peg$parse(input, options) {
} }
while (s4 !== peg$FAILED) { while (s4 !== peg$FAILED) {
s3.push(s4); s3.push(s4);
if (peg$r1.test(input.charAt(peg$currPos))) { if (peg$r0.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos); s4 = input.charAt(peg$currPos);
peg$currPos++; peg$currPos++;
} else { } else {
@ -661,8 +737,8 @@ function peg$parse(input, options) {
if (peg$silentFails === 0) { peg$fail(peg$e5); } if (peg$silentFails === 0) { peg$fail(peg$e5); }
} }
} }
if (input.charCodeAt(peg$currPos) === 34) { if (input.charCodeAt(peg$currPos) === 39) {
s4 = peg$c2; s4 = peg$c3;
peg$currPos++; peg$currPos++;
} else { } else {
s4 = peg$FAILED; s4 = peg$FAILED;
@ -683,11 +759,62 @@ function peg$parse(input, options) {
s1 = peg$f3(s1); s1 = peg$f3(s1);
} }
s0 = s1; s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
s2 = peg$c4;
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$r1.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$r1.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
}
}
if (input.charCodeAt(peg$currPos) === 34) {
s4 = peg$c4;
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
}
if (s4 !== peg$FAILED) {
s1 = s3;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$f4(s1);
}
s0 = s1;
} }
peg$silentFails--; peg$silentFails--;
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e1); } if (peg$silentFails === 0) { peg$fail(peg$e3); }
} }
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -698,7 +825,7 @@ function peg$parse(input, options) {
function peg$parseignore() { function peg$parseignore() {
var s0, s1; var s0, s1;
var key = peg$currPos * 10 + 4; var key = peg$currPos * 12 + 5;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -732,9 +859,9 @@ function peg$parse(input, options) {
} }
function peg$parsecomment() { function peg$parsecomment() {
var s0, s1, s2, s3; var s0, s1, s2, s3, s4;
var key = peg$currPos * 10 + 5; var key = peg$currPos * 12 + 6;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -743,79 +870,32 @@ function peg$parse(input, options) {
return cached.result; return cached.result;
} }
peg$silentFails++;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c3) {
s1 = peg$c3;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
}
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseany();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseany();
}
peg$savedPos = s0;
s0 = peg$f4();
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parsedelimitedComment() {
var s0, s1, s2, s3;
var key = peg$currPos * 10 + 6;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c4) {
s1 = peg$c4;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
}
if (input.substr(peg$currPos, 2) === peg$c5) { if (input.substr(peg$currPos, 2) === peg$c5) {
s3 = peg$c5; s1 = peg$c5;
peg$currPos += 2; peg$currPos += 2;
} else { } else {
s3 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e9); } if (peg$silentFails === 0) { peg$fail(peg$e9); }
} }
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseany();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseany();
}
s3 = peg$currPos;
peg$silentFails++;
s4 = peg$parsenewLine();
peg$silentFails--;
if (s4 !== peg$FAILED) {
peg$currPos = s3;
s3 = undefined;
} else {
s3 = peg$FAILED;
}
if (s3 !== peg$FAILED) { if (s3 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f5(); s0 = peg$f5();
@ -827,6 +907,80 @@ function peg$parse(input, options) {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
} }
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parsedelimitedComment() {
var s0, s1, s2, s3;
var key = peg$currPos * 12 + 7;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
peg$silentFails++;
s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c6) {
s1 = peg$c6;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e10); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$r2.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); }
}
}
if (input.substr(peg$currPos, 2) === peg$c7) {
s3 = peg$c7;
peg$currPos += 2;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e12); }
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f6();
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -836,7 +990,7 @@ function peg$parse(input, options) {
function peg$parse_() { function peg$parse_() {
var s0, s1; var s0, s1;
var key = peg$currPos * 10 + 7; var key = peg$currPos * 12 + 8;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -851,12 +1005,12 @@ function peg$parse(input, options) {
peg$currPos++; peg$currPos++;
} else { } else {
s0 = peg$FAILED; s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); } if (peg$silentFails === 0) { peg$fail(peg$e14); }
} }
peg$silentFails--; peg$silentFails--;
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e10); } if (peg$silentFails === 0) { peg$fail(peg$e13); }
} }
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -867,7 +1021,7 @@ function peg$parse(input, options) {
function peg$parsenewLine() { function peg$parsenewLine() {
var s0, s1; var s0, s1;
var key = peg$currPos * 10 + 8; var key = peg$currPos * 12 + 9;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -882,12 +1036,12 @@ function peg$parse(input, options) {
peg$currPos++; peg$currPos++;
} else { } else {
s0 = peg$FAILED; s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e13); } if (peg$silentFails === 0) { peg$fail(peg$e16); }
} }
peg$silentFails--; peg$silentFails--;
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e12); } if (peg$silentFails === 0) { peg$fail(peg$e15); }
} }
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -896,9 +1050,9 @@ function peg$parse(input, options) {
} }
function peg$parseany() { function peg$parseany() {
var s0; var s0, s1;
var key = peg$currPos * 10 + 9; var key = peg$currPos * 12 + 10;
var cached = peg$resultsCache[key]; var cached = peg$resultsCache[key];
if (cached) { if (cached) {
@ -907,12 +1061,96 @@ function peg$parse(input, options) {
return cached.result; return cached.result;
} }
peg$silentFails++;
if (peg$r5.test(input.charAt(peg$currPos))) { if (peg$r5.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos); s0 = input.charAt(peg$currPos);
peg$currPos++; peg$currPos++;
} else { } else {
s0 = peg$FAILED; s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e14); } if (peg$silentFails === 0) { peg$fail(peg$e18); }
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); }
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
return s0;
}
function peg$parseidentifier() {
var s0, s1, s2, s3, s4;
var key = peg$currPos * 12 + 11;
var cached = peg$resultsCache[key];
if (cached) {
peg$currPos = cached.nextPos;
return cached.result;
}
peg$silentFails++;
s0 = peg$currPos;
s1 = peg$currPos;
s2 = [];
if (peg$r6.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); }
}
if (s3 !== peg$FAILED) {
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$r6.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); }
}
}
} else {
s2 = peg$FAILED;
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$r7.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e21); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$r7.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e21); }
}
}
s2 = [s2, s3];
s1 = s2;
} else {
peg$currPos = s1;
s1 = peg$FAILED;
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$f7();
}
s0 = s1;
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e19); }
} }
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };

View File

@ -1,33 +1,37 @@
// Includes are at the start of the file, before any other code. // Includes are at the start of the file, before any other code.
// There might be some comments before or between the includes. // There might be some comments before or between the includes.
// #include "string" // #include "string"
// #include "string2" // #include "string2" as aVariable
start start
= (newLine/_/comment/delimitedComment)* @includes newLine* ignore = (newLine/_/comment/delimitedComment)* @includes newLine* ignore
includes includes
= head:includeStatement tail:(newLine+ @includeStatement)* = head:dependencyStatement tail:(newLine+ @dependencyStatement)*
{return [head, ...tail].filter( e => e != '');} {return [head, ...tail].filter( e => e != '');}
/ ignore / ! '#'
{return [];} {return [];}
includeStatement dependencyStatement
= _* '#include' _* @string _* = includeStatement
/ comment / comment
/ delimitedComment / delimitedComment
includeStatement
= _* '#include' _+ file:string variable:(_+ 'as' _+ @identifier)? _* & newLine
{return [!variable ? '' : variable, file]}
string 'string' string 'string'
= characters:("'" @([^'])* "'") {return characters.join('');} = characters:("'" @([^'])* "'") {return characters.join('');}
/ characters:('"' @([^"])* '"') {return characters.join('');} / characters:('"' @([^"])* '"') {return characters.join('');}
ignore = (any / newLine / _)* ignore = (any / newLine / _)*
comment comment 'comment'
= '//'any* = '//'any* & newLine
{ return '';} { return '';}
delimitedComment delimitedComment 'comment'
= '/*' ([^*]*) '*/' = '/*' ([^*]*) '*/'
{ return '';} { return '';}
@ -37,4 +41,8 @@ _ "white space"
newLine "newline" newLine "newline"
= [\n\r] = [\n\r]
any = [^\r\n] any 'code'
= [^\r\n]
identifier 'identifier'
= ([_a-z]+[_a-z0-9]i*) {return text();}

View File

@ -1,11 +1,15 @@
@module("./ReducerProject_IncludeParser.js") external parse__: string => array<string> = "parse" @module("./ReducerProject_IncludeParser.js")
external parse__: string => array<array<string>> = "parse"
let parseIncludes = (expr: string): result<array<string>, Reducer_ErrorValue.errorValue> => let parseIncludes = (expr: string): result<
array<(string, string)>,
Reducer_ErrorValue.errorValue,
> =>
try { try {
let answer = parse__(expr) let answer = parse__(expr)
// let logEntry = answer->Js.Array2.joinWith(",") // let logEntry = answer->Js.Array2.joinWith(",")
// `parseIncludes: ${logEntry} for expr: ${expr}`->Js.log // `parseIncludes: ${logEntry} for expr: ${expr}`->Js.log
answer->Ok Belt.Array.map(answer, item => (item[0], item[1]))->Ok
} catch { } catch {
| Js.Exn.Error(obj) => | Js.Exn.Error(obj) =>
RESyntaxError( RESyntaxError(

View File

@ -19,6 +19,8 @@ let emptyItem = T.ProjectItem({
result: None, result: None,
continues: [], continues: [],
includes: []->Ok, includes: []->Ok,
directIncludes: [],
includeAsVariables: [],
}) })
// source -> rawParse -> includes -> expression -> continuation -> result // source -> rawParse -> includes -> expression -> continuation -> result
@ -30,40 +32,59 @@ let getResult = (T.ProjectItem(r)): T.resultType => r.result
let getContinues = (T.ProjectItem(r)): T.continuesType => r.continues let getContinues = (T.ProjectItem(r)): T.continuesType => r.continues
let getIncludes = (T.ProjectItem(r)): T.includesType => r.includes let getIncludes = (T.ProjectItem(r)): T.includesType => r.includes
let getDirectIncludes = (T.ProjectItem(r)): array<string> => r.directIncludes
let getIncludesAsVariables = (T.ProjectItem(r)): T.importAsVariablesType => r.includeAsVariables
let touchSource = (this: t): t => { let touchSource = (this: t): t => {
let T.ProjectItem(r) = emptyItem let T.ProjectItem(r) = emptyItem
T.ProjectItem({ T.ProjectItem({
...r, ...r,
includes: getIncludes(this),
continues: getContinues(this),
source: getSource(this), source: getSource(this),
continues: getContinues(this),
includes: getIncludes(this),
includeAsVariables: getIncludesAsVariables(this),
directIncludes: getDirectIncludes(this),
}) })
} }
let touchRawParse = (this: t): t => { let touchRawParse = (this: t): t => {
let T.ProjectItem(r) = emptyItem let T.ProjectItem(r) = emptyItem
T.ProjectItem({ T.ProjectItem({
...r, ...r,
continues: getContinues(this),
source: getSource(this), source: getSource(this),
rawParse: getRawParse(this), continues: getContinues(this),
includes: getIncludes(this), includes: getIncludes(this),
includeAsVariables: getIncludesAsVariables(this),
directIncludes: getDirectIncludes(this),
rawParse: getRawParse(this),
}) })
} }
let touchExpression = (this: t): t => { let touchExpression = (this: t): t => {
let T.ProjectItem(r) = emptyItem let T.ProjectItem(r) = emptyItem
T.ProjectItem({ T.ProjectItem({
...r, ...r,
continues: getContinues(this),
source: getSource(this), source: getSource(this),
rawParse: getRawParse(this), continues: getContinues(this),
includes: getIncludes(this), includes: getIncludes(this),
includeAsVariables: getIncludesAsVariables(this),
directIncludes: getDirectIncludes(this),
rawParse: getRawParse(this),
expression: getExpression(this), expression: getExpression(this),
}) })
} }
let resetIncludes = (T.ProjectItem(r): t): t => {
T.ProjectItem({
...r,
includes: []->Ok,
includeAsVariables: [],
directIncludes: [],
})
}
let setSource = (T.ProjectItem(r): t, source: T.sourceArgumentType): t => let setSource = (T.ProjectItem(r): t, source: T.sourceArgumentType): t =>
T.ProjectItem({...r, source: source})->touchSource T.ProjectItem({...r, source: source})->resetIncludes->touchSource
let setRawParse = (T.ProjectItem(r): t, rawParse: T.rawParseArgumentType): t => let setRawParse = (T.ProjectItem(r): t, rawParse: T.rawParseArgumentType): t =>
T.ProjectItem({...r, rawParse: Some(rawParse)})->touchRawParse T.ProjectItem({...r, rawParse: Some(rawParse)})->touchRawParse
@ -95,6 +116,10 @@ let clean = (this: t): t => {
let getImmediateDependencies = (this: t): T.includesType => let getImmediateDependencies = (this: t): T.includesType =>
getIncludes(this)->Belt.Result.map(Js.Array2.concat(_, getContinues(this))) getIncludes(this)->Belt.Result.map(Js.Array2.concat(_, getContinues(this)))
let getPastChain = (this: t): array<string> => {
Js.Array2.concat(getDirectIncludes(this), getContinues(this))
}
let setContinues = (T.ProjectItem(r): t, continues: array<string>): t => let setContinues = (T.ProjectItem(r): t, continues: array<string>): t =>
T.ProjectItem({...r, continues: continues})->touchSource T.ProjectItem({...r, continues: continues})->touchSource
let removeContinues = (T.ProjectItem(r): t): t => T.ProjectItem({...r, continues: []})->touchSource let removeContinues = (T.ProjectItem(r): t): t => T.ProjectItem({...r, continues: []})->touchSource
@ -104,10 +129,38 @@ let setIncludes = (T.ProjectItem(r): t, includes: T.includesType): t => T.Projec
includes: includes, includes: includes,
}) })
//TODO: forward parse errors to the user let setImportAsVariables = (
let parseIncludes = (this: t): t => T.ProjectItem(r): t,
setIncludes(this, getSource(this)->ReducerProject_ParseIncludes.parseIncludes) includeAsVariables: T.importAsVariablesType,
): t => T.ProjectItem({...r, includeAsVariables: includeAsVariables})
let setDirectImports = (T.ProjectItem(r): t, directIncludes: array<string>): t => T.ProjectItem({
...r,
directIncludes: directIncludes,
})
let parseIncludes = (this: t): t => {
let T.ProjectItem(r) = this
let rRawImportAsVariables = getSource(this)->ReducerProject_ParseIncludes.parseIncludes
switch rRawImportAsVariables {
| Error(e) => resetIncludes(this)->setIncludes(Error(e))
| Ok(rawImportAsVariables) => {
let includes = rawImportAsVariables->Belt.Array.map(((_variable, file)) => file)->Ok
let includeAsVariables =
rawImportAsVariables->Belt.Array.keep(((variable, _file)) => variable != "")
let directIncludes =
rawImportAsVariables
->Belt.Array.keep(((variable, _file)) => variable == "")
->Belt.Array.map(((_variable, file)) => file)
T.ProjectItem({
...r,
includes: includes,
includeAsVariables: includeAsVariables,
directIncludes: directIncludes,
})
}
}
}
let doRawParse = (this: t): T.rawParseArgumentType => this->getSource->Reducer_Peggy_Parse.parse let doRawParse = (this: t): T.rawParseArgumentType => this->getSource->Reducer_Peggy_Parse.parse
let rawParse = (this: t): t => let rawParse = (this: t): t =>

View File

@ -21,6 +21,7 @@ type continuesArgumentType = array<string>
type continuesType = array<string> type continuesType = array<string>
type includesArgumentType = string type includesArgumentType = string
type includesType = result<array<string>, errorValue> type includesType = result<array<string>, errorValue>
type importAsVariablesType = array<(string, string)>
type projectItem = type projectItem =
| ProjectItem({ | ProjectItem({
@ -30,7 +31,9 @@ type projectItem =
continuation: continuationArgumentType, continuation: continuationArgumentType,
result: resultType, result: resultType,
continues: continuesType, continues: continuesType,
includes: includesType, includes: includesType, //For loader
}) includeAsVariables: importAsVariablesType, //For linker
directIncludes: array<string>,
}) //For linker
type t = projectItem type t = projectItem

View File

@ -19,4 +19,4 @@ let mathBindings: Bindings.t =
->Bindings.fromArray ->Bindings.fromArray
let makeBindings = (previousBindings: Bindings.t): Bindings.t => let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
previousBindings->Bindings.merge(mathBindings) previousBindings->Bindings.mergeFrom(mathBindings)

View File

@ -6,4 +6,4 @@ let bindings: Bindings.t =
]->Bindings.fromArray ]->Bindings.fromArray
let makeBindings = (previousBindings: Bindings.t): Bindings.t => let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
previousBindings->Bindings.merge(bindings) previousBindings->Bindings.mergeFrom(bindings)