Skip to content

Commit a6bc236

Browse files
added: readme.md
1 parent 9dbbc67 commit a6bc236

File tree

2 files changed

+30
-90
lines changed

2 files changed

+30
-90
lines changed

parser_combinators.go

+22-90
Original file line numberDiff line numberDiff line change
@@ -43,114 +43,46 @@ func parseUnary(pr *parser) *astNode {
4343

4444
}
4545

46+
// exponent -> unary ( ("**") unary )*
4647
func parseExponent(pr *parser) *astNode {
47-
log.Print("inside exponent")
48-
49-
leftUnary := parseUnary(pr) // consume first unary
50-
var parent = leftUnary
51-
52-
for token := pr.peek(); token.tokenType == RaisePower; token = pr.peek() {
53-
54-
if pr.eof() {
55-
break // we are just breaking the rule as we in the recusrive expansion of (**) unary
56-
}
57-
pr.next() // consume **
58-
// not checkig for eof as we have checked while calling peek()
59-
rightUnary := parseExponent(pr)
60-
61-
parent = newASTNode(token, parent, rightUnary, evalInfix) // exponent is right associated operation for us
62-
}
63-
return parent
48+
return parseCombinator(pr, evalInfix, parseUnary, RaisePower)
6449
}
6550

6651
// factor -> exponent ( ( "/" | "*" | "%" ) exponent)*
6752
func parseFactor(pr *parser) *astNode {
68-
log.Print("inside factor")
69-
70-
leftExponent := parseExponent(pr) // consume first unary
71-
var parent = leftExponent
72-
73-
for token := pr.peek(); token.tokenType == Mod || token.tokenType == Asterisk || token.tokenType == Slash; token = pr.peek() {
74-
75-
if pr.eof() {
76-
break // we are just breaking the rule as we in the recusrive expansion of (*|/) unary
77-
}
78-
pr.next() // consume * or /
79-
// not checkig for eof as we have checked while calling peek()
80-
rightExponent := parseFactor(pr) // Makr
81-
82-
parent = newASTNode(token, parent, rightExponent, evalInfix)
83-
}
84-
return parent
53+
return parseCombinator(pr, evalInfix, parseExponent, Mod, Asterisk, Slash)
8554
}
8655

8756
// term -> factor (( "+" | "-" ) factor)*
8857
func parseTerm(pr *parser) *astNode {
89-
log.Print("inside term")
90-
leftUnary := parseFactor(pr) // consume first unary
91-
var parent = leftUnary
92-
log.Print("Peek Token : ", pr.peek())
93-
for token := pr.peek(); token.tokenType == Plus || token.tokenType == Minus; token = pr.peek() {
94-
log.Print("Inside Loop")
95-
if pr.eof() {
96-
break // we are just breaking the rule as we in the recusrive expansion of (+|-) factor
97-
}
98-
99-
pr.next() // consume + or -
100-
rightUnary := parseTerm(pr)
101-
102-
parent = newASTNode(token, parent, rightUnary, evalInfix)
103-
104-
}
105-
log.Print("Out of Loop")
106-
return parent
107-
58+
return parseCombinator(pr, evalInfix, parseFactor, Plus, Minus)
10859
}
10960

11061
// comparison -> term (( ">" | ">=" | "<" | "<=" ) term)*
11162
func parseComp(pr *parser) *astNode {
112-
log.Print("inside comp")
113-
leftUnary := parseTerm(pr) // consume first unary
114-
var parent = leftUnary
115-
for {
116-
token := pr.peek()
117-
if pr.eof() {
118-
break // we are just breaking the rule as we in the recusrive expansion of (>|>=|<|<=) term
119-
}
120-
121-
switch token.tokenType {
122-
case LT, GT, LTEQ, GTEQ:
123-
pr.next() // consume > or >= or < or <=
124-
rightUnary := parseComp(pr)
125-
126-
parent = newASTNode(token, parent, rightUnary, evalInfix)
127-
default:
128-
129-
return parent
130-
}
131-
132-
}
133-
return parent
63+
return parseCombinator(pr, evalInfix, parseTerm, LT, GT, LTEQ, GTEQ)
13464
}
13565

13666
// expr -> comparison ( ( "==" | "!=" ) comparison )*
13767
func parseExpr(pr *parser) *astNode {
138-
log.Print("inside expr")
139-
140-
leftUnary := parseComp(pr) // consume first unary
141-
var parent = leftUnary
68+
return parseCombinator(pr, evalInfix, parseComp, Eq, NotEq)
69+
}
14270

143-
for token := pr.peek(); token.tokenType == Eq || token.tokenType == NotEq; token = pr.peek() {
144-
if pr.eof() {
145-
break // we are just breaking the rule as we in the recusrive expansion of (== or !=) comparison
71+
func parseCombinator(pr *parser, evalr evaluator, nonterminalParser parserFn, matchableTokens ...TokenType) *astNode {
72+
var tokenMap = make(map[TokenType]struct{}, len(matchableTokens))
73+
for _, token := range matchableTokens {
74+
tokenMap[token] = struct{}{}
75+
}
76+
var fn parserFn
77+
fn = func(pr *parser) *astNode {
78+
parent := nonterminalParser(pr) // parsing first part of the grammar e.g. in grammar E -> F ( operator E )* parses F
79+
token := pr.peek()
80+
_, ok := tokenMap[token.tokenType]
81+
if !pr.eof() && ok {
82+
pr.next() // consume token
83+
return newASTNode(token, parent, fn(pr), evalr)
14684
}
147-
148-
pr.next() // consume == or !=
149-
rightUnary := parseExpr(pr)
150-
151-
parent = newASTNode(token, parent, rightUnary, evalInfix)
152-
85+
return parent
15386
}
154-
return parent
155-
87+
return fn(pr)
15688
}

readme.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# RUGIA
2+
3+
- RUGIA is a simple expression lanuage
4+
- It supports parenthess
5+
- It supports, + , - , / , %, ** etc. mathamatical operations
6+
- It also supports == != >= <= > < etc, logical operations
7+
8+
e.g. *2 + 3 * 4* would result in *14*

0 commit comments

Comments
 (0)