-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParser.n
121 lines (89 loc) · 3.49 KB
/
Parser.n
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Generic;
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;
using Nemerle.Peg;
namespace tinyacc
{
[PegGrammar(Options = EmitDebugSources, start,
grammar
{
any = ['\u0000'..'\uFFFF'];
#region White space
whitespace = [Zs]
/ '\t'
/ '\v' /* vertial tab */
/ '\f'; /* form feed */
#endregion
#region Line terminators
newLineCharacter = '\n'
/ '\r'
/ '\u2028' /* line separator */
/ '\u2029'; /* paragraph separator */
newLine = ("\r\n" / newLineCharacter);
#endregion
#region Comments
singleLineComment = "//" (!newLineCharacter any)*;
delimitedComment = "/*" (!"*/" any)* "*/";
comment = singleLineComment / delimitedComment;
#endregion
#region Spacer
space : Void = whitespace / newLine / comment;
semicolon : Void = ";" space*;
#endregion
#region Identifiers
decimalDigit = ['0'..'9'];
combiningCharacter = [Mn, Mc];
decimalDigitCharacter = [Nd];
connectingCharacter = [Pc];
formattingCharacter = [Cf];
letterCharacter = [Lu, Ll, Lt, Lm, Lo, Nl] / '$' / '+' / '-';
#endregion
identifierStartCharacter = letterCharacter / "_";
identifierPartCharacters = letterCharacter / decimalDigitCharacter / connectingCharacter / combiningCharacter / formattingCharacter;
identifierBody = identifierStartCharacter identifierPartCharacters*;
identifier = identifierBody;
name = identifier;
number = decimalDigit* "." decimalDigit+ / decimalDigit*;
accountName = name;
currencyName = name;
operationName = name;
rate : Ast = "rate" space+ currencyName space+ currencyName space+ number semicolon;
account : Ast = "account" space+ currencyName space+ number space+ accountName space* semicolon;
creditOrDebit : Ast = ('+'/ '-') space* number space+ currencyName space+ accountName space+ operationName space* semicolon;
badRecord : Ast = (!semicolon any)* semicolon;
veryBadRecord : Ast = any+;
definition : Ast = (rate / account / creditOrDebit / badRecord / veryBadRecord) space*;
start : List[Ast] = space* definition* !any;
})]
public class AccParser
{
badRecord(_ : NToken) : Ast
{
Ast.Bad()
}
veryBadRecord(_ : NToken) : Ast
{
Ast.Bad()
}
rate(_ : NToken, currencyNameFrom : NToken, currencyNameTo : NToken, course : NToken) : Ast
{
Ast.Rate(GetText(currencyNameFrom), GetText(currencyNameTo), Convert.ToDouble(GetText(course)));
}
account(_ : NToken, currencyName : NToken, balance : NToken, accountName : NToken) : Ast
{
Ast.Account(GetText(accountName), GetText(currencyName), Convert.ToDouble(GetText(balance)));
}
creditOrDebit(operation : NToken, amount : NToken, currencyName : NToken, accountName : NToken, operationName : NToken) : Ast
{
def op = match(GetText(operation))
{
| "-" => OperationType.Debit
| "+" => OperationType.Credit
| _ => OperationType.Credit
}
Ast.Operation(op, Convert.ToDouble(GetText(amount)), GetText(currencyName), GetText(accountName), GetText(operationName));
}
}
}