Skip to content

Commit

Permalink
functional parsing, ast translation, incomplete
Browse files Browse the repository at this point in the history
  • Loading branch information
PtrMan committed Dec 10, 2015
1 parent db25139 commit dd3eca8
Show file tree
Hide file tree
Showing 11 changed files with 378 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ptrman.causalReasoningSystem.functional.language.ast;

/**
* Created by r0b3 on 10.12.2015.
*/
public class Element extends ptrman.causalReasoningSystem.functional.tree.Element {
public enum EnumCallType {
ADD,
SUB,
MUL,
DIV
}

public String identifier; // null if it is not an identififer
public EnumCallType callType; // can be null if it is not a function call

public int constantInteger; // only valid for a constant integer

public Element(Type type) {
super();
this.type = type;
}

@Override
public boolean isEqual(ptrman.causalReasoningSystem.functional.tree.Element other) {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ptrman.causalReasoningSystem.functional.language.ast;

/**
* Created by r0b3 on 09.12.2015.
*/
public class Type extends ptrman.causalReasoningSystem.functional.tree.Type {
public enum EnumType {
FUNCDAMENTAL_SEQUENCE,

COND,
FUNCTION_DEFINITION,
FUNCTION_CALL,

COMPARISION_LESS,
COMPARISON_MESSEQUAL,
COMPARISION_GREATER,
COMPARISION_GREATEREQUAL,
COMPARISION_EQUAL,
COMPARISION_NOTEQUAL,

OPERATION_SUBTRACTION,
OPERATION_ADDITION,
OPERATION_MULTIPLICATION,
OPERATION_DIVISION,

NIL,

VARIABLE,

CONSTANT_INTEGER
}

private final EnumType type;

public Type(EnumType type) {
this.type = type;
}

@Override
public boolean isEqualWithType(ptrman.causalReasoningSystem.functional.tree.Type other) {
return type == ((Type)other).type;
}

@Override
public boolean isFundamentalType() {
return type == EnumType.FUNCDAMENTAL_SEQUENCE;
}

@Override
public EnumFundamentalType getFundamentalType() {
if( type == EnumType.FUNCDAMENTAL_SEQUENCE ) {
return EnumFundamentalType.SEQUENCE;
}
throw new RuntimeException("Internal Error");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package ptrman.causalReasoningSystem.functional.language.convertParseTreeToAst;

import ptrman.causalReasoningSystem.functional.language.ast.Type;
import ptrman.causalReasoningSystem.functional.language.parseTree.BasicIdentifierParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.parseTree.BasicIntegerParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.parseTree.HasChildrenParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.parseTree.ParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.ast.Element;

/**
* Created by r0b3 on 10.12.2015.
*/
public class ConvertParseTreeToAst {
public static Element convert(ParseTreeElement root) {
if( root instanceof BasicIdentifierParseTreeElement ) {
BasicIdentifierParseTreeElement convertedRoot = (BasicIdentifierParseTreeElement)root;

Element result = new Element(new Type(Type.EnumType.VARIABLE));
result.identifier = convertedRoot.identifier;
return result;
}
else if( root instanceof HasChildrenParseTreeElement ) {
HasChildrenParseTreeElement convertedRoot = (HasChildrenParseTreeElement)root;

if( convertedRoot.type == HasChildrenParseTreeElement.EnumType.STANDARDCALL_BRACES ) {
/**
* the result is a FUNCTION_CALL where the identifier is set to the function name or the calltype is set to the calltype
*/
// TODO ULTRALOW< maybe the component pattern improves this but its overkill because it adds unneeded complexity >

Element result = new Element(new Type(Type.EnumType.FUNCTION_CALL));

HasChildrenParseTreeElement calledFunctionIdentifierOrOperator = ((HasChildrenParseTreeElement)convertedRoot.children[0]);
if( calledFunctionIdentifierOrOperator.children[0] instanceof BasicIdentifierParseTreeElement) {
BasicIdentifierParseTreeElement calleeNameTreeElement = (BasicIdentifierParseTreeElement)calledFunctionIdentifierOrOperator.children[0];
String calleeName = calleeNameTreeElement.identifier;
result.identifier = calleeName;
}
else {
HasChildrenParseTreeElement operator = (HasChildrenParseTreeElement)calledFunctionIdentifierOrOperator.children[0];

if( operator.type == HasChildrenParseTreeElement.EnumType.PLUS ) {
result.callType = Element.EnumCallType.ADD;
}
else if( operator.type == HasChildrenParseTreeElement.EnumType.MINUS ) {
result.callType = Element.EnumCallType.SUB;
}
else if( operator.type == HasChildrenParseTreeElement.EnumType.MUL ) {
result.callType = Element.EnumCallType.MUL;
}
else if( operator.type == HasChildrenParseTreeElement.EnumType.DIV ) {
result.callType = Element.EnumCallType.DIV;
}
else {
throw new RuntimeException("Internal error!");
}
}

// translate all operands
for( int childrenI = 1; childrenI < convertedRoot.children.length; childrenI++ ) {
result.children.add(convert(convertedRoot.children[childrenI]));
}

return result;
}
else if( convertedRoot.type == HasChildrenParseTreeElement.EnumType.CONSTANT_INTEGER ) {
BasicIntegerParseTreeElement constantParseTreeElement = ((BasicIntegerParseTreeElement)convertedRoot.children[0]);

Element result = new Element(new Type(Type.EnumType.CONSTANT_INTEGER));
result.constantInteger = Integer.parseInt(constantParseTreeElement.constant);
return result;
}

else {
throw new RuntimeException("Internal Error!");
}
}
else {
throw new RuntimeException("Internal error!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ptrman.causalReasoningSystem.functional.language.parseTree;

/**
* Created by r0b3 on 09.12.2015.
*/
public class BasicIdentifierParseTreeElement extends ParseTreeElement {
public final String identifier;

public BasicIdentifierParseTreeElement(String identifier) {
super();
this.identifier = identifier;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ptrman.causalReasoningSystem.functional.language.parseTree;

import ptrman.causalReasoningSystem.functional.language.parseTree.ParseTreeElement;

/**
* Created by r0b3 on 10.12.2015.
*/
public class BasicIntegerParseTreeElement extends ParseTreeElement {
public final String constant;

public BasicIntegerParseTreeElement(String constant) {
super();
this.constant = constant;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ptrman.causalReasoningSystem.functional.language.parseTree;

import java.util.List;

/**
* Created by r0b3 on 09.12.2015.
*/
public class HasChildrenParseTreeElement extends ParseTreeElement {
public final ParseTreeElement[] children;
public final EnumType type;

public enum EnumType {
IDENTIFIER_OR_FUNCTION_OR_OPERATOR,
STANDARDCALL_BRACES,

PLUS,
MINUS,
MUL,
VARIABLE_OR_CONSTANT_OR_STANDARD_CALL_BRACES, VARIABLE, CONSTANT_INTEGER, DIV
}

public HasChildrenParseTreeElement(EnumType type, ParseTreeElement[] children) {
super();
this.type = type;
this.children = children;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package ptrman.causalReasoningSystem.functional.language.parseTree;

public class ParseTreeElement {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ptrman.causalReasoningSystem.functional.language.parser;

import com.github.fge.grappa.Grappa;
import com.github.fge.grappa.run.ListeningParseRunner;
import com.github.fge.grappa.run.ParseRunner;
import com.github.fge.grappa.run.ParsingResult;
import ptrman.causalReasoningSystem.functional.language.parseTree.ParseTreeElement;

/**
* Created by r0b3 on 10.12.2015.
*/
public class Parse {
public static ParseTreeElement parse(String text) {
Parser parser = Grappa.createParser(Parser.class);

ParseRunner<ParseTreeElement> runner = new ListeningParseRunner<>(parser.standardCallBraces());
ParsingResult<ParseTreeElement> parsingResult = runner.run(text);

if (!parsingResult.isSuccess()) {
throw new RuntimeException("Syntax Error!");
}

ParseTreeElement topElement = parsingResult.getTopStackValue();
return topElement;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package ptrman.causalReasoningSystem.functional.language.parser;


import com.github.fge.grappa.parsers.BaseParser;
import com.github.fge.grappa.rules.Rule;
import com.github.fge.grappa.support.StringVar;
import com.github.fge.grappa.support.Var;
import ptrman.causalReasoningSystem.functional.language.parseTree.BasicIdentifierParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.parseTree.BasicIntegerParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.parseTree.HasChildrenParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.parseTree.ParseTreeElement;

import java.util.ArrayList;
import java.util.List;

/**
* Simple functional grammar
*/
// TODO< spaces are not correct for all rules >
public class Parser extends BaseParser<ParseTreeElement> {
Rule standardCallBraces() {
Var<ParseTreeElement> callIdentifier = new Var<>();
Var<List<ParseTreeElement>> arguments = new Var<>(new ArrayList<>());

return sequence(
'(',
whiteSpaces(), identifierOrFunctionOrOperator(), callIdentifier.set(pop()), whiteSpaces(),
optional(
variableOrConstantOrStandardCallBraces(), arguments.get().add(pop()), whiteSpaces(),
zeroOrMore(variableOrConstantOrStandardCallBraces(), arguments.get().add(pop()), whiteSpaces())
),
')',
push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.STANDARDCALL_BRACES, convertElementAndListToArray(callIdentifier.get(), arguments.get()))));
}

Rule variableOrConstantOrStandardCallBraces() {
return firstOf(
sequence(standardCallBraces(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.VARIABLE_OR_CONSTANT_OR_STANDARD_CALL_BRACES, new ParseTreeElement[]{pop()}))),
sequence(variable(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.VARIABLE_OR_CONSTANT_OR_STANDARD_CALL_BRACES, new ParseTreeElement[]{pop()}))),
sequence(integer(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.CONSTANT_INTEGER, new ParseTreeElement[]{pop()})))
);
}

Rule identifierOrFunctionOrOperator() {
// TODO< other cases >
return firstOf(
sequence(basicIdentifier(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.IDENTIFIER_OR_FUNCTION_OR_OPERATOR, new ParseTreeElement[]{pop()}))),
sequence('+', push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.IDENTIFIER_OR_FUNCTION_OR_OPERATOR, new ParseTreeElement[]{new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.PLUS, new ParseTreeElement[]{})}))),
sequence('-', push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.IDENTIFIER_OR_FUNCTION_OR_OPERATOR, new ParseTreeElement[]{new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.MINUS, new ParseTreeElement[]{})}))),
sequence('*', push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.IDENTIFIER_OR_FUNCTION_OR_OPERATOR, new ParseTreeElement[]{new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.MUL, new ParseTreeElement[]{})}))),
sequence('/', push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.IDENTIFIER_OR_FUNCTION_OR_OPERATOR, new ParseTreeElement[]{new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.DIV, new ParseTreeElement[]{})})))
);
}

Rule variable() {
return sequence(basicIdentifier(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.VARIABLE, new ParseTreeElement[]{pop()})));
}

Rule basicIdentifier() {
StringVar var = new StringVar();

return sequence(
anyOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
var.append(match()),
zeroOrMore(anyOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")),
push(new BasicIdentifierParseTreeElement(var.get() + match()))
);
}

Rule integer() {
StringVar var = new StringVar();

return sequence(
anyOf("123456789"),
var.append(match()),
zeroOrMore(anyOf("0123456789")),
push(new BasicIntegerParseTreeElement(var.get() + match()))
);
}


// from http://stackoverflow.com/questions/33029437/matching-or-expression-using-grappa-java-peg-parser
Rule whiteSpaces() {
return join(zeroOrMore(wsp())).using(sequence(optional(cr()), lf())).min(0);
}

Rule whiteSpacesAtleastOne() {
return join(oneOrMore(wsp())).using(sequence(optional(cr()), lf())).min(1);
}

// helpers

protected static ParseTreeElement[] convertElementAndListToArray(ParseTreeElement element, List<ParseTreeElement> list) {
ParseTreeElement[] result = new ParseTreeElement[1 + list.size()];

result[0] = element;

for( int i = 0; i < list.size(); i++ ) {
result[i+1] = list.get(i);
}

return result;
}
}



Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@
public abstract class Element {
public Type type;
public List<Element> children = new ArrayList<>();

public abstract boolean isEqual(final Element other);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ptrman.causalReasoningSystem.interactiveTests;

import ptrman.causalReasoningSystem.functional.language.ast.Element;
import ptrman.causalReasoningSystem.functional.language.convertParseTreeToAst.ConvertParseTreeToAst;
import ptrman.causalReasoningSystem.functional.language.parseTree.ParseTreeElement;
import ptrman.causalReasoningSystem.functional.language.parser.Parse;

/**
* Created by r0b3 on 10.12.2015.
*/
public class InterpreterTest {
public static void main(String[] args) {
ParseTreeElement parseTree = Parse.parse("(a 5)");

Element ast = ConvertParseTreeToAst.convert(parseTree);

int x = 0;
}

}

0 comments on commit dd3eca8

Please sign in to comment.