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