Skip to content

Commit

Permalink
Merge pull request #5322 from OceanOak/grammar-updates-3
Browse files Browse the repository at this point in the history
Update the grammar to support the remaining infix operators
  • Loading branch information
StachuDotNet authored Mar 12, 2024
2 parents 99834e8 + 85bea81 commit 0a7fcff
Show file tree
Hide file tree
Showing 10 changed files with 6,568 additions and 2,766 deletions.
10 changes: 10 additions & 0 deletions backend/testfiles/execution/stdlib/parser.dark
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,16 @@ module TextToTextRoundtripping =
// TODO: these is ugly
("1L + 2L" |> roundtripCliScript) = "(1L) + (2L)"
("1L + b + 3L" |> roundtripCliScript) = "((1L) + (b)) + (3L)"
("1L + 2L * 3L - 4L" |> roundtripCliScript) = "((1L) + ((2L) * (3L))) - (4L)"
("1L > 2L" |> roundtripCliScript) = "(1L) > (2L)"
("1L >= 2L" |> roundtripCliScript) = "(1L) >= (2L)"
("1L < 2L" |> roundtripCliScript) = "(1L) < (2L)"
("1L <= 2L" |> roundtripCliScript) = "(1L) <= (2L)"
("1L == 2L" |> roundtripCliScript) = "(1L) == (2L)"
("1L != 2L" |> roundtripCliScript) = "(1L) != (2L)"
("1L ^ 2L" |> roundtripCliScript) = "(1L) ^ (2L)"
("true && false" |> roundtripCliScript) = "(true) && (false)"
("true || false" |> roundtripCliScript) = "(true) || (false)"
("(and true false)" |> roundtripCliScript) = "and true false"
("(Bool.and true false)" |> roundtripCliScript) = "Bool.and true false"
("(PACKAGE.Darklang.Stdlib.Bool.and true false)" |> roundtripCliScript) = "PACKAGE.Darklang.Stdlib.Bool.and_v0 true false"
Expand Down
43 changes: 41 additions & 2 deletions packages/darklang/languageTools/parser.dark
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ module Darklang =
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error


let parseFloatLiteral
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.Expr, WrittenTypes.Unparseable> =
Expand Down Expand Up @@ -656,8 +657,46 @@ module Darklang =
match operatorNode with
| Ok operatorNode ->
match getText operatorNode with
| "+" -> WrittenTypes.InfixOperator.ArithmeticPlus
| "-" -> WrittenTypes.InfixOperator.ArithmeticMinus
| "+" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ArithmeticPlus
| "-" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ArithmeticMinus
| "*" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ArithmeticMultiply
| "/" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ArithmeticDivide
| "%" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ArithmeticModulo
| "^" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ArithmeticPower
| ">" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ComparisonGreaterThan
| ">=" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ComparisonGreaterThanOrEqual
| "<" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ComparisonLessThan
| "<=" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ComparisonLessThanOrEqual
| "==" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ComparisonEquals
| "!=" ->
WrittenTypes.Infix.InfixFnCall
WrittenTypes.InfixFnName.ComparisonNotEquals
| "&&" ->
WrittenTypes.Infix.BinOp WrittenTypes.BinaryOperation.BinOpAnd
| "||" ->
WrittenTypes.Infix.BinOp WrittenTypes.BinaryOperation.BinOpOr
| _ ->
(WrittenTypes.Unparseable { source = node })
|> Stdlib.Result.Result.Error
Expand Down
23 changes: 21 additions & 2 deletions packages/darklang/languageTools/writtenTypes.dark
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,28 @@ module Darklang =
// Expressions
type LetPattern = LPVariable of SourceRange * name: String

type InfixOperator =
type Infix =
| InfixFnCall of InfixFnName
| BinOp of BinaryOperation

type InfixFnName =
| ArithmeticPlus
| ArithmeticMinus
| ArithmeticMultiply
| ArithmeticDivide
| ArithmeticModulo
| ArithmeticPower
| ComparisonGreaterThan
| ComparisonGreaterThanOrEqual
| ComparisonLessThan
| ComparisonLessThanOrEqual
| ComparisonEquals
| ComparisonNotEquals
| StringConcat

type BinaryOperation =
| BinOpAnd
| BinOpOr

type Expr =
| EUnit of SourceRange
Expand Down Expand Up @@ -141,7 +160,7 @@ module Darklang =

| EInfix of
SourceRange *
op: (SourceRange * InfixOperator) *
op: (SourceRange * Infix) *
left: Expr *
right: Expr

Expand Down
44 changes: 35 additions & 9 deletions packages/darklang/languageTools/writtenTypesToProgramTypes.dark
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,40 @@ module Darklang =
deprecated = ProgramTypes.Deprecation.NotDeprecated }


module InfixFnName =
let toPT (infix: WrittenTypes.InfixFnName) : ProgramTypes.InfixFnName =
match infix with
| ArithmeticPlus -> ProgramTypes.InfixFnName.ArithmeticPlus
| ArithmeticMinus -> ProgramTypes.InfixFnName.ArithmeticMinus
| ArithmeticMultiply -> ProgramTypes.InfixFnName.ArithmeticMultiply
| ArithmeticDivide -> ProgramTypes.InfixFnName.ArithmeticDivide
| ArithmeticModulo -> ProgramTypes.InfixFnName.ArithmeticModulo
| ArithmeticPower -> ProgramTypes.InfixFnName.ArithmeticPower
| ComparisonGreaterThan -> ProgramTypes.InfixFnName.ComparisonGreaterThan
| ComparisonGreaterThanOrEqual ->
ProgramTypes.InfixFnName.ComparisonGreaterThanOrEqual
| ComparisonLessThan -> ProgramTypes.InfixFnName.ComparisonLessThan
| ComparisonLessThanOrEqual ->
ProgramTypes.InfixFnName.ComparisonLessThanOrEqual
| ComparisonEquals -> ProgramTypes.InfixFnName.ComparisonEquals
| ComparisonNotEquals -> ProgramTypes.InfixFnName.ComparisonNotEquals
| StringConcat -> ProgramTypes.InfixFnName.StringConcat


module BinaryOperation =
let toPT
(binop: WrittenTypes.BinaryOperation)
: ProgramTypes.BinaryOperation =
match binop with
| BinOpAnd -> ProgramTypes.BinaryOperation.BinOpAnd
| BinOpOr -> ProgramTypes.BinaryOperation.BinOpOr


module Infix =
let toPT (infix: WrittenTypes.Infix) : ProgramTypes.Infix =
match infix with
| InfixFnCall op -> ProgramTypes.Infix.InfixFnCall(InfixFnName.toPT op)
| BinOp op -> ProgramTypes.Infix.BinOp(BinaryOperation.toPT op)

module Expr =
module LetPattern =
Expand Down Expand Up @@ -187,15 +221,7 @@ module Darklang =

// fn calls
| EInfix(_, (_, op), left, right) ->
let infix =
match op with
| ArithmeticPlus ->
ProgramTypes.InfixFnName.ArithmeticPlus
|> ProgramTypes.Infix.InfixFnCall

| ArithmeticMinus ->
ProgramTypes.InfixFnName.ArithmeticMinus
|> ProgramTypes.Infix.InfixFnCall
let infix = Infix.toPT op

ProgramTypes.Expr.EInfix(
gid (),
Expand Down
2 changes: 1 addition & 1 deletion packages/darklang/prettyPrinter/programTypes.dark
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ module Darklang =
| ComparisonLessThan -> "<"
| ComparisonLessThanOrEqual -> "<="
| ComparisonEquals -> "=="
| ComparisonNotEquals -> "<>"
| ComparisonNotEquals -> "!="
| StringConcat -> "++"

let infix (i: PACKAGE.Darklang.LanguageTools.ProgramTypes.Infix) : String =
Expand Down
78 changes: 72 additions & 6 deletions tree-sitter-darklang/grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@
// - deal with keywords
// - better support for partially-written code (i.e. `let x =`)

const PREC = {
LOGICAL_OR: 0,
LOGICAL_AND: 1,
COMPARISON: 2,
SUM: 3,
PRODUCT: 4,
EXPONENT: 5,
};

const logicalOperators = choice("&&", "||");
const comparisonOperators = choice("==", "!=", "<", "<=", ">", ">=");
const additiveOperators = choice("+", "-");
const multiplicativeOperators = choice("*", "/", "%");
const exponentOperator = "^";

module.exports = grammar({
name: "darklang",

Expand Down Expand Up @@ -139,12 +154,63 @@ module.exports = grammar({

infix_operation: $ =>
// given `1 + 2 * 3`, this will parse as `1 + (2 * 3)`
prec.left(
1,
seq(
field("left", $.expression),
field("operator", alias(choice("+", "-"), $.operator)), // TODO more operators.
field("right", $.expression), // TODO maybe optional
choice(
// Power
prec.right(
PREC.EXPONENT,
seq(
field("left", $.expression),
field("operator", alias(exponentOperator, $.operator)),
field("right", $.expression),
),
),

// multiplication, division, modulo
prec.left(
PREC.PRODUCT,
seq(
field("left", $.expression),
field("operator", alias(multiplicativeOperators, $.operator)),
field("right", $.expression),
),
),

// addition, subtraction
prec.left(
PREC.SUM,
seq(
field("left", $.expression),
field("operator", alias(additiveOperators, $.operator)),
field("right", $.expression),
),
),

// Comparison
prec.left(
PREC.COMPARISON,
seq(
field("left", $.expression),
field("operator", alias(comparisonOperators, $.operator)),
field("right", $.expression),
),
),

// Logical operations
prec.left(
PREC.LOGICAL_AND,
seq(
field("left", $.expression),
field("operator", alias(logicalOperators, $.operator)),
field("right", $.expression),
),
),
prec.left(
PREC.LOGICAL_OR,
seq(
field("left", $.expression),
field("operator", alias(logicalOperators, $.operator)),
field("right", $.expression),
),
),
),

Expand Down
Loading

0 comments on commit 0a7fcff

Please sign in to comment.