Comments (4)
That is expected, yes. We should definitely improve the documentation about this.
It's due to the way repetition operators (e.g. *
, +
) are dealt with in semantic actions. If you have a rule like line = one ("," two)+
, its semantic action takes three arguments:
line(one, commas, twos) {
...
}
Generally this makes writing semantic actions easier (we think) but it's a bit unintuitive to understand at first.
It's difficult to write an operation that will reconstruct the input using only the special actions (_terminal
, _nonterminal
, _iter
). Probably the easiest thing to do would be to add a nonemptyListOf
action to your operation.
from ohm.
By pursuing my investigations, I noticed that the issue appears when there is more than 2 nodes in the iteration:
op(1),op(2)
=> op(1),op(2)
op(1),op(2),op(3)
=> op(1),,op(2)op(3)
It looks like a bug more and more. :)
from ohm.
I've added some debug info to my code and rewrote the grammar to be the simplest possible:
import {grammar, Node} from "ohm-js";
const myGrammar = grammar(`MyGrammar {
Operations = nonemptyListOf<digit, ",">
}`);
const semantics = myGrammar.createSemantics();
semantics.addOperation<any>('passthrough', {
_nonterminal(this: Node, ...nodes) {
console.log('NON TERMINAL', this.sourceString, this.ctorName);
return this.children.map((node) => {
console.log(' CHILD', node.sourceString, node.ctorName);
return node.passthrough();
});
},
_terminal(this: Node) {
console.log(' TERMINAL', this.sourceString, this.ctorName);
return this.sourceString;
},
_iter(this: Node, ...nodes) {
return nodes.map((node) => node.passthrough());
}
})
const val = semantics(myGrammar.match('1,2,3,4')).passthrough();
console.log(JSON.stringify(val));
Here is the formatted debug output:
NON TERMINAL 1,2,3,4 Operations
CHILD 1,2,3,4 nonemptyListOf
NON TERMINAL 1,2,3,4 nonemptyListOf
CHILD 1 digit
NON TERMINAL 1 digit
CHILD 1 _terminal
TERMINAL 1 _terminal
CHILD ,2,3,4 _iter
TERMINAL , _terminal
TERMINAL , _terminal
TERMINAL , _terminal
CHILD ,2,3,4 _iter
NON TERMINAL 2 digit
CHILD 2 _terminal
TERMINAL 2 _terminal
NON TERMINAL 3 digit
CHILD 3 _terminal
TERMINAL 3 _terminal
NON TERMINAL 4 digit
CHILD 4 _terminal
TERMINAL 4 _terminal
What we see here is that the nonemptyListOf
node has 3 children:
- This first one is the
1
digit - The second one is an
_iter
that contains all the comas terminal nodes - The third one is an
_iter
that contains all the other digits
I'm puzzled. Why is the nonemptyListOf
having three children (1
, ,,,
, 234
) instead of seven (1
, ,
, 2
, ,
, 3
, ,
, 4
)?
Is it expected? If so, how can we reconstruct the input by visiting the nodes?
from ohm.
It is not very elegant, there may be a better way, but it works:
semantics.addOperation<any>('passthrough', {
nonemptyListOf(first, separators, rest) {
return [
first.passthrough(),
rest.children.map((node, index) => {
const separatorNode = separators.children[index];
return [
separatorNode.passthrough(),
node.passthrough()
].join('');
}).join('')
].join('');
},
_nonterminal(this: Node, ...nodes) {
return this.children.map((node) => {
return node.passthrough();
}).join('');
},
_terminal(this: Node) {
return this.sourceString;
}
})
1,2,3,4
Thanks a lot for your help. :)
from ohm.
Related Issues (20)
- Type definitions for parameterized rules are inconsistent with behavior HOT 1
- Semantic action '[...]' has the wrong arity: expected 3, got 0 HOT 5
- Semantic actions for comments defined under the space rule HOT 1
- Add ability to type operation parameters & return values HOT 11
- CLI: Line endings in generated files vary across systems and platforms HOT 1
- cli.js is reading incorrect package.json file for version HOT 2
- Typescript example causes error HOT 1
- space with applySyntactic causes failure
- `toAST` incorrectly makes some nodes intermediate nodes HOT 1
- Indentation-sensitive grammar forgets consumed dedents HOT 1
- Syntax error handling? HOT 2
- Indentation-sensitive parsing: dedent not working? HOT 3
- Typescript example fails to compile HOT 1
- "Built-in Rules" section of syntax reference docs are incorrectly formatted
- No indication of stack size exceeded
- Do we get comments from ohm? HOT 6
- Idiomatic way to do partial (prefix) parses
- NPM release behind latest commit
- Partially parse grammar
- Odd behavior: Alternation fails instead of trying second alternative
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ohm.