Skip to content

Commit

Permalink
making API more javascripty (#2)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: This PR removes all submodules, and instead exports everything only from the main index.ts entry point
BREAKING CHANGE: This PR replaces any functions that have multiple optional parameters with an optional options object instead, to avoid needing to pass undefined for unused function arguments
BREAKING CHANGE: This PR renames all constant module functions and exports by adding the word Constant to their names
  • Loading branch information
chanind authored Jan 1, 2024
1 parent 846f2fa commit cc75de2
Show file tree
Hide file tree
Showing 45 changed files with 913 additions and 663 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"functional/immutable-data": "off",
"functional/prefer-immutable-types": "off",
"functional/no-throw-statements": "off",
"functional/no-mixed-types": "off",
"functional/functional-parameters": "off",
"functional/prefer-type-literal": "off",
"no-constant-condition": "off",
Expand Down
55 changes: 36 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,15 @@
[![ci](https://img.shields.io/github/actions/workflow/status/chanind/penman-js/ci.yaml?branch=main)](https://github.com/chanind/penman-js)
[![Npm](https://img.shields.io/npm/v/penman-js)](https://www.npmjs.com/package/penman-js)

Javascript port of [Penman Python library](https://github.com/goodmami/penman) for Abstract Meaning Representation (AMR).
Javascript port of the [Penman Python library](https://github.com/goodmami/penman) for Abstract Meaning Representation (AMR).

Full docs: [https://chanind.github.io/penman-js](https://chanind.github.io/penman-js/)

## About

This library is a manual port of the Penman Python library, with identical method names and import structure. However, as Python and Javascript do have some differences, this port has the following changes:
This library is a manual port of the [Penman Python library](https://github.com/goodmami/penman), with similar method names and import structure. All functionality available in the original library should also be available in this library, with similar usage and semantics. The Python library should still be considered the main project for new features.

- all snake-case function names from the Python library are renamed using camel-case to fit Javascript naming conventions. For example, the function `get_pushed_variable` from Python is renamed to `getPushedVariable` in Javascript.
- Python tuples are replaced with Javascript arrays
- Python dictionaries are replaced with Javascript `Map`
- functions only support positional arguments, since Javascript doesn't support keyword arguments like Python
- All imports use `penman-js` as the base instead of `penman`. For instance, `from penman.graph import Graph` in Python is replaced with `import { Graph } from "penman-js/graph";` in Javascript.

This library is not officially part of the Penman project.
The goal of this project is to bring the power of the Penman Python library's AMR parsing and generation to the browser and Node.js. This project does not provide a CLI interface for manipulating AMR, since the Python library already provides that functionality.

## Installation

Expand All @@ -29,21 +23,44 @@ npm install penman-js

## Basic usage

The most faithful representation of AMR text in the library is the `Tree` class. The `parse` function turns an AMR text string into a `Tree`, and `format` does the reverse, turning a `Tree` back into a string.

```js
import { encode, decode } from 'penman-js';
import { parse, format } from 'penman-js';

const t = penman.parse('(w / want-01 :ARG0 (b / boy) :ARG1 (g / go :ARG0 b))');
const [variable, branches] = t.node;
console.log(variable); // ouput: 'w'
console.log(branches.length); // output: 3
const [role, target] = branches[2];
console.log(role); // output: ':ARG1'
console.log(format(target));
// (g / go
// :ARG0 b)
```

g = decode('(b / bark-01 :ARG0 (d / dog))');
g.triples;
// [('b', ':instance', 'bark-01'), ('b', ':ARG0', 'd'), ('d', ':instance', 'dog')]
g.edges();
// [Edge(source='b', role=':ARG0', target='d')]
Users wanting to interact with graphs might find the `decode` and
`encode` functions a good place to start.

// JS doesn't support keyword parameters, so `undefined` must be passed for optional params
console.log(encode(g, undefined, undefined, 3));
// (b / bark-01
// :ARG0 (d / dog))
```js
import { encode, decode } from 'penman-js';
const g = penman.decode('(w / want-01 :ARG0 (b / boy) :ARG1 (g / go :ARG0 b))');
console.log(g.top);
// 'w'
console.log(g.triples.length);
// 6
console.log(g.instances().map((instance) => instance[2]));
// ['want-01', 'boy', 'go']

console.log(encode(g, { top: 'b' }));
// (b / boy
// :ARG0-of (w / want-01
// :ARG1 (g / go
// :ARG0 b)))
```

See [https://chanind.github.io/penman-js](https://chanind.github.io/penman-js/) for full docs.

## Contributing

Contributions are welcome! If you notice any bugs or have ideas for improvements, please either file an issue or open a pull request.
Expand Down
19 changes: 18 additions & 1 deletion docs/docs/api.codec.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import PENMANCodec, { toc as PENMANCodecToc } from '../generated/classes/lib_cod
import Decode, { toc as decodeToc } from '../generated/functions/lib_codec.decode.mdx';
import Iterdecode, { toc as iterdecodeToc } from '../generated/functions/lib_codec.iterdecode.mdx';
import Encode, { toc as encodeToc } from '../generated/functions/lib_codec.encode.mdx';
import Dump, { toc as dumpToc } from '../generated/functions/lib_codec.dump.mdx';
import Dumps, { toc as dumpsToc } from '../generated/functions/lib_codec.dumps.mdx';
import Load, { toc as loadToc } from '../generated/functions/lib_codec.load.mdx';
import Loads, { toc as loadsToc } from '../generated/functions/lib_codec.loads.mdx';

# codec

Expand All @@ -12,10 +16,23 @@ ___
<Iterdecode />
___
<PENMANCodec />
___
<Dump />
___
<Dumps />
___
<Load />
___
<Loads />


export const toc = [
...encodeToc,
...decodeToc,
...iterdecodeToc,
...PENMANCodecToc
...PENMANCodecToc,
...dumpToc,
...dumpsToc,
...loadToc,
...loadsToc,
];
39 changes: 12 additions & 27 deletions docs/docs/api.constant.mdx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import FLOAT, {toc as FloatToc} from '../generated/variables/lib_constant.FLOAT.mdx'
import INTEGER, {toc as IntegerToc} from '../generated/variables/lib_constant.INTEGER.mdx'
import NULL, {toc as NullToc} from '../generated/variables/lib_constant.NULL.mdx'
import STRING, {toc as StringToc} from '../generated/variables/lib_constant.STRING.mdx'
import SYMBOL, {toc as SymbolToc} from '../generated/variables/lib_constant.SYMBOL.mdx'
import Quote, {toc as QuoteToc} from '../generated/functions/lib_constant.quote.mdx'
import Evaluate, {toc as EvaluateToc} from '../generated/functions/lib_constant.evaluate.mdx'
import Type, {toc as TypeToc} from '../generated/functions/lib_constant.type-1.mdx'
import ConstantTypeEnum, {toc as ConstantTypeEnumToc} from '../generated/enums/lib_constant.ConstantType.mdx'
import QuoteConstant, {toc as QuoteConstantToc} from '../generated/functions/lib_constant.quoteConstant.mdx'
import EvaluateConstant, {toc as EvaluateConstantToc} from '../generated/functions/lib_constant.evaluateConstant.mdx'
import ConstantType, {toc as ConstantTypeToc} from '../generated/functions/lib_constant.constantType-1.mdx'

# constant

Expand All @@ -19,28 +15,17 @@ value, is used when an attribute is missing its target, but aside from
robustness measures it is not a supported datatype.




<Quote />
<QuoteConstant />
___
<Evaluate />
<EvaluateConstant />
___
<Type />
<ConstantType />
___

<FLOAT />
<INTEGER />
<NULL />
<STRING />
<SYMBOL />
<ConstantTypeEnum />

export const toc = [
...QuoteToc,
...EvaluateToc,
...TypeToc,
...FloatToc,
...IntegerToc,
...NullToc,
...StringToc,
...SymbolToc,
...QuoteConstantToc,
...EvaluateConstantToc,
...ConstantTypeToc,
...ConstantTypeEnumToc,
]
8 changes: 4 additions & 4 deletions docs/docs/api.graph.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Graph, { toc as GraphToc } from '../generated/classes/lib_graph.Graph.mdx';
import Triple, { toc as TripleToc } from '../generated/types/lib_graph.Triple.mdx';
import Instance, { toc as InstanceToc } from '../generated/types/lib_graph.Instance.mdx';
import Edge, { toc as EdgeToc } from '../generated/types/lib_graph.Edge.mdx';
import Attribute, { toc as AttributeToc } from '../generated/types/lib_graph.Attribute.mdx';
import Triple, { toc as TripleToc } from '../generated/types/lib_types.Triple.mdx';
import Instance, { toc as InstanceToc } from '../generated/types/lib_types.Instance.mdx';
import Edge, { toc as EdgeToc } from '../generated/types/lib_types.Edge.mdx';
import Attribute, { toc as AttributeToc } from '../generated/types/lib_types.Attribute.mdx';


# graph
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Abstract Meaning Representation (AMR) parser and generator for JavaScript.

This library is a manual port of the [Penman Python library](https://github.com/goodmami/penman), with similar method names and import structure. All functionality available in the original library should also be available in this library, with similar usage and semantics. The Python library should still be considered the main project for new features.

The goal of this project is to bring the power of the Penman Python library's AMR parsing and generation to the browser and Node.js. This project does not provide a CLI interface for manipulating AMR, since the Python library already provides the functionality.
The goal of this project is to bring the power of the Penman Python library's AMR parsing and generation to the browser and Node.js. This project does not provide a CLI interface for manipulating AMR, since the Python library already provides that functionality.

### AMR

Expand Down
3 changes: 1 addition & 2 deletions docs/docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ console.log(g.triples.length);
console.log(g.instances().map((instance) => instance[2]));
// ['want-01', 'boy', 'go']

// JS doesn't support keyword parameters, so `undefined` must be passed for optional params
console.log(encode(g, undefined, undefined, 'b'));
console.log(encode(g, { top: 'b' }));
// (b / boy
// :ARG0-of (w / want-01
// :ARG1 (g / go
Expand Down
8 changes: 0 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@
".": {
"import": "./build/module/index.js",
"require": "./build/main/index.js"
},
"./*": {
"import": "./build/module/*.js",
"require": "./build/main/*.js"
},
"./models/*": {
"import": "./build/module/lib/models/*.js",
"require": "./build/main/lib/models/*.js"
}
},
"scripts": {
Expand Down
1 change: 0 additions & 1 deletion src/codec.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/constant.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/epigraph.ts

This file was deleted.

9 changes: 0 additions & 9 deletions src/exceptions.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/graph.ts

This file was deleted.

90 changes: 84 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,94 @@
export { parse, iterparse, parseTriples } from './lib/_parse';
export { format, formatTriples } from './lib/_format';
export { interpret, configure } from './lib/layout';
export { Tree } from './lib/tree';
export { Graph, Triple } from './lib/graph';
export { parse, iterparse, parseTriples } from './lib/parse';
export { format, formatTriples } from './lib/format';
export {
LayoutMarker,
Push,
Pop,
POP,
interpret,
InterpretOptions,
rearrange,
RearrangeOptions,
configure,
ConfigureOptions,
reconfigure,
ReconfigureOptions,
getPushedVariable,
appearsInverted,
nodeContexts,
} from './lib/layout';
export { Tree, isAtomic, TreeOptions } from './lib/tree';
export {
Graph,
GraphAttributesOptions,
GraphEdgesOptions,
GraphOptions,
} from './lib/graph';
export {
Triple,
Instance,
Edge,
Attribute,
Branch,
Node,
Constant,
Variable,
Role,
} from './lib/types';
export {
PENMANCodec,
CodecEncodeOptions,
CodecFormatOptions,
CodecFormatTriplesOptions,
decode,
DecodeOptions,
dump,
DumpOptions,
dumps,
DumpsOptions,
encode,
EncodeOptions,
iterdecode,
load,
LoadOptions,
loads,
LoadsOptions,
} from './lib/codec';
export { DecodeError, PenmanError } from './lib/exceptions';
export {
canonicalizeRoles,
CanonicalizeRolesOptions,
reifyEdges,
ReifyEdgesOptions,
dereifyEdges,
DereifyEdgesOptions,
reifyAttributes,
indicateBranches,
} from './lib/transform';
export {
AlignmentMarker,
AlignmentMarkerOptions,
Alignment,
RoleAlignment,
alignments,
roleAlignments,
} from './lib/surface';
export { Model, ModelOptions, ModelReifyOptions } from './lib/model';
export { amrModel } from './lib/models/amr';
export { noopModel } from './lib/models/noop';
export {
PenmanError,
ConstantError,
GraphError,
LayoutError,
DecodeError,
SurfaceError,
ModelError,
} from './lib/exceptions';
export { Epidatum } from './lib/epigraph';
export {
ConstantType,
constantType,
evaluateConstant,
quoteConstant,
} from './lib/constant';
export { ArrayKeysMap } from './lib/utils';
13 changes: 0 additions & 13 deletions src/layout.ts

This file was deleted.

7 changes: 5 additions & 2 deletions src/lib/_lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ export class TokenIterator {
this._next = null;
}
this._last = current;
if (current == null) {
throw new Error('Unexpected end of input');
}
return current;
}

Expand Down Expand Up @@ -155,7 +158,7 @@ export class TokenIterator {
}

error(message: string, token?: Token): DecodeError {
let line: string | null = null;
let line: string | undefined;
let lineno: number;
let offset: number;
if (token == null) {
Expand Down Expand Up @@ -226,7 +229,7 @@ const _lex = function* (
`capturing group:\n${regex.source}`,
);
}
const token: Token = [typ, val, i, m.index, line];
const token: Token = [typ, val, i, m.index ?? 0, line];
debug(`${token}`);
yield token;
}
Expand Down
Loading

0 comments on commit cc75de2

Please sign in to comment.