Skip to content

Commit

Permalink
Merge pull request #295 from uqbar-project/292-error-poco-claro-cuand…
Browse files Browse the repository at this point in the history
…o-se-omite-el-receptor-de-un-mensaje

Fix #292 Error poco claro cuando se omite el receptor de un mensaje
  • Loading branch information
PalumboN authored Jan 10, 2025
2 parents 8c08698 + ac6adb4 commit 6c2e7a3
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 10 deletions.
37 changes: 33 additions & 4 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { log } from 'console'
import Parsimmon, { alt as alt_parser, any, Index, index, lazy, makeSuccess, newline, notFollowedBy, of, Parser, regex, seq, seqObj, string, whitespace } from 'parsimmon'
import Parsimmon, { alt as alt_parser, any, Index, index, lazy, makeSuccess, newline, notFollowedBy, of, Parser, regex, seq, seqObj, string, succeed, whitespace } from 'parsimmon'

Check warning on line 2 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

'succeed' is defined but never used
import unraw from 'unraw'
import { ASSIGNATION_OPERATORS, INFIX_OPERATORS, KEYWORDS, LIST_MODULE, PREFIX_OPERATORS, SET_MODULE } from './constants'
import { discriminate, hasWhitespace, is, List, mapObject } from './extensions'
Expand All @@ -19,6 +19,7 @@ const ALL_OPERATORS = [
export const MALFORMED_ENTITY = 'malformedEntity'
export const MALFORMED_MEMBER = 'malformedMember'
export const MALFORMED_SENTENCE = 'malformedSentence'
export const MALFORMED_MESSAGE_SEND = 'malformedMessageSend'

export class ParseError implements BaseProblem {
constructor(public code: Name, public sourceMap: SourceMap) { }
Expand Down Expand Up @@ -103,6 +104,11 @@ const spaces = optional(string(' ').many())
const comment = (position: 'start' | 'end' | 'inner') => lazy('comment', () => regex(/\/\*(.|[\r\n])*?\*\/|\/\/.*/)).map(text => new Annotation('comment', { text, position }))
const sameLineComment: Parser<Annotation> = spaces.then(comment('end'))

const withSameLineComment = <T extends Node>(result: T): Parser<T> =>

Check warning on line 107 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
optional(sameLineComment).map(comment => comment
? result.copy({ metadata: result.metadata.concat(comment) })

Check warning on line 109 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Expected indentation of 4 spaces but found 6
: result)

Check warning on line 110 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Expected indentation of 4 spaces but found 6

export const sanitizeWhitespaces = (originalFrom: SourceIndex, originalTo: SourceIndex, input: string): [SourceIndex, SourceIndex] => {
const EOL = input.includes('\r\n') ? '\r\n' : '\n'
const hasLineBreaks = (aString: string) => aString.includes(EOL)
Expand Down Expand Up @@ -227,7 +233,8 @@ export const Body: Parser<BodyNode> = node(BodyNode)(() =>
sentences: alt(
Sentence.skip(__),
comment('inner').wrap(_, _),
sentenceError).many(),
sentenceError
).many(),
}).wrap(key('{'), lastKey('}')).map(recover)
)

Expand Down Expand Up @@ -452,12 +459,35 @@ const prefixMessageChain: Parser<ExpressionNode> = lazy(() =>

const postfixMessageChain: Parser<ExpressionNode> = lazy(() =>
messageChain(
primaryExpression,
postfixMessageChainInitialReceiver,
key('.').then(name),
alt(unamedArguments, Closure.times(1))
)
)

const postfixMessageChainInitialReceiver: Parser<ExpressionNode & { problems?: List<BaseProblem> }> = lazy(() =>

Check warning on line 468 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
alt(
primaryExpression,
obj({
markedMessage: name.mark(),
args: alt(unamedArguments, Closure.times(1)),
}).mark().chain(({
start,
end,
value: {

Check warning on line 477 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
markedMessage: { value: message, start: errorStart, end: errorEnd },

Check warning on line 478 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
args

Check warning on line 479 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed

Check warning on line 479 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Missing trailing comma
},
}) => Parsimmon((input: string, i: number) => makeSuccess(i, new SendNode({
receiver: new LiteralNode({ value: null }),
message,

Check warning on line 483 in src/parser.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
args,
problems: [new ParseError(MALFORMED_MESSAGE_SEND, buildSourceMap(errorStart, errorEnd))],
sourceMap: buildSourceMap(...sanitizeWhitespaces(start, end, input))
}))))
).chain(withSameLineComment)
)

const messageChain = (receiver: Parser<ExpressionNode>, message: Parser<Name>, args: Parser<List<ExpressionNode>>): Parser<ExpressionNode> => lazy(() =>
seq(
index,
Expand Down Expand Up @@ -498,7 +528,6 @@ const primaryExpression: Parser<ExpressionNode> = lazy(() => {
)
})


export const Self: Parser<SelfNode> = node(SelfNode)(() =>
key(KEYWORDS.SELF).result({})
)
Expand Down
86 changes: 80 additions & 6 deletions test/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ describe('Wollok parser', () => {
}))
})

it('comments after malformed sends should be parsed', () => {
'vola() //some comment'
.should.be.parsedBy(parse.Send)
.recoveringFrom(parse.MALFORMED_MESSAGE_SEND, 0, 4)
.into(new Send({
receiver: new Literal({ value: null }),
message: 'vola',
metadata: [new Annotation('comment', { text: '//some comment', position: 'end' })],
}))
})

it('comments after variable should be parsed', () => {
'const a = 1 //some comment'
.should.be.parsedBy(parse.Variable).into(new Variable({
Expand Down Expand Up @@ -2607,7 +2618,7 @@ class c {}`
.and.have.nested.property('receiver').tracedTo(0, 3)
})

it('should parse compound sending messages', () => {
it('should parse chained sending messages', () => {
'a.m().n().o()'.should.be.parsedBy(parser).into(
new Send({
receiver: new Send({
Expand Down Expand Up @@ -2723,16 +2734,79 @@ class c {}`
'a.'.should.not.be.parsedBy(parser)
})

it('should not parse a call to a method without the reference that is calling', () => {
'm(p,q)'.should.not.be.parsedBy(parser)
})

it('should not parse an expression with a "." at the start', () => {
'.m'.should.not.be.parsedBy(parser)
})

})
it('should recover from malformed message send without arguments', () => {
`m()`.should.be.parsedBy(parser)
.recoveringFrom(parse.MALFORMED_MESSAGE_SEND, 0, 1)
.into(new Send({
receiver: new Literal({ value: null }),
message: 'm',
args: [],
}))
})

it('should recover from malformed message send with one argument', () => {
`m(p)`.should.be.parsedBy(parser)
.recoveringFrom(parse.MALFORMED_MESSAGE_SEND, 0, 1)
.into(new Send({
receiver: new Literal({ value: null }),
message: 'm',
args: [ new Reference({ name: 'p' }) ],
}))
})

it('should recover from malformed message send with multiple arguments', () => {
'm(p,q)'.should.be.parsedBy(parser)
.recoveringFrom(parse.MALFORMED_MESSAGE_SEND, 0, 1)
.into(new Send({
receiver: new Literal({ value: null }),
message: 'm',
args: [
new Reference({ name: 'p' }),
new Reference({ name: 'q' })
],
}))
})

it('should parse malformed message sends with a closure as an argument', () => {
'm1 {p => p}'.should.be.parsedBy(parser)
.recoveringFrom(parse.MALFORMED_MESSAGE_SEND, 0, 2)
.into(
new Send({
receiver: new Literal({ value: null }),
message: 'm1',
args: [
Closure({
parameters: [new Parameter({ name: 'p' })],
sentences: [new Return({ value: new Reference({ name: 'p' }) })],
code: '{p => p}',
}),
],
})
)
.and.exist.tracedTo(0,11)
.and.have.nested.property('args.0').tracedTo(3, 11)
.and.also.have.nested.property('args.0.members.0.parameters.0').tracedTo(4, 5)
.and.also.have.nested.property('args.0.members.0.body.sentences.0.value').tracedTo(9, 10)
})

it('should parse chained send with malformed receiver', () => {
`m1().m2()`.should.be.parsedBy(parser)
.into(new Send({
receiver: new Send({
receiver: new Literal({ value: null }),
message: 'm1',
args: [],
}),
message: 'm2',
args: [],
}))
})

})

describe('New', () => {

Expand Down

0 comments on commit 6c2e7a3

Please sign in to comment.