-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy pathparsing.wyv
82 lines (73 loc) · 3.2 KB
/
parsing.wyv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
module parsing
import javaMetaDebug
import wyvern.ast
import metadata wyvern.collections.list
import javascript:stdlib.support.parsing
import selfhost.lexing
import wyvern.util.matching.regexInternal
import java:wyvern.stdlib.support.StringHelper.utils
// based on Nearly, see https://nearley.js.org/docs/grammar
// also an article: https://medium.com/@gajus/parsing-absolutely-anything-in-javascript-using-earley-algorithm-886edcc31e5e
val regex = regexInternal
val lineRegex = regex(".*\n")
val untilColonRegex = regex("[^:]*:")
def linesCollect(input:String, f : String -> String):String
def linesCollectHelper(input:String, f : String -> String, acc:String):String
match lineRegex.findPrefixMatchOf(input):
s:option.Some => linesCollectHelper(s.content.after(), f, acc + f(s.content.matched()))
n:option.None => acc+f(input)
linesCollectHelper(input, f, "")
/*
def lines(input:String):list.List[String]
val result = list.make[String]()
var current : String = input
var r : regex.Regex = lineRegex.findPrefixMatchOf(input)
while {r.isDefined}
val match = r.get()
val line = match.matched()
result.append(line)
current = match.after()
r = lineRegex.findPrefixMatchOf(current)
result.append(current)
result
*/
/* input is the body of the TSL block
* decls is the list of decls we will add functions to
* we return a String which is the Nearly code to use in generating the parser
*/
def parse(input : String, decls : list.List[ast.Decl], ctx : system.Context) : String
var index : Int = 0
def processLine(line : String) : String
match untilColonRegex.findPrefixMatchOf(line):
s:option.Some =>
val m = s.content.matched()
val production = m.substring(0, m.length()-1)
val result = production + "{% function(a) { return context.f" + utils.ofInt(index) + ".apply(a) } %}\n"
val wyvExp = s.content.after()
val bodyAST = ast.parseExpression(wyvExp, ctx)
val realAST:Dyn = bodyAST.ast
//val arg = ast.formalArg("x",ast.types.dyn())
val valAST = ast.valDeclaration("f" + utils.ofInt(index), ast.types.dyn(), bodyAST)
decls.append(valAST)
index = index + 1
result
n:option.None =>
line // empty line, or no processing done
linesCollect(input, x => processLine(x))
type Grammar
val parseInfo:String
metadata new
def parseTSL(input : String, ctx : system.Context) : option.Option
// create a string ast from input
val decls = list.make[ast.Decl]()
val nearlyString = parse(input, decls, ctx)
val stringAST = ast.string(nearlyString) // input
// create an object with the string as a field
decls.append(ast.valDeclaration("parseInfo", ast.types.string(), stringAST))
val result = ast.object(decls)
option.Some(result)
type Parser
def feed(input:String):Unit
val results:Dyn
def makeParser(grammar: Grammar, lexer : lexing.Lexer):Parser
parsing.makeParserWithContext(grammar.parseInfo, lexer, grammar)