@@ -3,6 +3,8 @@ module BuiltinExecution.Libs.Parser
33open FSharp.Control .Tasks
44open System.Threading .Tasks
55open System.Text
6+ open System.Globalization
7+ open System
68
79open Prelude
810open LibExecution.RuntimeTypes
@@ -20,6 +22,99 @@ let pointTypeName = FQTypeName.fqPackage IDs.point
2022let rangeTypeName = FQTypeName.fqPackage IDs.range
2123let parsedNodeTypeName = FQTypeName.fqPackage IDs.parsedNode
2224
25+ let parse ( sourceCode : string ) : Dval =
26+ // This was added to handle EGCs correctly
27+ let byteIndexToCharIndex ( byteIndex : int ) ( text : string ) : int =
28+ let bytes = Encoding.UTF8.GetBytes( text)
29+ let subText = Encoding.UTF8.GetString( bytes, 0 , byteIndex)
30+ StringInfo.ParseCombiningCharacters( subText) .Length
31+
32+ let processLine ( line : string ) ( startIndex : int ) ( endIndex : int ) =
33+ let textElements = StringInfo.GetTextElementEnumerator( line)
34+ let mutable result = " "
35+ let mutable currentIndex = 0
36+ while textElements.MoveNext() do
37+ if currentIndex >= startIndex && currentIndex < endIndex then
38+ result <- result + ( textElements.GetTextElement())
39+ currentIndex <- currentIndex + 1
40+ result
41+
42+ let rec mapNodeAtCursor ( cursor : TreeCursor ) : Dval =
43+ let mutable children = []
44+
45+ if cursor.GotoFirstChild() then
46+ children <- children @ [ mapNodeAtCursor cursor ]
47+
48+ while cursor.GotoNextSibling() do
49+ children <- children @ [ mapNodeAtCursor cursor ]
50+
51+ cursor.GotoParent() |> ignore< bool>
52+
53+ let fields =
54+ let mapPoint ( point : Point ) =
55+ let pointRow = point.row + 1
56+ let fields = [ " row" , DInt64 pointRow; " column" , DInt64 point.column ]
57+ DRecord( pointTypeName, pointTypeName, [], Map fields)
58+
59+ let startPos = cursor.Current.StartPosition
60+ let endPos = cursor.Current.EndPosition
61+
62+ let range =
63+ let fields = [ " start" , mapPoint startPos; " end_" , mapPoint endPos ]
64+ DRecord( rangeTypeName, rangeTypeName, [], Map fields)
65+
66+ let sourceText =
67+ let lines = String.splitOnNewline sourceCode
68+ if lines.Length = 0 then
69+ " "
70+ else
71+ let startLine = lines[ startPos.row]
72+ let endLine = lines[ endPos.row]
73+ let startCharIndex = byteIndexToCharIndex startPos.column startLine
74+ let endCharIndex = byteIndexToCharIndex endPos.column endLine
75+
76+ match startPos.row with
77+ | row when row = endPos.row ->
78+ processLine startLine startCharIndex endCharIndex
79+ | _ ->
80+ let firstLine = processLine startLine startCharIndex startLine.Length
81+ let middleLines =
82+ if startPos.row + 1 <= endPos.row - 1 then
83+ lines[ startPos.row + 1 .. endPos.row - 1 ]
84+ |> List.map ( fun line -> processLine line 0 line.Length)
85+ else
86+ []
87+ let lastLine = processLine endLine 0 endCharIndex
88+ String.concat " \n " ( firstLine :: middleLines @ [ lastLine ])
89+
90+ let stringToHex ( input : string ) =
91+ let bytes = Encoding.UTF8.GetBytes( input)
92+ BitConverter.ToString( bytes)
93+
94+ debuG " sourceTextHex" ( stringToHex sourceText)
95+
96+
97+ let fieldName =
98+ if cursor.FieldName = null then
99+ Dval.optionNone KTString
100+ else
101+ Dval.optionSome KTString ( DString cursor.FieldName)
102+
103+ [ ( " fieldName" , fieldName)
104+ ( " typ" , DString cursor.Current.Kind)
105+ ( " text" , DString sourceText)
106+ ( " range" , range)
107+ ( " children" , DList( VT.customType parsedNodeTypeName [], children)) ]
108+
109+ DRecord( parsedNodeTypeName, parsedNodeTypeName, [], Map fields)
110+
111+
112+ let parser = new Parser( Language = DarklangLanguage.create ())
113+
114+ let tree =
115+ parser.Parse( Encoding.UTF8.GetBytes sourceCode, InputEncoding.Utf8, None)
116+ tree.Root.Walk() |> mapNodeAtCursor
117+
23118let fns : List < BuiltInFn > =
24119 [ { name = fn " parserParseToSimplifiedTree" 0
25120 typeParams = []
@@ -28,80 +123,7 @@ let fns : List<BuiltInFn> =
28123 description = " Parses some Darklang code"
29124 fn =
30125 ( function
31- | _, _, [ DString sourceCode ] ->
32- // This was added to handle EGCs correctly
33- let byteIndexToCharIndex ( byteIndex : int ) ( text : string ) : int =
34- let bytes = Encoding.UTF8.GetBytes( text)
35- let subText = Encoding.UTF8.GetString( bytes, 0 , byteIndex)
36- subText.Length
37-
38- let rec mapNodeAtCursor ( cursor : TreeCursor ) : Dval =
39- let mutable children = []
40-
41- if cursor.GotoFirstChild() then
42- children <- children @ [ mapNodeAtCursor cursor ]
43-
44- while cursor.GotoNextSibling() do
45- children <- children @ [ mapNodeAtCursor cursor ]
46-
47- cursor.GotoParent() |> ignore< bool>
48-
49- let fields =
50- let mapPoint ( point : Point ) =
51- let fields =
52- [ " row" , DInt64 point.row; " column" , DInt64 point.column ]
53- DRecord( pointTypeName, pointTypeName, [], Map fields)
54-
55- let startPos = cursor.Current.StartPosition
56- let endPos = cursor.Current.EndPosition
57-
58- let range =
59- let fields = [ " start" , mapPoint startPos; " end_" , mapPoint endPos ]
60- DRecord( rangeTypeName, rangeTypeName, [], Map fields)
61-
62- let startCharIndex = byteIndexToCharIndex startPos.column sourceCode
63- let endCharIndex = byteIndexToCharIndex endPos.column sourceCode
64-
65- let sourceText =
66- let lines = String.splitOnNewline sourceCode
67- if lines.Length = 0 then
68- " "
69- else
70- match startPos.row with
71- | row when row = endPos.row ->
72- lines[ row][ startCharIndex .. ( endCharIndex - 1 )]
73- | _ ->
74- let firstLine = lines[ startPos.row][ startCharIndex..]
75- let middleLines =
76- if startPos.row + 1 <= endPos.row - 1 then
77- lines[ startPos.row + 1 .. endPos.row - 1 ]
78- else
79- []
80- let lastLine = lines[ endPos.row][.. ( endCharIndex - 1 )]
81-
82- String.concat " \n " ( firstLine :: middleLines @ [ lastLine ])
83-
84- let fieldName =
85- if cursor.FieldName = null then
86- Dval.optionNone KTString
87- else
88- Dval.optionSome KTString ( DString cursor.FieldName)
89-
90- [ ( " fieldName" , fieldName)
91- ( " typ" , DString cursor.Current.Kind)
92- ( " text" , DString sourceText)
93- ( " range" , range)
94- ( " children" , DList( VT.customType parsedNodeTypeName [], children)) ]
95-
96- DRecord( parsedNodeTypeName, parsedNodeTypeName, [], Map fields)
97-
98-
99- let parser = new Parser( Language = DarklangLanguage.create ())
100-
101- let tree =
102- parser.Parse( Encoding.UTF8.GetBytes sourceCode, InputEncoding.Utf8, None)
103-
104- tree.Root.Walk() |> mapNodeAtCursor |> Ply
126+ | _, _, [ DString sourceCode ] -> ( parse sourceCode) |> Ply
105127 | _ -> incorrectArgs ())
106128 sqlSpec = NotQueryable
107129 previewable = Impure
0 commit comments