diff --git a/common/dialects.ts b/common/dialects.ts new file mode 100644 index 00000000..d47d18d3 --- /dev/null +++ b/common/dialects.ts @@ -0,0 +1,4 @@ +export enum Dialect { + DTN, + Tony, +} diff --git a/common/enums.ts b/common/enums.ts deleted file mode 100644 index 1bdf91c2..00000000 --- a/common/enums.ts +++ /dev/null @@ -1,37 +0,0 @@ -export enum Prec { - SubtractionType = -1, - UnionType = 0, - Assignment = 1, - TypeHint = 1, - CurriedType = 1, - NamedInfixApplication = 1, - SectionIdentifier = 1, - Literal = 1, - IntersectionType = 1, - LabeledType = 2, - OperatorInfixApplication = 2, - OptionalType = 3, - Biconditional = 3, - TaggedType = 4, - Implication = 4, - Or = 5, - And = 6, - Equality = 7, - Order = 8, - Mod = 9, - Sum = 10, - Product = 11, - Exponentiation = 12, - Not = 13, - PrefixApplication = 14, - Application = 15, - Term = 16, - Pattern = 16, - Access = 17, - Pipeline = 18, -} - -export enum Dialect { - DTN, - Tony, -} diff --git a/common/imports.ts b/common/imports.ts index b60a10d5..2a422ba8 100644 --- a/common/imports.ts +++ b/common/imports.ts @@ -1,4 +1,5 @@ -import { Dialect, Prec } from './enums' +import { Dialect } from './dialects' +import { Prec } from './precedences' import { commaSep1 } from './util' export const import_ = ($: GrammarSymbols) => @@ -16,7 +17,7 @@ export const _import_body_constructor = (dialect: Dialect) => < switch (dialect) { case Dialect.DTN: return prec.left( - Prec.Pattern, + Prec.PatternOrTerm, seq( '{', commaSep1(field('import', $.import_type)), @@ -27,7 +28,7 @@ export const _import_body_constructor = (dialect: Dialect) => < ) case Dialect.Tony: return prec.left( - Prec.Pattern, + Prec.PatternOrTerm, seq( choice( field('default', alias($.identifier, $.identifier_pattern_name)), diff --git a/common/literals.ts b/common/literals.ts index e9bea2da..d775383c 100644 --- a/common/literals.ts +++ b/common/literals.ts @@ -1,10 +1,9 @@ import { BIN, DIGITS, EXP, HEX, OCT } from './constants' -import { Prec } from './enums' import { buildString } from './util' export const _literal = ( $: GrammarSymbols, -) => prec(Prec.Literal, choice($.boolean, $.number, $.string, $.regex)) +) => choice($.boolean, $.number, $.string, $.regex) export const boolean = () => choice('false', 'true') diff --git a/common/patterns.ts b/common/patterns.ts index abefb772..f8525c72 100644 --- a/common/patterns.ts +++ b/common/patterns.ts @@ -1,9 +1,9 @@ import { buildList, buildMember, buildStruct, buildTuple } from './util' -import { Prec } from './enums' +import { Prec } from './precedences' export const _pattern = ( $: GrammarSymbols, -) => prec(Prec.Pattern, choice($._assignable_pattern, $._literal_pattern)) +) => prec(Prec.PatternOrTerm, choice($._assignable_pattern, $._literal_pattern)) export const _assignable_pattern = ( $: GrammarSymbols, @@ -19,7 +19,7 @@ export const destructuring_pattern = ( $: GrammarSymbols, ) => prec( - Prec.Pattern, + Prec.PatternOrTerm, seq( optional( seq( @@ -38,7 +38,7 @@ export const struct_pattern = ( $: GrammarSymbols, ) => prec( - Prec.Pattern, + Prec.PatternOrTerm, buildStruct( $, choice( @@ -55,17 +55,17 @@ export const member_pattern = ( export const tuple_pattern = ( $: GrammarSymbols, -) => prec(Prec.Pattern, buildTuple($, $._pattern, true)) +) => prec(Prec.PatternOrTerm, buildTuple($, $._pattern, true)) export const list_pattern = ( $: GrammarSymbols, -) => prec(Prec.Pattern, buildList($, $._pattern, true)) +) => prec(Prec.PatternOrTerm, buildList($, $._pattern, true)) export const identifier_pattern = ( $: GrammarSymbols, ) => prec.right( - Prec.Pattern, + Prec.PatternOrTerm, seq( field('name', alias($.identifier, $.identifier_pattern_name)), optional(seq('::', field('type', $._type))), @@ -88,4 +88,4 @@ export const _literal_pattern = ( export const pattern_group = ( $: GrammarSymbols, -) => prec(Prec.Pattern, seq('(', field('pattern', $._pattern), ')')) +) => prec(Prec.PatternOrTerm, seq('(', field('pattern', $._pattern), ')')) diff --git a/common/precedences.ts b/common/precedences.ts new file mode 100644 index 00000000..ac9f841a --- /dev/null +++ b/common/precedences.ts @@ -0,0 +1,80 @@ +export enum Prec { + Access = 'Access', + And = 'And', + Application = 'Application', + Assignment = 'Assignment', + Biconditional = 'Biconditional', + CurriedOrIntersectionType = 'CurriedOrIntersectionType', + Equality = 'Equality', + Exponentiation = 'Exponentiation', + Identifier = 'Identifier', + Implication = 'Implication', + InfixApplication = 'InfixApplication', + LabeledType = 'LabeledType', + Mod = 'Mod', + NamedInfixApplication = 'NamedInfixApplication', + Not = 'Not', + OperatorInfixApplication = 'OperatorInfixApplication', + OptionalType = 'OptionalType', + Or = 'Or', + Order = 'Order', + PatternOrTerm = 'PatternOrTerm', + Pipeline = 'Pipeline', + PrefixApplication = 'PrefixApplication', + Product = 'Product', + SectionIdentifier = 'SectionIdentifier', + SubtractionType = 'SubtractionType', + Sum = 'Sum', + TaggedType = 'TaggedType', + TaggedValue = 'TaggedValue', + Type = 'Type', + TypeHint = 'TypeHint', + UnionType = 'UnionType', +} + +const typePrecedences = [ + Prec.Access, + Prec.TaggedType, + Prec.OptionalType, + Prec.LabeledType, + Prec.CurriedOrIntersectionType, + Prec.UnionType, + Prec.Type, + Prec.SubtractionType, +] + +const termPrecedences = [ + Prec.PatternOrTerm, + Prec.Application, + Prec.PrefixApplication, + Prec.InfixApplication, + Prec.Assignment, + Prec.TypeHint, + Prec.TaggedValue, + Prec.SectionIdentifier, + Prec.Identifier, +] + +const operatorPrecedences = [ + Prec.Pipeline, + Prec.Access, + Prec.Not, + Prec.Exponentiation, + Prec.Product, + Prec.Sum, + Prec.Mod, + Prec.Order, + Prec.Equality, + Prec.And, + Prec.Or, + Prec.Implication, + Prec.Biconditional, + Prec.OperatorInfixApplication, + Prec.NamedInfixApplication, +] + +export const precedences = () => [ + typePrecedences, + termPrecedences, + operatorPrecedences, +] diff --git a/common/terms.ts b/common/terms.ts index 58f1f3cc..c290f4dd 100644 --- a/common/terms.ts +++ b/common/terms.ts @@ -10,7 +10,7 @@ import { buildTuple, commaSep1, } from './util' -import { Prec } from './enums' +import { Prec } from './precedences' export const _term = ($: GrammarSymbols) => choice(seq($._simple_term, $._newline), $._compound_term) @@ -19,14 +19,13 @@ export const _simple_term = ( $: GrammarSymbols, ) => prec.left( - Prec.Term, + Prec.PatternOrTerm, choice( alias($.simple_abstraction, $.abstraction), $.application, $.prefix_application, $.infix_application, $._section, - // $.pipeline, $.access, alias($.simple_assignment, $.assignment), alias($.simple_export, $.export), @@ -49,7 +48,7 @@ export const _compound_term = ( $: GrammarSymbols, ) => prec.left( - Prec.Term, + Prec.PatternOrTerm, choice( alias($.compound_abstraction, $.abstraction), alias($.compound_assignment, $.assignment), @@ -175,6 +174,7 @@ export const simple_abstraction = ( $: GrammarSymbols, ) => prec.left( + Prec.PatternOrTerm, commaSep1( field('branch', alias($.simple_abstraction_branch, $.abstraction_branch)), ), @@ -182,12 +182,13 @@ export const simple_abstraction = ( export const simple_abstraction_branch = ( $: GrammarSymbols, -) => prec.left(buildAbstractionBranch($, $._simple_block)) +) => prec.left(Prec.PatternOrTerm, buildAbstractionBranch($, $._simple_block)) export const compound_abstraction = ( $: GrammarSymbols, ) => prec.left( + Prec.PatternOrTerm, repeat1( field( 'branch', @@ -198,12 +199,12 @@ export const compound_abstraction = ( export const compound_abstraction_branch = ( $: GrammarSymbols, -) => prec.left(buildAbstractionBranch($, $._compound_block)) +) => prec.left(Prec.PatternOrTerm, buildAbstractionBranch($, $._compound_block)) export const application = ( $: GrammarSymbols, ) => - prec( + prec.left( Prec.Application, seq( field('name', $._simple_term), @@ -226,175 +227,178 @@ export const prefix_application = ( export const infix_application = ( $: GrammarSymbols, ) => - choice( - prec.left( - Prec.Pipeline, - seq( - field('left', $._simple_term), - field('name', alias('&.', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.InfixApplication, + choice( + prec.left( + Prec.Pipeline, + seq( + field('left', $._simple_term), + field('name', alias('&.', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Pipeline, - seq( - field('left', $._simple_term), - field('name', alias('.', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Pipeline, + seq( + field('left', $._simple_term), + field('name', alias('.', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Not, - seq( - field('left', $._simple_term), - field('name', alias('!', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Not, + seq( + field('left', $._simple_term), + field('name', alias('!', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Exponentiation, - seq( - field('left', $._simple_term), - field('name', alias('^', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Exponentiation, + seq( + field('left', $._simple_term), + field('name', alias('^', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Product, - seq( - field('left', $._simple_term), - field('name', alias('*', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Product, + seq( + field('left', $._simple_term), + field('name', alias('*', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Product, - seq( - field('left', $._simple_term), - field('name', alias('/', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Product, + seq( + field('left', $._simple_term), + field('name', alias('/', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Sum, - seq( - field('left', $._simple_term), - field('name', alias('+', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Sum, + seq( + field('left', $._simple_term), + field('name', alias('+', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Sum, - seq( - field('left', $._simple_term), - field('name', alias('-', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Sum, + seq( + field('left', $._simple_term), + field('name', alias('-', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Mod, - seq( - field('left', $._simple_term), - field('name', alias('%', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Mod, + seq( + field('left', $._simple_term), + field('name', alias('%', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Order, - seq( - field('left', $._simple_term), - field('name', alias('<', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Order, + seq( + field('left', $._simple_term), + field('name', alias('<', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Order, - seq( - field('left', $._simple_term), - field('name', alias('<=', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Order, + seq( + field('left', $._simple_term), + field('name', alias('<=', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Order, - seq( - field('left', $._simple_term), - field('name', alias('>', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Order, + seq( + field('left', $._simple_term), + field('name', alias('>', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Order, - seq( - field('left', $._simple_term), - field('name', alias('>=', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Order, + seq( + field('left', $._simple_term), + field('name', alias('>=', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Equality, - seq( - field('left', $._simple_term), - field('name', alias('==', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Equality, + seq( + field('left', $._simple_term), + field('name', alias('==', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Equality, - seq( - field('left', $._simple_term), - field('name', alias('!=', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Equality, + seq( + field('left', $._simple_term), + field('name', alias('!=', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.And, - seq( - field('left', $._simple_term), - field('name', alias('&&', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.And, + seq( + field('left', $._simple_term), + field('name', alias('&&', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Or, - seq( - field('left', $._simple_term), - field('name', alias('||', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Or, + seq( + field('left', $._simple_term), + field('name', alias('||', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Implication, - seq( - field('left', $._simple_term), - field('name', alias('==>', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Implication, + seq( + field('left', $._simple_term), + field('name', alias('==>', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.Biconditional, - seq( - field('left', $._simple_term), - field('name', alias('<=>', $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.Biconditional, + seq( + field('left', $._simple_term), + field('name', alias('<=>', $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.OperatorInfixApplication, - seq( - field('left', $._simple_term), - field('name', alias($._operator, $.identifier)), - field('right', $._simple_term), + prec.left( + Prec.OperatorInfixApplication, + seq( + field('left', $._simple_term), + field('name', alias($._operator, $.identifier)), + field('right', $._simple_term), + ), ), - ), - prec.left( - Prec.NamedInfixApplication, - seq( - field('left', $._simple_term), - '`', - field('name', alias($._identifier_without_operators, $.identifier)), - '`', - field('right', $._simple_term), + prec.left( + Prec.NamedInfixApplication, + seq( + field('left', $._simple_term), + '`', + field('name', alias($._identifier_without_operators, $.identifier)), + '`', + field('right', $._simple_term), + ), ), ), ) @@ -519,7 +523,7 @@ export const when = ($: GrammarSymbols) => export const struct = ($: GrammarSymbols) => prec( - Prec.Term, + Prec.PatternOrTerm, buildStruct( $, choice($.member, alias($.identifier, $.shorthand_member), $.spread), @@ -530,10 +534,10 @@ export const member = ($: GrammarSymbols) => buildMember($, $._simple_term, $._simple_term) export const tuple = ($: GrammarSymbols) => - prec(Prec.Term, buildTuple($, $._element)) + prec(Prec.PatternOrTerm, buildTuple($, $._element)) export const list = ($: GrammarSymbols) => - prec(Prec.Term, buildList($, $._element)) + prec(Prec.PatternOrTerm, buildList($, $._element)) export const _element = ( $: GrammarSymbols, @@ -545,10 +549,13 @@ export const spread = ($: GrammarSymbols) => export const tagged_value = ( $: GrammarSymbols, ) => - seq( - ':', - field('name', alias($._identifier_without_operators, $.identifier)), - field('value', $._simple_term), + prec.right( + Prec.TaggedValue, + seq( + ':', + field('name', alias($._identifier_without_operators, $.identifier)), + field('value', $._simple_term), + ), ) export const type_alias = ( @@ -577,7 +584,7 @@ export const _operator = () => OPERATOR export const identifier = ( $: GrammarSymbols, -) => choice($._operator, $._identifier_without_operators) +) => prec(Prec.Identifier, choice($._operator, $._identifier_without_operators)) export const group = ($: GrammarSymbols) => seq('(', field('term', $._simple_term), ')') diff --git a/common/types.ts b/common/types.ts index 9c5d88f5..3cd81971 100644 --- a/common/types.ts +++ b/common/types.ts @@ -1,4 +1,3 @@ -import { Dialect, Prec } from './enums' import { buildGenericType, buildStruct, @@ -6,6 +5,8 @@ import { buildTypeConstraint, commaSep1, } from './util' +import { Dialect } from './dialects' +import { Prec } from './precedences' import { TYPE } from './constants' export const type_variable_declaration = ( @@ -50,7 +51,7 @@ export const _type_constructor = (dialect: Dialect) => < $.refinement_type_declaration, ) - return choice(...choices) + return prec(Prec.Type, choice(...choices)) } export const _term_type = ( @@ -80,7 +81,7 @@ export const curried_type = ( $: GrammarSymbols, ) => prec.right( - Prec.CurriedType, + Prec.CurriedOrIntersectionType, seq(field('from', $._type), '->', field('to', $._type)), ) @@ -88,7 +89,7 @@ export const intersection_type = ( $: GrammarSymbols, ) => prec.right( - Prec.IntersectionType, + Prec.CurriedOrIntersectionType, seq(field('left', $._type), '&', field('right', $._type)), ) @@ -198,7 +199,7 @@ export const optional_type = ( export const tagged_type = ( $: GrammarSymbols, ) => - prec( + prec.right( Prec.TaggedType, seq( ':', diff --git a/dtn/grammar.ts b/dtn/grammar.ts index 582b33a1..50ca28dc 100644 --- a/dtn/grammar.ts +++ b/dtn/grammar.ts @@ -46,8 +46,9 @@ import { declaration_member, js_identifier, } from '../common/declarations' -import { Dialect } from '../common/enums' +import { Dialect } from '../common/dialects' import { comment } from '../common/miscellaneous' +import { precedences } from '../common/precedences' const dialect = Dialect.DTN @@ -65,7 +66,7 @@ export = grammar({ extras: ($) => [$.comment, /\s+/], word: ($) => $._identifier_without_operators, - precedences: () => [], + precedences, rules: { program: ($) => diff --git a/tony/corpus/terms.txt b/tony/corpus/terms.txt index 2cb18e63..9db792eb 100644 --- a/tony/corpus/terms.txt +++ b/tony/corpus/terms.txt @@ -19,10 +19,13 @@ fib := c b(1) +(0) => 0 +(0, a) => 0 + 0 + () => 1 / := (a, b) => / -fn :: Number -> Number? -> Number := (a, b = 5) => a + b +fn :: Number -> Number? -> Number := (a, b = 5) => a > b --- @@ -124,8 +127,23 @@ fn :: Number -> Number? -> Number := (a, b = 5) => a + b value: (number)))))) term: (abstraction branch: (abstraction_branch - body: (block - term: (number)))) + element: (number) + body: (block + term: (number)))) + term: (abstraction + branch: (abstraction_branch + element: (number) + element: (identifier_pattern + name: (identifier_pattern_name)) + body: (block + term: (infix_application + left: (number) + name: (identifier) + right: (number))))))))) + term: (abstraction + branch: (abstraction_branch + body: (block + term: (number)))) term: (assignment pattern: (identifier_pattern name: (identifier_pattern_name)) diff --git a/tony/grammar.ts b/tony/grammar.ts index e167f1ca..ac5cbe72 100644 --- a/tony/grammar.ts +++ b/tony/grammar.ts @@ -113,7 +113,8 @@ import { union_type, } from '../common/types' import { comment, hash_bang_line } from '../common/miscellaneous' -import { Dialect } from '../common/enums' +import { Dialect } from '../common/dialects' +import { precedences } from '../common/precedences' const dialect = Dialect.Tony @@ -132,22 +133,22 @@ export = grammar({ word: ($) => $._identifier_without_operators, conflicts: ($) => [ [$._simple_term, $.identifier_pattern], + [$._simple_term, $._type], [$._simple_term, $.identifier_pattern, $._type], + [$.import_identifier, $.identifier_pattern], + [$.refinement_type_declaration, $.identifier_pattern], [$.string, $.raw_string], + [$._literal, $._literal_pattern], [$.struct, $.struct_pattern], + [$.struct, $.struct_type], [$.struct, $.struct_pattern, $.struct_type], [$.tuple, $.tuple_pattern], + [$.tuple, $.tuple_type], [$.tuple, $.tuple_pattern, $.tuple_type], [$.list, $.list_pattern], - [$.application, $.prefix_application, $.infix_application], - [$.application, $.infix_application], - [$.tagged_value, $.tagged_pattern], - [$.tagged_value, $.tagged_pattern, $.tagged_type], - [$.tagged_value, $.tagged_type], - [$.tagged_pattern, $.tagged_type], ], - precedences: () => [], + precedences, rules: { program: ($) =>