From 59dd45287fbdccee7eb4df3d9c165f670c273f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20H=C3=BCbotter?= Date: Sun, 11 Apr 2021 13:22:20 +0200 Subject: [PATCH] fixes --- common/patterns.ts | 92 +++++++------ common/precedences.ts | 37 ++++++ common/terms.ts | 294 ++++++++++++++++++++++++------------------ common/util.ts | 46 ++++--- tony/corpus/terms.txt | 4 +- tony/grammar.ts | 9 +- tony/index.d.ts | 2 + 7 files changed, 292 insertions(+), 192 deletions(-) diff --git a/common/patterns.ts b/common/patterns.ts index a2159c06..fc9002fc 100644 --- a/common/patterns.ts +++ b/common/patterns.ts @@ -10,76 +10,93 @@ import { export const _pattern = ( $: GrammarSymbols, ) => - choice( - $.wildcard_pattern, - $.binding_pattern, - $._assignable_pattern, - $._literal_pattern, + prec( + 'base', + choice( + $.wildcard_pattern, + $.binding_pattern, + $._assignable_pattern, + $._literal_pattern, + ), ) export const _assignable_pattern = ( $: GrammarSymbols, ) => - choice( - alias($.root_binding_pattern, $.binding_pattern), - $.destructuring_pattern, - $.pattern_group, + prec( + 'base', + choice( + alias($.root_binding_pattern, $.binding_pattern), + $.destructuring_pattern, + $.pattern_group, + ), ) export const destructuring_pattern = ( $: GrammarSymbols, ) => - seq( - optional( - seq( - field( - 'alias', - choice( - alias($.identifier, $.identifier_pattern), - alias($.type, $.type_pattern), + prec( + 'base', + seq( + optional( + seq( + field( + 'alias', + choice( + alias($.identifier, $.identifier_pattern), + alias($.type, $.type_pattern), + ), ), + '@', + ), + ), + field( + 'pattern', + choice( + $.struct_pattern, + $.tuple_pattern, + $.list_pattern, + $.tag_pattern, ), - '@', ), - ), - field( - 'pattern', - choice($.struct_pattern, $.tuple_pattern, $.list_pattern, $.tag_pattern), ), ) export const struct_pattern = ( $: GrammarSymbols, ) => - buildStruct( - $, - 'member', - choice( - $.member_pattern, - alias($.binding_pattern, $.shorthand_member_pattern), + prec( + 'base', + buildStruct( + $, + 'member', + choice( + $.member_pattern, + alias($.binding_pattern, $.shorthand_member_pattern), + ), + true, ), - true, ) export const member_pattern = ( $: GrammarSymbols, -) => buildMember($, $._term, $._pattern) +) => prec('base', buildMember($, $._term, $._pattern)) export const tuple_pattern = ( $: GrammarSymbols, -) => buildTuple($, 'element', $._pattern, true, false) +) => prec('base', buildTuple($, 'element', $._pattern, true, false)) export const list_pattern = ( $: GrammarSymbols, -) => buildList($, 'element', $._pattern, true) +) => prec('base', buildList($, 'element', $._pattern, true)) export const binding_pattern = ( $: GrammarSymbols, -) => buildBindingPattern($, true) +) => prec('base', buildBindingPattern($, true)) export const root_binding_pattern = ( $: GrammarSymbols, -) => choice(buildBindingPattern($, false)) +) => prec('base', choice(buildBindingPattern($, false))) export const wildcard_pattern = () => '_' @@ -87,7 +104,7 @@ export const tag_pattern = ( $: GrammarSymbols, ) => prec( - Prec.Pattern, + 'application', seq( field('name', alias($._identifier_without_operators, $.identifier)), field('pattern', $._pattern), @@ -96,8 +113,9 @@ export const tag_pattern = ( export const _literal_pattern = ( $: GrammarSymbols, -) => choice($.boolean, $.decimal, $.integer, $.raw_string, $.regex) +) => + prec('base', choice($.boolean, $.decimal, $.integer, $.raw_string, $.regex)) export const pattern_group = ( $: GrammarSymbols, -) => seq('(', field('pattern', $._pattern), ')') +) => prec('base', seq('(', field('pattern', $._pattern), ')')) diff --git a/common/precedences.ts b/common/precedences.ts index 4c18f3b6..4deecac9 100644 --- a/common/precedences.ts +++ b/common/precedences.ts @@ -5,6 +5,7 @@ export enum Operator { Difference = 'Difference', Equality = 'Equality', Exponentiation = 'Exponentiation', + Extends = 'Extends', Implication = 'Implication', Mod = 'Mod', Named = 'Named', @@ -59,6 +60,32 @@ export enum Prec { export const precedences = ( $: GrammarSymbols, ) => [ + [ + $.argument, + Operator.Pipeline, + 'access', + 'patternOrTerm', + 'application', + $.infix_application, + Operator.Not, + Operator.Exponentiation, + Operator.Product, + Operator.Sum, + Operator.Mod, + Operator.Order, + Operator.Equality, + Operator.And, + Operator.Or, + Operator.Difference, + Operator.Implication, + Operator.Biconditional, + Operator.Extends, + Operator.Other, + Operator.Named, + $._section_identifier, + 'base', + $.group, + ], // [ // Operator.Access, // Operator.Pipeline, @@ -119,4 +146,14 @@ export const precedences = ( // _term ( ... binding_pattern ) = :: member // [$.tuple_pattern, $.application], + + // { identifier , ... :: struct + [$.struct, $.binding_pattern], + + // _term ? _term ... :: conditional + [$.conditional, $.optional_type], + + // type = _term :: binding_pattern + [$.binding_pattern, $.infix_application], + [$.binding_pattern, $.application], ] diff --git a/common/terms.ts b/common/terms.ts index ac95eefa..2f74ffe7 100644 --- a/common/terms.ts +++ b/common/terms.ts @@ -8,109 +8,122 @@ import { commaSep1, sep1, } from './util' -import { Prec } from './precedences' +import { Operator, Prec } from './precedences' export const _statement = ( $: GrammarSymbols, ) => choice($._term, $.assignment, $.export, $.class, $.instance, $.data) export const _term = ($: GrammarSymbols) => - choice( - $.block, - $.function, - $.application, - $.infix_application, - $._section, - $.access, - $.return, - $.conditional, - $.case, - $.struct, - $.tuple, - $.list, - $.list_comprehension, - $.pure, - $.hole, - $.static_function, - $.static_application, - $.type_hint, - $.function_type, - $.optional_type, - $.keyof_type, - $.map_type, - $.type, - $.identifier, - $._literal, - $.group, + prec( + 'base', + choice( + $.block, + $.function, + $.application, + $.infix_application, + $._section, + $.access, + $.return, + $.conditional, + $.case, + $.struct, + $.tuple, + $.list, + $.list_comprehension, + $.pure, + $.hole, + $.static_function, + $.static_application, + $.type_hint, + $.function_type, + $.optional_type, + $.keyof_type, + $.map_type, + $.type, + $.identifier, + $._literal, + $.group, + ), ) export const block = ($: GrammarSymbols) => - buildBlock($, field('term', choice($._term, $.assignment))) + prec('base', buildBlock($, field('term', choice($._term, $.assignment)))) export const _immediate_block = ( $: GrammarSymbols, -) => choice(seq('then', field('body', $._term)), field('body', $.block)) +) => + prec( + 'base', + choice(seq('then', field('body', $._term)), field('body', $.block)), + ) export const export_ = ($: GrammarSymbols) => - seq('export', field('declaration', $.assignment)) + prec('base', seq('export', field('declaration', $.assignment))) export const assignment = ( $: GrammarSymbols, ) => prec.right( + 'base', seq(field('pattern', $._assignable_pattern), '=', field('value', $._term)), ) export const class_ = ($: GrammarSymbols) => prec.right( + 'base', seq( 'class', field('name', $.type), optional(seq(':', field('constraint', $._term))), buildBlock($, field('member', $.class_member)), - ) + ), ) export const class_member = ( $: GrammarSymbols, ) => - seq( - field('name', alias($.identifier, $.identifier_pattern)), - ':', - field('type', $._term), + prec( + 'base', + seq( + field('name', alias($.identifier, $.identifier_pattern)), + ':', + field('type', $._term), + ), ) export const instance = ( $: GrammarSymbols, ) => - seq( - 'instance', - field('type', $._term), - 'of', - field('class', $.type), - buildBlock($, field('assignment', $.assignment)), + prec( + 'base', + seq( + 'instance', + field('type', $._term), + 'of', + field('class', $.type), + buildBlock($, field('assignment', $.assignment)), + ), ) export const _parameters = ( $: GrammarSymbols, -) => buildTuple($, 'parameter', $._pattern, true, true) +) => prec('base', buildTuple($, 'parameter', $._pattern, true, true)) export const function_ = ( $: GrammarSymbols, -) => - prec.right( - seq($._parameters, '=>', field('body', $._term)), - ) +) => prec.right('base', seq($._parameters, '=>', field('body', $._term))) export const _arguments = ( $: GrammarSymbols, -) => buildTuple($, 'argument', $.argument, true, true) +) => prec('base', buildTuple($, 'argument', $.argument, true, true)) export const application = ( $: GrammarSymbols, ) => prec.left( - Prec.Application, + 'application', + // Prec.Application, seq( field('name', $._term), choice($._arguments, field('argument', $._term)), @@ -119,16 +132,20 @@ export const application = ( export const argument = ( $: GrammarSymbols, -) => prec(Prec.Argument, choice(field('placeholder', '?'), field('value', $._element))) +) => + // prec( + // Prec.Argument, + choice(field('placeholder', '?'), field('value', $._element)) +//) export const infix_application = ( $: GrammarSymbols, ) => prec.left( - Prec.InfixApplication, + // Prec.InfixApplication, choice( prec.left( - Prec.Pipeline, + Operator.Pipeline, seq( field('left', $._term), field('name', alias('&.', $.identifier)), @@ -136,7 +153,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Pipeline, + Operator.Pipeline, seq( field('left', $._term), field('name', alias('.', $.identifier)), @@ -144,7 +161,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Not, + Operator.Not, seq( field('left', $._term), field('name', alias('!', $.identifier)), @@ -152,7 +169,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Exponentiation, + Operator.Exponentiation, seq( field('left', $._term), field('name', alias('^', $.identifier)), @@ -160,7 +177,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Product, + Operator.Product, seq( field('left', $._term), field('name', alias('*', $.identifier)), @@ -168,7 +185,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Product, + Operator.Product, seq( field('left', $._term), field('name', alias('/', $.identifier)), @@ -176,7 +193,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Sum, + Operator.Sum, seq( field('left', $._term), field('name', alias('+', $.identifier)), @@ -184,7 +201,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Sum, + Operator.Sum, seq( field('left', $._term), field('name', alias('-', $.identifier)), @@ -192,7 +209,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Mod, + Operator.Mod, seq( field('left', $._term), field('name', alias('%', $.identifier)), @@ -200,7 +217,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Order, + Operator.Order, seq( field('left', $._term), field('name', alias('<', $.identifier)), @@ -208,7 +225,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Order, + Operator.Order, seq( field('left', $._term), field('name', alias('<=', $.identifier)), @@ -216,7 +233,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Order, + Operator.Order, seq( field('left', $._term), field('name', alias('>', $.identifier)), @@ -224,7 +241,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Order, + Operator.Order, seq( field('left', $._term), field('name', alias('>=', $.identifier)), @@ -232,7 +249,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Equality, + Operator.Equality, seq( field('left', $._term), field('name', alias('==', $.identifier)), @@ -240,7 +257,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Equality, + Operator.Equality, seq( field('left', $._term), field('name', alias('!=', $.identifier)), @@ -248,7 +265,7 @@ export const infix_application = ( ), ), prec.left( - Prec.And, + Operator.And, seq( field('left', $._term), field('name', alias('&&', $.identifier)), @@ -256,7 +273,7 @@ export const infix_application = ( ), ), prec.left( - Prec.And, + Operator.And, seq( field('left', $._term), field('name', alias('&', $.identifier)), @@ -264,7 +281,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Or, + Operator.Or, seq( field('left', $._term), field('name', alias('||', $.identifier)), @@ -272,7 +289,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Or, + Operator.Or, seq( field('left', $._term), field('name', alias('|', $.identifier)), @@ -280,7 +297,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Difference, + Operator.Difference, seq( field('left', $._term), field('name', alias('\\', $.identifier)), @@ -288,7 +305,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Implication, + Operator.Implication, seq( field('left', $._term), field('name', alias('==>', $.identifier)), @@ -296,7 +313,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Biconditional, + Operator.Biconditional, seq( field('left', $._term), field('name', alias('<=>', $.identifier)), @@ -304,7 +321,7 @@ export const infix_application = ( ), ), prec.left( - Prec.Extends, + Operator.Extends, seq( field('left', $._term), field('name', alias('<:', $.identifier)), @@ -312,7 +329,7 @@ export const infix_application = ( ), ), prec.left( - Prec.OperatorInfixApplication, + Operator.Other, seq( field('left', $._term), field('name', alias($._operator, $.identifier)), @@ -320,7 +337,7 @@ export const infix_application = ( ), ), prec.left( - Prec.NamedInfixApplication, + Operator.Named, seq( field('left', $._term), '`', @@ -334,56 +351,63 @@ export const infix_application = ( export const _section = ( $: GrammarSymbols, -) => choice($.left_section, $.right_section) +) => prec('base', choice($.left_section, $.right_section)) export const left_section = ( $: GrammarSymbols, -) => seq('(', field('value', $._term), $._section_identifier, ')') +) => prec('base', seq('(', field('value', $._term), $._section_identifier, ')')) export const right_section = ( $: GrammarSymbols, -) => seq('(', $._section_identifier, field('value', $._term), ')') +) => prec('base', seq('(', $._section_identifier, field('value', $._term), ')')) export const _section_identifier = ( $: GrammarSymbols, ) => - prec( - Prec.SectionIdentifier, - choice( - seq('(', field('name', alias($._operator, $.identifier)), ')'), - seq( - '`', - field('name', alias($._identifier_without_operators, $.identifier)), - '`', - ), + // prec( + // Prec.SectionIdentifier, + choice( + seq('(', field('name', alias($._operator, $.identifier)), ')'), + seq( + '`', + field('name', alias($._identifier_without_operators, $.identifier)), + '`', ), ) +// ) export const list_comprehension = ( $: GrammarSymbols, ) => - seq( - '[', - field('body', $._term), - '|', - commaSep1( - choice(field('generator', $.generator), field('condition', $._term)), + prec( + 'base', + seq( + '[', + field('body', $._term), + '|', + commaSep1( + choice(field('generator', $.generator), field('condition', $._term)), + ), + ']', ), - ']', ) export const generator = ( $: GrammarSymbols, ) => - seq( - field('name', alias($.identifier, $.identifier_pattern)), - 'in', - field('value', $._term), + prec( + 'base', + seq( + field('name', alias($.identifier, $.identifier_pattern)), + 'in', + field('value', $._term), + ), ) export const access = ($: GrammarSymbols) => prec.left( - Prec.Access, + 'access', + // Prec.Access, seq( field('left', $._term), choice( @@ -397,13 +421,14 @@ export const access = ($: GrammarSymbols) => ) export const return_ = ($: GrammarSymbols) => - prec.right(seq('return', field('value', $._term))) + prec.right('base', seq('return', field('value', $._term))) export const conditional = ( $: GrammarSymbols, ) => prec.right( - Prec.Application, + 'application', + // Prec.Application, seq( field('condition', $._term), '?', @@ -414,6 +439,7 @@ export const conditional = ( export const case_ = ($: GrammarSymbols) => prec.right( + 'base', seq( 'case', field('value', $._term), @@ -424,11 +450,15 @@ export const case_ = ($: GrammarSymbols) => ) export const when = ($: GrammarSymbols) => - seq('when', commaSep1(field('pattern', $._pattern)), $._immediate_block) + prec( + 'base', + seq('when', commaSep1(field('pattern', $._pattern)), $._immediate_block), + ) export const struct = ($: GrammarSymbols) => prec( - Prec.Term, + 'patternOrTerm', + // Prec.Term, buildStruct( $, 'member', @@ -438,31 +468,35 @@ export const struct = ($: GrammarSymbols) => ) export const member = ($: GrammarSymbols) => - buildMember($, $._term, $._term) + prec('base', buildMember($, $._term, $._term)) export const tuple = ($: GrammarSymbols) => - buildTuple($, 'element', $._element, false, false) + prec('base', buildTuple($, 'element', $._element, false, false)) export const list = ($: GrammarSymbols) => - buildList($, 'element', $._element, false) + prec('base', buildList($, 'element', $._element, false)) export const _element = ( $: GrammarSymbols, -) => choice($._term, $.spread) +) => prec('base', choice($._term, $.spread)) export const spread = ($: GrammarSymbols) => - seq('...', field('value', $._term)) + prec('base', seq('...', field('value', $._term))) export const pure = ($: GrammarSymbols) => - prec.right(seq('pure', field('value', $._term))) + prec('base', prec.right(seq('pure', field('value', $._term)))) export const hole = ($: GrammarSymbols) => - seq('?', field('name', alias($.identifier, $.identifier_pattern))) + prec( + 'base', + seq('?', field('name', alias($.identifier, $.identifier_pattern))), + ) export const static_function = ( $: GrammarSymbols, ) => prec.right( + 'base', seq( '<', commaSep1(field('parameter', $._pattern)), @@ -475,7 +509,8 @@ export const static_application = ( $: GrammarSymbols, ) => prec.left( - Prec.Term, + 'patternOrTerm', + // Prec.Term, seq( field('value', $._term), '<', @@ -486,11 +521,12 @@ export const static_application = ( export const type_hint = ( $: GrammarSymbols, -) => prec.right(seq(field('value', $._term), 'as', field('type', $._term))) +) => + prec.right('base', seq(field('value', $._term), 'as', field('type', $._term))) export const data = ($: GrammarSymbols) => prec.right( - Prec.Or, + Operator.Or, seq( 'data', field('name', $.type), @@ -502,7 +538,7 @@ export const data = ($: GrammarSymbols) => export const tag = ($: GrammarSymbols) => prec.left( - Prec.Or, + Operator.Or, seq( field( 'name', @@ -516,28 +552,32 @@ export const function_type = ( $: GrammarSymbols, ) => prec.right( - Prec.Access, + 'access', + // Prec.Access, seq(field('from', $._term), '->', field('to', $._term)), ) export const optional_type = ( $: GrammarSymbols, -) => prec.right(seq('?', field('type', $._term))) +) => prec.right('base', seq('?', field('type', $._term))) export const keyof_type = ( $: GrammarSymbols, -) => prec.right(seq('keyof', field('type', $._term))) +) => prec.right('base', seq('keyof', field('type', $._term))) export const map_type = ( $: GrammarSymbols, ) => - seq( - '{', - optional(seq(field('property', alias($.type, $.type_pattern)), 'in')), - field('key', $._term), - '->', - field('value', $._term), - '}', + prec( + 'base', + seq( + '{', + optional(seq(field('property', alias($.type, $.type_pattern)), 'in')), + field('key', $._term), + '->', + field('value', $._term), + '}', + ), ) export const type = () => TYPE @@ -546,7 +586,7 @@ export const _identifier_without_operators = () => IDENTIFIER export const _operator = () => OPERATOR export const identifier = ( $: GrammarSymbols, -) => prec.left(choice($._operator, $._identifier_without_operators)) +) => prec.left('base', choice($._operator, $._identifier_without_operators)) export const group = ($: GrammarSymbols) => - prec(Prec.Group, seq('(', field('term', $._term), ')')) + seq('(', field('term', $._term), ')') diff --git a/common/util.ts b/common/util.ts index 16ebb7f4..3f255ae0 100644 --- a/common/util.ts +++ b/common/util.ts @@ -8,6 +8,10 @@ export const commaSep1 = sep1(',') const commaSep2 = sep2(',') +export const newlineSep1 = ( + $: GrammarSymbols, +) => sep1(($._newline as unknown) as string) + const buildDataStructure = ( $: GrammarSymbols, element: Rule, @@ -39,16 +43,20 @@ export const buildTuple = ( element: Rule, rest: boolean, allowSingle: boolean, -) => choice(seq( - '(', - buildDataStructure( - $, - field(fieldName, element), - rest, - allowSingle ? commaSep1 : commaSep2, - ), - ')', -), '()') +) => + choice( + seq( + '(', + buildDataStructure( + $, + field(fieldName, element), + rest, + allowSingle ? commaSep1 : commaSep2, + ), + ')', + ), + '()', + ) export const buildList = ( $: GrammarSymbols, @@ -100,16 +108,12 @@ export const buildBindingPattern = ( allowDefaults ? optional(seq('=', field('default', $._term))) : seq(), ) -const buildStatements = - ($: GrammarSymbols) => - (rule: Rule) => - seq( - optional($._newline), - sep1($._newline as unknown as string)(rule), - optional($._newline), - ) - export const buildBlock = ( $: GrammarSymbols, - ...rules: Rule[] -) => seq('{', seq(...rules.map(buildStatements($))), '}') + rule: Rule +) => seq('{', newlineSep1($)(rule), '}') + +export const line = ( + $: GrammarSymbols, + rule: Rule, +) => seq(rule, choice($._newline, ';')) diff --git a/tony/corpus/terms.txt b/tony/corpus/terms.txt index fa99a8e1..0be7b739 100644 --- a/tony/corpus/terms.txt +++ b/tony/corpus/terms.txt @@ -919,7 +919,7 @@ list comprehension static function / application ================== -value +value; ((a: T) => a) --- @@ -934,7 +934,7 @@ value parameter: (binding_pattern name: (type_pattern)) value: (function - element: (binding_pattern + parameter: (binding_pattern name: (identifier_pattern) type: (type)) body: (identifier)))) diff --git a/tony/grammar.ts b/tony/grammar.ts index 84d28d97..fbc356b8 100644 --- a/tony/grammar.ts +++ b/tony/grammar.ts @@ -88,6 +88,7 @@ import { import { comment, hash_bang_line } from '../common/miscellaneous' import { Dialect } from '../common/dialects' import { precedences } from '../common/precedences' +import { line } from '../common/util' const dialect = Dialect.Tony @@ -165,11 +166,9 @@ export = grammar({ rules: { program: ($) => seq( - optional(seq(field('hashBangLine', $.hash_bang_line), $._newline)), - repeat( - seq(field('import', choice($.import, $.exported_import)), $._newline), - ), - repeat(seq(field('term', $._statement), $._newline)), + optional(line($, field('hashBangLine', $.hash_bang_line))), + repeat(line($, field('import', choice($.import, $.exported_import)))), + repeat(line($, field('term', $._statement))), ), hash_bang_line, diff --git a/tony/index.d.ts b/tony/index.d.ts index 834f6b87..5d0228f4 100644 --- a/tony/index.d.ts +++ b/tony/index.d.ts @@ -253,6 +253,7 @@ export type UnnamedType = | "..." | "/" | ":" + | ";" | "<" | "=" | "=>" @@ -357,6 +358,7 @@ export type SyntaxNode = | UnnamedNode<"..."> | UnnamedNode<"/"> | UnnamedNode<":"> + | UnnamedNode<";"> | UnnamedNode<"<"> | UnnamedNode<"="> | UnnamedNode<"=>">