/*
 * Copyright 2017 Jaakko Hannikainen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package fi.jgke.miniplc.builder;

import static fi.jgke.miniplc.builder.BaseRules.*;
import static fi.jgke.miniplc.builder.Terminal.*;

public class Syntax {
    public static Rule statements() {
        return
                any(
                        rule(
                                all(statement(), semicolon, lazy(Syntax::statements)),
                                (rules, context) -> {
                                    rules.get(0).execute(context);
                                    rules.get(2).execute(context);
                                    return null;
                                }),
                        empty()
                );
    }

    public static Rule statement() {
        return
                any(
                        rule(
                                all(var, identifier, colon, type, maybe(assign, expression())),
                                SyntaxHandlers::createVariable),
                        rule(
                                all(identifier, assign, expression()),
                                SyntaxHandlers::updateVariable),
                        rule(
                                all(print, expression()),
                                SyntaxHandlers::printExpression),
                        rule(
                                all(read, identifier),
                                SyntaxHandlers::readVariable),
                        rule(
                                all(Assert, openBrace, expression(), closeBrace),
                                SyntaxHandlers::assertExpression),
                        rule(
                                all(For, identifier, in, expression(), range, expression(), Do, lazy(Syntax::statements), end, For),
                                SyntaxHandlers::forLoop)
                );
    }

    public static Rule expression() {
        return any(
                rule(
                        all(not, operand()),
                        SyntaxHandlers::handleNot),
                rule(
                        all(operand(), maybe(operator(), operand())),
                        SyntaxHandlers::handleOperation)
        );
    }

    public static Rule operator() {
        return any(plus, minus, times, divide, lessThan, equals, and);
    }

    public static Rule operand() {
        return any(
                rule(
                        all(any(intConst, stringConst, boolConst)),
                        SyntaxHandlers::handleConstant),
                rule(
                        all(identifier),
                        SyntaxHandlers::handleIdentifier),
                rule(
                        all(openBrace, lazy(Syntax::expression), closeBrace),
                        (rules, context) -> rules.get(1).getVariable(context))
        );
    }
}

@@ -798,33 +798,44 @@
 %7B%0A        return
+ lazy(() -%3E
 %0A
-
                 
@@ -929,29 +929,16 @@
 icolon, 
-lazy(Syntax::
 statemen
@@ -939,16 +939,17 @@
 atements
+(
 )),%0A    
@@ -1257,32 +1257,33 @@
                 
+)
 );%0A    %7D%0A%0A    pu
@@ -2313,29 +2313,16 @@
 (), Do, 
-lazy(Syntax::
 statemen
@@ -2323,16 +2323,17 @@
 atements
+(
 ), end, 
@@ -2465,32 +2465,43 @@
 %7B%0A        return
+ lazy(() -%3E
  any(%0A          
@@ -2758,32 +2758,33 @@
 ration)%0A        
+)
 );%0A    %7D%0A%0A    pu
@@ -3280,21 +3280,8 @@
 ce, 
-lazy(Syntax::
 expr
@@ -3286,16 +3286,17 @@
 pression
+(
 ), close

Move lazy() to expression's and statements' start