initial parser
This commit is contained in:
commit
d0d6aae1e5
175
.gitignore
vendored
Normal file
175
.gitignore
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
npm-debug.log_
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Caches
|
||||||
|
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
|
||||||
|
pids
|
||||||
|
_.pid
|
||||||
|
_.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
|
||||||
|
.temp
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
18
.prettierrc
Normal file
18
.prettierrc
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"htmlWhitespaceSensitivity": "css",
|
||||||
|
"insertPragma": false,
|
||||||
|
"jsxBracketSameLine": false,
|
||||||
|
"jsxSingleQuote": true,
|
||||||
|
"printWidth": 80,
|
||||||
|
"proseWrap": "always",
|
||||||
|
"quoteProps": "as-needed",
|
||||||
|
"requirePragma": false,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"useTabs": false,
|
||||||
|
"plugins": ["prettier-plugin-pegjs"]
|
||||||
|
}
|
2
README.md
Normal file
2
README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
An interpreter for the CPS intermediate representation as
|
||||||
|
suggested in "Compiling with Continuations" by Appel.
|
18
package.json
Normal file
18
package.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "cps-interpreter",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.8",
|
||||||
|
"peggy": "^4.0.0",
|
||||||
|
"prettier": "^3.2.5",
|
||||||
|
"prettier-plugin-pegjs": "^2.0.2",
|
||||||
|
"ts-pegjs": "^4.2.1"
|
||||||
|
}
|
||||||
|
}
|
11
src/args.ts
Normal file
11
src/args.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const argv = require('minimist')(process.argv.slice(2));
|
||||||
|
|
||||||
|
export type Args = {
|
||||||
|
devMode: boolean;
|
||||||
|
repl: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const args: Args = {
|
||||||
|
repl: argv.repl ?? false,
|
||||||
|
devMode: argv.dev ?? false,
|
||||||
|
};
|
63
src/index.ts
Normal file
63
src/index.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { args, type Args } from '@/args';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { watch } from 'fs/promises';
|
||||||
|
import { generateParser, GRAMMAR_FILE, GENERATED_PARSER } from '@/parser';
|
||||||
|
import {
|
||||||
|
ConsoleTracingLogger,
|
||||||
|
type LogLevel,
|
||||||
|
type TracingLogger,
|
||||||
|
} from '@/utils';
|
||||||
|
import { evaluate } from '@/interpreter';
|
||||||
|
|
||||||
|
const LOG_LEVELS: LogLevel[] = ['info', 'warn', 'error'];
|
||||||
|
|
||||||
|
const devMode = async (logger: TracingLogger) => {
|
||||||
|
logger.info('Watching for changes in parser...');
|
||||||
|
|
||||||
|
const watcher = watch(import.meta.dir, { recursive: true });
|
||||||
|
for await (const event of watcher) {
|
||||||
|
if (event.filename?.endsWith(GRAMMAR_FILE)) {
|
||||||
|
const grammarFile = join(import.meta.dir, event.filename);
|
||||||
|
const outputFile = join(
|
||||||
|
import.meta.dir,
|
||||||
|
event.filename.replace(GRAMMAR_FILE, GENERATED_PARSER),
|
||||||
|
);
|
||||||
|
logger.info(
|
||||||
|
`Generating parser at Location=(${grammarFile}) to Source=(${outputFile})...`,
|
||||||
|
);
|
||||||
|
generateParser(grammarFile, outputFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const doRepl = async (prompt = '~> ') => {
|
||||||
|
process.stdout.write(prompt);
|
||||||
|
|
||||||
|
for await (const line of console) {
|
||||||
|
const result = await evaluate(line);
|
||||||
|
console.log(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
await doRepl(prompt);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const main = async (args: Args) => {
|
||||||
|
if (args.devMode) {
|
||||||
|
LOG_LEVELS.push('debug');
|
||||||
|
}
|
||||||
|
|
||||||
|
const logger = new ConsoleTracingLogger('main', LOG_LEVELS);
|
||||||
|
|
||||||
|
if (args.devMode) {
|
||||||
|
logger.info('Starting in dev mode...');
|
||||||
|
await devMode(logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.repl) {
|
||||||
|
logger.info('Starting REPL...');
|
||||||
|
logger.info('Welcome to the CPS interpreter!');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
main(args);
|
1
src/interpreter/index.ts
Normal file
1
src/interpreter/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const evaluate = async (ast: Program) => {};
|
17
src/parser/generate.ts
Normal file
17
src/parser/generate.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import peggy from 'peggy';
|
||||||
|
const tspegjs: any = require('ts-pegjs');
|
||||||
|
|
||||||
|
export const GRAMMAR_FILE = 'grammar.pegjs';
|
||||||
|
export const GENERATED_PARSER = 'parser.ts';
|
||||||
|
|
||||||
|
export const generateParser = async (file: string, output: string) => {
|
||||||
|
const grammar = await Bun.file(file).text();
|
||||||
|
|
||||||
|
const parserSrc = peggy.generate(grammar, {
|
||||||
|
format: 'commonjs',
|
||||||
|
plugins: [tspegjs],
|
||||||
|
output: 'source',
|
||||||
|
});
|
||||||
|
|
||||||
|
await Bun.write(output, parserSrc);
|
||||||
|
};
|
364
src/parser/grammar.pegjs
Normal file
364
src/parser/grammar.pegjs
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
Program
|
||||||
|
= exprs:(ContinuationExpression / _)* {
|
||||||
|
return exprs.filter(x => !Array.isArray(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
ContinuationExpression
|
||||||
|
= RecordExpression
|
||||||
|
/ SelectExpression
|
||||||
|
/ OffsetExpression
|
||||||
|
/ ApplicationExpression
|
||||||
|
/ FixExpression
|
||||||
|
/ SwitchExpression
|
||||||
|
/ PrimitiveOperationExpression
|
||||||
|
|
||||||
|
SelectExpression
|
||||||
|
= SELECT
|
||||||
|
_?
|
||||||
|
LPAREN
|
||||||
|
_?
|
||||||
|
select:Integer
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
val:Value
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
bind:Identifier
|
||||||
|
_?
|
||||||
|
continuation:ContinuationExpression
|
||||||
|
_?
|
||||||
|
RPAREN { return { select, val, bind, continuation }; }
|
||||||
|
|
||||||
|
OffsetExpression
|
||||||
|
= OFFSET
|
||||||
|
_?
|
||||||
|
LPAREN
|
||||||
|
_?
|
||||||
|
offset:Integer
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
val:Value
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
bind:Identifier
|
||||||
|
_?
|
||||||
|
continuation:ContinuationExpression
|
||||||
|
_?
|
||||||
|
RPAREN { return { offset, val, bind, continuation }; }
|
||||||
|
|
||||||
|
IdentifierList
|
||||||
|
= LBRACKET
|
||||||
|
_?
|
||||||
|
identifiers:(ident:Identifier _? COMMA _?)*
|
||||||
|
_?
|
||||||
|
lastIdent:Identifier?
|
||||||
|
_?
|
||||||
|
RBRACKET {
|
||||||
|
return identifiers.length || lastIdent
|
||||||
|
? [...identifiers.map(x => x.ident), lastIdent]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueList
|
||||||
|
= LBRACKET
|
||||||
|
_?
|
||||||
|
values:(value:Value _? COMMA _?)*
|
||||||
|
_?
|
||||||
|
lastValue:Value?
|
||||||
|
_?
|
||||||
|
RBRACKET {
|
||||||
|
return values.length || lastValue
|
||||||
|
? [...values.map(x => x.value), lastValue]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
SwitchExpression
|
||||||
|
= SWITCH
|
||||||
|
_?
|
||||||
|
LPAREN
|
||||||
|
_?
|
||||||
|
switchIndex:Value
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
continuations:ContinuationList
|
||||||
|
_?
|
||||||
|
RPAREN { return { switchIndex, continuations }; }
|
||||||
|
|
||||||
|
ApplicationExpression
|
||||||
|
= APP _? LPAREN _? fn:Value _? COMMA _? args:ValueList _? RPAREN {
|
||||||
|
return { fn, args };
|
||||||
|
}
|
||||||
|
|
||||||
|
FixBinding
|
||||||
|
= LPAREN
|
||||||
|
_?
|
||||||
|
fn:Identifier
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
args:IdentifierList
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
continuation:ContinuationExpression
|
||||||
|
_?
|
||||||
|
RPAREN
|
||||||
|
|
||||||
|
FixBindingList
|
||||||
|
= LBRACKET
|
||||||
|
_
|
||||||
|
bindings:(binding:FixBinding _? COMMA _?)*
|
||||||
|
_?
|
||||||
|
lastBinding:FixBinding?
|
||||||
|
_?
|
||||||
|
RBRACKET {
|
||||||
|
return bindings.length || lastBinding
|
||||||
|
? [...bindings.map(x => x.binding), lastBinding]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
FixExpression
|
||||||
|
= FIX
|
||||||
|
_?
|
||||||
|
LPAREN
|
||||||
|
_?
|
||||||
|
fixBindings:FixBindingList
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
continuation:ContinuationExpression
|
||||||
|
_?
|
||||||
|
RPAREN { return { fixBindings, continuation }; }
|
||||||
|
|
||||||
|
ContinuationList
|
||||||
|
= LBRACKET
|
||||||
|
_?
|
||||||
|
continuations:(continuation:ContinuationExpression _? COMMA _?)*
|
||||||
|
_?
|
||||||
|
lastContinuation:ContinuationExpression?
|
||||||
|
_?
|
||||||
|
RBRACKET {
|
||||||
|
return lastContinuation || continuations.length
|
||||||
|
? [...continuations.map(x => x.continuation), lastContinuation]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveOperationExpression
|
||||||
|
= PRIMOP
|
||||||
|
_?
|
||||||
|
LPAREN
|
||||||
|
_?
|
||||||
|
opr:PrimitiveOperation
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
operands:ValueList
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
resultBindings:IdentifierList
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
continuations:ContinuationList
|
||||||
|
_?
|
||||||
|
RPAREN { return { opr, operands, resultBindings, continuations }; }
|
||||||
|
|
||||||
|
RecordExpressionTuple
|
||||||
|
= LPAREN
|
||||||
|
_?
|
||||||
|
variable:VarStatement
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
offset:OffsetStatement
|
||||||
|
_?
|
||||||
|
RPAREN { return { variable, offset }; }
|
||||||
|
|
||||||
|
RecordExpressionTupleList
|
||||||
|
= LBRACKET
|
||||||
|
_?
|
||||||
|
records:(record:RecordExpressionTuple _? COMMA _?)*
|
||||||
|
_?
|
||||||
|
lastRecord:RecordExpressionTuple?
|
||||||
|
_?
|
||||||
|
RBRACKET {
|
||||||
|
return records.length || lastRecord
|
||||||
|
? [...records.map(x => x.record), lastRecord]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordExpression
|
||||||
|
= RECORD
|
||||||
|
_?
|
||||||
|
LPAREN
|
||||||
|
_?
|
||||||
|
records:RecordExpressionTupleList
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
address:Literal
|
||||||
|
_?
|
||||||
|
COMMA
|
||||||
|
_?
|
||||||
|
body:ContinuationExpression
|
||||||
|
_?
|
||||||
|
RPAREN {
|
||||||
|
return {
|
||||||
|
records,
|
||||||
|
address,
|
||||||
|
body,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Value
|
||||||
|
= VarStatement
|
||||||
|
/ LabelStatement
|
||||||
|
/ IntStatement
|
||||||
|
/ RealStatement
|
||||||
|
/ StringStatement
|
||||||
|
|
||||||
|
VarStatement = VAR _ ident:Identifier { return ident; }
|
||||||
|
|
||||||
|
LabelStatement = LABEL _ ident:Identifier { return ident; }
|
||||||
|
|
||||||
|
IntStatement = INT _ int:Integer { return int; }
|
||||||
|
|
||||||
|
RealStatement = REAL _ real:Real { return real; }
|
||||||
|
|
||||||
|
StringStatement = STRING _ string:QuotedString { return string; }
|
||||||
|
|
||||||
|
AccessStatement
|
||||||
|
= OffsetStatement
|
||||||
|
/ SelectStatement
|
||||||
|
|
||||||
|
OffsetStatement = OFFP _ offset:Integer { return offset; }
|
||||||
|
|
||||||
|
SelectStatement = SELP _ offset:Integer { return offset; }
|
||||||
|
|
||||||
|
Identifier
|
||||||
|
= name:([A-Za-z] (LETTER / DIGIT / SAFE_SYMBOL)*) {
|
||||||
|
return { name: name[0] + name[1].join('') };
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveOperation
|
||||||
|
= ArithmeticOperation
|
||||||
|
/ ComparisonOperation
|
||||||
|
/ BitOperation
|
||||||
|
/ StoreOperation
|
||||||
|
|
||||||
|
StoreOperation
|
||||||
|
= STORE
|
||||||
|
/ UPDATE
|
||||||
|
/ MAKEREF
|
||||||
|
/ MAKEREFUNBOXED
|
||||||
|
/ UNBOXED_UPDATE
|
||||||
|
/ BOXED
|
||||||
|
/ SUBSCRIPT
|
||||||
|
|
||||||
|
ArithmeticOperation
|
||||||
|
= "+"
|
||||||
|
/ "-"
|
||||||
|
/ "/"
|
||||||
|
/ "*"
|
||||||
|
/ "**"
|
||||||
|
|
||||||
|
BitOperation
|
||||||
|
= ">>"
|
||||||
|
/ "<<"
|
||||||
|
/ "~"
|
||||||
|
/ "^"
|
||||||
|
|
||||||
|
ComparisonOperation
|
||||||
|
= "=="
|
||||||
|
/ "<="
|
||||||
|
/ ">="
|
||||||
|
/ "!="
|
||||||
|
/ "!"
|
||||||
|
/ ">"
|
||||||
|
/ "<"
|
||||||
|
|
||||||
|
Integer = digits:[0-9]+ !"." { return parseInt(digits.join(''), 10); }
|
||||||
|
|
||||||
|
QuotedString
|
||||||
|
= "'" content:[^']* "'" { return content.join(''); }
|
||||||
|
/ "\"" content:[^"]* "\"" { return content.join(''); }
|
||||||
|
|
||||||
|
Real
|
||||||
|
= value:("-"? [0-9]+ "." [0-9]+) {
|
||||||
|
return parseFloat(
|
||||||
|
value.map(x => (Array.isArray(x) ? x.join('') : x)).join(''),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Literal
|
||||||
|
= Real
|
||||||
|
/ QuotedString
|
||||||
|
/ Integer
|
||||||
|
|
||||||
|
OFFSET = "OFFSET"
|
||||||
|
|
||||||
|
OFFP = "OFFp"
|
||||||
|
|
||||||
|
SELP = "SELp"
|
||||||
|
|
||||||
|
VAR = "VAR"
|
||||||
|
|
||||||
|
INT = "INT"
|
||||||
|
|
||||||
|
REAL = "REAL"
|
||||||
|
|
||||||
|
STRING = "STRING"
|
||||||
|
|
||||||
|
APP = "APP"
|
||||||
|
|
||||||
|
RECORD = "RECORD"
|
||||||
|
|
||||||
|
SELECT = "SELECT"
|
||||||
|
|
||||||
|
FIX = "FIX"
|
||||||
|
|
||||||
|
SWITCH = "SWITCH"
|
||||||
|
|
||||||
|
PRIMOP = "PRIMOP"
|
||||||
|
|
||||||
|
LABEL = "LABEL"
|
||||||
|
|
||||||
|
STORE = "store"
|
||||||
|
|
||||||
|
UPDATE = "update"
|
||||||
|
|
||||||
|
MAKEREF = "makeref"
|
||||||
|
|
||||||
|
MAKEREFUNBOXED = "makerefunboxed"
|
||||||
|
|
||||||
|
UNBOXED_UPDATE = "unboxedupdate"
|
||||||
|
|
||||||
|
SUBSCRIPT = "subscript"
|
||||||
|
|
||||||
|
BOXED = "boxed"
|
||||||
|
|
||||||
|
LETTER = [A-Za-z]
|
||||||
|
|
||||||
|
SAFE_SYMBOL = "_"
|
||||||
|
|
||||||
|
DIGIT = [0-9]
|
||||||
|
|
||||||
|
LBRACKET = "["
|
||||||
|
|
||||||
|
RBRACKET = "]"
|
||||||
|
|
||||||
|
COMMA = ","
|
||||||
|
|
||||||
|
EQUALS = "="
|
||||||
|
|
||||||
|
LPAREN = "("
|
||||||
|
|
||||||
|
RPAREN = ")"
|
||||||
|
|
||||||
|
_ = (" " / "\n" / "\t" / "\r\n")+
|
6
src/parser/index.ts
Normal file
6
src/parser/index.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export * from './generate';
|
||||||
|
export * from './parser';
|
||||||
|
import * as peggy from './parser';
|
||||||
|
|
||||||
|
export const peggyParse = (source: string): peggy.FunctionDefinition[] =>
|
||||||
|
peggy.parse(source);
|
5235
src/parser/parser.ts
Normal file
5235
src/parser/parser.ts
Normal file
File diff suppressed because it is too large
Load Diff
1
src/utils/exception.ts
Normal file
1
src/utils/exception.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export class NotImplementedException extends Error {}
|
2
src/utils/index.ts
Normal file
2
src/utils/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './logger';
|
||||||
|
export * from './exception';
|
51
src/utils/logger.ts
Normal file
51
src/utils/logger.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
export interface TracingLogger {
|
||||||
|
info(log: string): void;
|
||||||
|
warn(log: string): void;
|
||||||
|
error(log: string): void;
|
||||||
|
debug(log: string): void;
|
||||||
|
|
||||||
|
createChild(prefix: string): TracingLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
||||||
|
|
||||||
|
export class ConsoleTracingLogger implements TracingLogger {
|
||||||
|
protected prefix: string;
|
||||||
|
private levels: LogLevel[];
|
||||||
|
|
||||||
|
constructor(prefix: string, levels: LogLevel[] = ['warn', 'error']) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.levels = levels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private makePrefix(level: LogLevel): string {
|
||||||
|
return `[${new Date().toISOString()}] ${level} (${this.prefix}) > `;
|
||||||
|
}
|
||||||
|
|
||||||
|
public info(log: string) {
|
||||||
|
if (this.levels.includes('info'))
|
||||||
|
console.log(this.makePrefix('info') + log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public warn(log: string) {
|
||||||
|
if (this.levels.includes('warn'))
|
||||||
|
console.warn(this.makePrefix('warn') + log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public error(log: string) {
|
||||||
|
if (this.levels.includes('error'))
|
||||||
|
console.error(this.makePrefix('error') + log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public debug(log: string) {
|
||||||
|
if (this.levels.includes('debug'))
|
||||||
|
console.debug(this.makePrefix('debug') + log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createChild(prefix: string, levels?: LogLevel[]) {
|
||||||
|
return new ConsoleTracingLogger(
|
||||||
|
`${this.prefix} -> ${prefix}`,
|
||||||
|
levels ?? this.levels,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
27
tsconfig.json
Normal file
27
tsconfig.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["ESNext"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"],
|
||||||
|
"@t/*": ["./test/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user