From 30d75a67a63b702b74fc8a702482969241d14891 Mon Sep 17 00:00:00 2001 From: Yuehan-Lin Date: Mon, 23 Sep 2019 14:01:16 -0400 Subject: [PATCH] Rewrote parser in tril Signed-off-by: Yuehan-Lin --- fvtest/tril/tril/CMakeLists.txt | 17 +- fvtest/tril/tril/parser.cpp | 482 ++++++++++++++++++++++++++++++++ fvtest/tril/tril/tril.l | 81 ------ fvtest/tril/tril/tril.y | 170 ----------- 4 files changed, 483 insertions(+), 267 deletions(-) create mode 100644 fvtest/tril/tril/parser.cpp delete mode 100644 fvtest/tril/tril/tril.l delete mode 100644 fvtest/tril/tril/tril.y diff --git a/fvtest/tril/tril/CMakeLists.txt b/fvtest/tril/tril/CMakeLists.txt index 20143b84391..cb35fb78f2e 100644 --- a/fvtest/tril/tril/CMakeLists.txt +++ b/fvtest/tril/tril/CMakeLists.txt @@ -23,17 +23,11 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/modules" ${CMAKE_MODULE_PATH}) include(OmrUtility) -include(FindYACC) -include(FindLEX) - -find_package(YACC REQUIRED) -find_package(LEX REQUIRED) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_EXTENSIONS OFF) -list(APPEND TRIL_FLEX_FLAGS) # There is no unistd.h on Windows, so if win_flex.exe is in use, # the --wincompat option must be added. @@ -43,20 +37,11 @@ if(OMR_HOST_OS STREQUAL "win") ) endif() -omr_stringify(TRIL_FLEX_OPTIONS ${TRIL_FLEX_FLAGS}) -YACC_TARGET(tril_parser tril.y ${CMAKE_CURRENT_BINARY_DIR}/tril.parser.c - DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/tril.parser.h) -LEX_TARGET(tril_scanner tril.l ${CMAKE_CURRENT_BINARY_DIR}/tril.scanner.c - COMPILE_FLAGS ${TRIL_FLEX_OPTIONS} -) -ADD_LEX_YACC_DEPENDENCY(tril_scanner tril_parser) - set(TRIL_BACKEND_LIB testcompiler) add_library(tril STATIC - ${YACC_tril_parser_OUTPUTS} - ${LEX_tril_scanner_OUTPUTS} ast.cpp + parser.cpp ilgen.cpp simple_compiler.cpp ) diff --git a/fvtest/tril/tril/parser.cpp b/fvtest/tril/tril/parser.cpp new file mode 100644 index 00000000000..6795791c94b --- /dev/null +++ b/fvtest/tril/tril/parser.cpp @@ -0,0 +1,482 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +#include "ast.h" +#include "ast.hpp" +#include +#include +#include +#include +#include + + +static ASTNode* trees; + +int MAX_NUM = 128; + +class Token { + public: + enum Type { + ID = 0, + STRING_, + STRING_0, + INT, + WHITESPACE, + AT, + ZERO, + HEXINT, + QUOT, + LPAREN, + RPAREN, + LPAREN_SQ, + RPAREN_SQ, + BECOMES, + COMMA, + COMMENT, + DOUBLE_ + }; + + private: + Type type; + std::string value; + + + public: + Token(Type type, std::string value): + type(type), value(value) {} + Type getType() const { return type; } + void setType(Token::Type t) {type = t ;} + const std::string &getValue() const {return value ;} +}; + +class TokenFailure { + std::string message; + +public: + TokenFailure(std::string message); + const std::string &what() const; +}; + +TokenFailure::TokenFailure(std::string message) : + message(message) {} + +const std::string &TokenFailure::what() const { return message; } + +int isNotNewLine(int c) { return c != '\n'; } + +int isNotQuot(int c) { return c != '"'; } + +int isHex(int c) { + if (c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c =='f' || + c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' || c == 'F') { + return true; + } else { + return false; + } +} + +int isNotZero(int c) { return c != '0' && isdigit(c); } + +class ASTstates { + public: + enum State { + ID = 0, + STRING_, + STRING_0, + INT, + WHITESPACE, + AT, + ZERO, + HEXINT, + QUOT, + PAREN, + LPAREN, + RPAREN, + LPAREN_SQ, + RPAREN_SQ, + BECOMES, + COMMA, + DOUBLE_, + + START, + FAIL, + DOT, + MINUS, + COMMENT, + LARGEST_STATE = COMMENT + }; + + private: + std::vector acceptingStates; + std::vector > transitionFunction; + Token::Type stateToType(State s) const { + switch(s) { + case ID: return Token::ID; + case STRING_: return Token::STRING_; + case INT: return Token::INT; + case WHITESPACE: return Token::WHITESPACE; + case DOUBLE_: return Token::DOUBLE_; + case AT: return Token::AT; + case ZERO: return Token::ZERO; + case QUOT: return Token::QUOT; + case LPAREN: return Token::LPAREN; + case RPAREN: return Token::RPAREN; + case LPAREN_SQ: return Token::LPAREN_SQ; + case RPAREN_SQ: return Token::RPAREN_SQ; + case BECOMES: return Token::BECOMES; + case COMMA: return Token::COMMA; + case HEXINT: return Token::HEXINT; + case COMMENT: return Token::COMMENT; + default: throw TokenFailure("Cannot convert state to Type"); + } + } + + public: + + State start() const { return START; } + + bool failed(State state) const { return state == FAIL; } + + bool accept(State state) const { + for (int i = 0; i < acceptingStates.size(); i++) { + if (acceptingStates[i] == state) { + return true; + } + } + return false; + } + + void stateTransition(State oldState, const std::string &chars, State newState) { + for (char c : chars) { + transitionFunction[oldState][c] = newState; + } + } + + void stateTransition(State oldState, int (*test)(int), State newState) { + for (int c = 0; c < 128; ++c) { + if (test(c)) { + transitionFunction[oldState][c] = newState; + } + } + } + + State getNewState(State state, char nextChar) const { + return transitionFunction[state][nextChar]; + } + + + ASTstates() { + acceptingStates = {ID, STRING_, INT, DOUBLE_, WHITESPACE, COMMENT, PAREN, ZERO, + LPAREN, RPAREN, LPAREN_SQ, RPAREN_SQ, BECOMES, COMMA, HEXINT}; + transitionFunction = std::vector > (LARGEST_STATE+1, std::vector (MAX_NUM)); + + for (size_t i = 0; i < transitionFunction.size(); ++i) { + for (size_t j = 0; j < transitionFunction[0].size(); ++j) { + transitionFunction[i][j] = FAIL; + } + } + stateTransition(START, "@", AT); + stateTransition(START, "-", MINUS); + stateTransition(START, isNotZero, INT); + stateTransition(START, ";", COMMENT); + stateTransition(START, "-", MINUS); + stateTransition(START, "\"", QUOT); + stateTransition(START, isalpha, ID); + stateTransition(START, isspace, WHITESPACE); + stateTransition(START, "[", LPAREN_SQ); + stateTransition(START, "]", RPAREN_SQ); + stateTransition(START, "(", LPAREN); + stateTransition(START, ")", RPAREN); + stateTransition(START, "=", BECOMES); + stateTransition(START, ",", COMMA); + stateTransition(START, "0", ZERO); + stateTransition(WHITESPACE, isspace, WHITESPACE); + stateTransition(AT, isalpha, ID); + stateTransition(ID, isalpha, ID); + stateTransition(ID, isdigit, ID); + stateTransition(MINUS, "0", ZERO); + stateTransition(MINUS, isNotZero, INT); + stateTransition(ZERO, isdigit, INT); + stateTransition(ZERO, "x", HEXINT); + stateTransition(HEXINT, isdigit, HEXINT); + stateTransition(HEXINT, isHex, HEXINT); + stateTransition(INT, isdigit, INT); + stateTransition(ZERO, ".", DOT); + stateTransition(INT, ".", DOT); + stateTransition(DOT, isdigit, DOUBLE_); + stateTransition(DOUBLE_, isdigit, DOUBLE_); + stateTransition(COMMENT, isNotNewLine, COMMENT); + stateTransition(COMMENT, isNotNewLine, COMMENT); + stateTransition(QUOT, isNotQuot, STRING_0); + stateTransition(STRING_0, isdigit, STRING_0); + stateTransition(STRING_0, isalpha, STRING_0); + stateTransition(STRING_0, isNotQuot, STRING_0); + stateTransition(STRING_0, "\"", STRING_); + } + + std::vector simplifiedMaximalMunch(const std::string &input) const { + std::vector result; + State state = start(); + std::string munchedInput; + for (std::string::const_iterator inputPosn = input.begin(); inputPosn != input.end();) { + State oldState = state; + state = getNewState(state, *inputPosn); + if (!failed(state)) { + munchedInput += *inputPosn; + oldState = state; + ++inputPosn; + } + if (inputPosn == input.end() || failed(state)) { + if (accept(oldState)) { + result.push_back(Token(stateToType(oldState), munchedInput)); + munchedInput = ""; + state = start(); + } else { + if (failed(state)) { + munchedInput += *inputPosn; + } + throw TokenFailure("ERROR: Simplified maximal munch failed on input: " + munchedInput); + } + } + } + return result; + } +}; + +std::vector scan(const std::string &input) { + static ASTstates rules; + std::vector tokens = rules.simplifiedMaximalMunch(input); + std::vector newTokens; + for (int i = 0; i < tokens.size(); i++) { + if (tokens[i].getType() != Token::Type::COMMENT && tokens[i].getType() != Token::Type::WHITESPACE) { + newTokens.push_back(tokens[i]); + } + } + return newTokens; +} + + +std::ostream &operator<<(std::ostream &out, const Token &tok) { + switch(tok.getType()) { + case Token::ID: out << "ID"; break; + case Token::STRING_: out << "STRING_"; break; + case Token::INT: out << "INT"; break; + case Token::DOUBLE_: out << "DOUBLE_"; break; + case Token::AT: out << "AT"; break; + case Token::ZERO: out << "ZERO"; break; + case Token::QUOT: out << "QUOT"; break; + case Token::LPAREN: out << "LPAREN"; break; + case Token::RPAREN: out << "RPAREN"; break; + case Token::LPAREN_SQ: out << "LPAREN_SQ"; break; + case Token::RPAREN_SQ: out << "RPAREN_SQ"; break; + case Token::BECOMES: out << "BECOMES"; break; + case Token::COMMA: out << "COMMA"; break; + case Token::HEXINT: out << "HEXINT"; break; + default: throw TokenFailure("ERROR: Failed to determine input: " + tok.getValue()); + } + out << " " << tok.getValue(); + return out; +} + +class TokenIter { + private: + std::vector ::iterator it; + std::vector ::iterator end; + public: + TokenIter(std::vector ::iterator it, std::vector ::iterator end) + : it(it), end(end) {} + std::vector ::iterator operator++() { return it++;} + bool is_end() { return it == end;} + std::vector ::iterator peek() { + std::vector ::iterator temp = it; + temp++; + return temp; + } + std::vector ::iterator getIt() { return it; } + std::vector ::iterator getEnd() { return end; } +}; + +ASTValue* buildNodeValue(Token token) { + Token::Type tokenType = token.getType(); + std::string tokenValue = token.getValue(); + if (tokenValue.size() > 1 && tokenType == Token::STRING_) { + tokenValue = tokenValue.substr(1, tokenValue.size() - 2); + } + char * cstr = new char[tokenValue.size() + 1]; + strcpy(cstr, tokenValue.c_str()); + if (tokenType == Token::STRING_ || tokenType == Token::ID) { + return createStrValue(cstr); + } else if (tokenType == Token::DOUBLE_) { + double tmp = std::atof(cstr); + return createFloatingPointValue(tmp); + } else if (tokenType == Token::INT || tokenType == Token::ZERO) { + return createIntegerValue(std::stoull(tokenValue)); + } else if (tokenType == Token::HEXINT) { + return createIntegerValue(std::strtoull(cstr, NULL, 0)); + } else { + throw TokenFailure("Do not have token type with value" + tokenValue + " as value type"); + } +} + + +ASTNodeArg* parseArgList(TokenIter &tokenIt) { + ASTNodeArg* head_arg = NULL; + ASTNodeArg* head_argList = NULL; + ASTValue* head_args_value = NULL; + ASTValue* head_args_value_head = NULL; + + try { + while (tokenIt.getIt()->getType() != Token::LPAREN && tokenIt.getIt()->getType() != Token::RPAREN) { + if (tokenIt.getIt()->getType() == Token::ID && tokenIt.peek()->getType() == Token::BECOMES) { + char * node_args_name = new char[tokenIt.getIt()->getValue().size() + 1]; + strcpy(node_args_name, tokenIt.getIt()->getValue().c_str()); + if (tokenIt.peek()->getType() == Token::RPAREN) { + head_arg = createNodeArg(node_args_name, buildNodeValue(*(tokenIt.getIt())), NULL); + } else { + ++tokenIt; + ++tokenIt; + if (tokenIt.getIt()->getType() == Token::LPAREN_SQ) { + ++tokenIt; + while (tokenIt.getIt()->getType() != Token::RPAREN_SQ) { + if (head_args_value == NULL && tokenIt.getIt()->getType() != Token::COMMA) { + head_args_value = buildNodeValue(*(tokenIt.getIt())); + head_args_value_head = head_args_value; + } else if (head_args_value && tokenIt.getIt()->getType() != Token::COMMA) { + head_args_value->next = buildNodeValue(*(tokenIt.getIt())); + head_args_value = head_args_value->next; + } + ++tokenIt; + } + head_arg = createNodeArg(node_args_name, head_args_value_head, NULL); + } else { + head_arg = createNodeArg(node_args_name, buildNodeValue(*(tokenIt.getIt())), NULL); + } + } + } else if (tokenIt.getIt()->getType() == Token::DOUBLE_ || tokenIt.getIt()->getType() == Token::INT || + tokenIt.getIt()->getType() == Token::STRING_ || tokenIt.getIt()->getType() == Token::HEXINT || + tokenIt.getIt()->getType() == Token::ZERO || tokenIt.getIt()->getType() == Token::ID) { + head_arg = createNodeArg("", buildNodeValue(*(tokenIt.getIt())), NULL); + } else { + throw TokenFailure("Incorrect type for argument, current value is " + tokenIt.getIt()->getValue()); + } + if (head_argList == NULL) { + head_argList = head_arg; + } else { + appendSiblingArg(head_argList, head_arg); + } + ++tokenIt; + } + } catch (TokenFailure &f) { + std::cerr << f.what() << std::endl; + } + return head_argList; +} + + +ASTNode* buildAST(TokenIter &tokenIt) { + ASTNodeArg* head_argList = NULL; + ASTNode * head_child = NULL; + ASTNode * head_children = NULL; + ASTNode * head_siblings = NULL; + + while (tokenIt.getIt()->getType() == Token::LPAREN) { + if (tokenIt.peek() == tokenIt.getEnd() || tokenIt.peek()->getType() != Token::ID) { + throw TokenFailure("The next token of LPAREN should be IDENTIFIER, while current value is " + tokenIt.getIt()->getValue()); + } + ++tokenIt; + char * node_name = new char[tokenIt.getIt()->getValue().size() + 1]; + strcpy(node_name, tokenIt.getIt()->getValue().c_str()); + ++tokenIt; + if (tokenIt.getIt()->getType() == Token::ID || tokenIt.getIt()->getType() == Token::DOUBLE_ || + tokenIt.getIt()->getType() == Token::INT || tokenIt.getIt()->getType() == Token::STRING_ || + tokenIt.getIt()->getType() == Token::HEXINT || tokenIt.getIt()->getType() == Token::ZERO) { + try { + head_argList = parseArgList(tokenIt); + } catch (TokenFailure &f) { + std::cerr << f.what() << std::endl; + } + } + head_child = buildAST(tokenIt); + if (head_children == NULL) { + head_children = head_child; + } else { + appendSiblingNode(head_children, head_child); + } + if (tokenIt.getIt()->getType() != Token::RPAREN && tokenIt.getIt() != tokenIt.getEnd()) { + throw TokenFailure("Missing RPAREN, while current value is " + tokenIt.getIt()->getValue()); + } + ++tokenIt; + if (head_siblings == NULL) { + head_siblings = createNode(node_name, head_argList, head_children, NULL); + } else { + appendSiblingNode(head_siblings, createNode(node_name, head_argList, head_children, NULL)); + } + head_children = NULL; + head_child = NULL; + } + return head_siblings; +} + + +ASTNode* parseFile(FILE *in) { + std::vector scanToken; + try { + char * line = NULL; + ssize_t read; + size_t len = 0; + while ((read = getline(&line, &len, in)) != -1) { + std::vector tokenLine = scan(line); + scanToken.insert(scanToken.end(), tokenLine.begin(), tokenLine.end()); + } + } catch (TokenFailure &f) { + std::cerr << f.what() << std::endl; + } + + TokenIter token = TokenIter(scanToken.begin(), scanToken.end()); + ASTNode* head = NULL; + try { + head = buildAST(token); + } catch (TokenFailure &f) { + std::cerr << f.what() << std::endl; + } + return head; +} + + +ASTNode* parseString(const char* in) { + ASTNode* head = NULL; + + FILE* pf = tmpfile(); + if (pf != NULL) { + if(fputs(in, pf) >= 0) { + fflush(pf); + fseek(pf, 0, SEEK_SET); + head = parseFile(pf); + } else { + fprintf(stderr, "Tril parser error: Could not write to temporary file \n"); + } + } else { + fprintf(stderr, "Tril parser error: Could not create temporary file for writing \n"); + } + fclose(pf); + return head; +} diff --git a/fvtest/tril/tril/tril.l b/fvtest/tril/tril/tril.l deleted file mode 100644 index a2f071efdf5..00000000000 --- a/fvtest/tril/tril/tril.l +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -%{ - #include "ast.h" - #include "tril.parser.h" - #include -%} - -%% - -@?[a-zA-Z][a-zA-Z0-9]* { - char* name = (char*)malloc(yyleng*sizeof(char) + 1); - snprintf(name, yyleng + 1, "%s", yytext); - yylval.str = name; - return IDENTIFIER; - }; - -[-]?[0-9]+ { - yylval.integer = strtoull(yytext, NULL, 10); - return INTEGER; - }; - -[-]?0x[0-9a-fA-F]+ { - yylval.integer = strtoull(yytext, NULL, 16); - return INTEGER; - }; - -[-]?[0-9]+[.][0-9]+ { - yylval.f64 = strtod(yytext, NULL); - return DOUBLE; - }; - -;[^\n]* ; /* ignore comment */ - -\"[^"]*\" { - char* val = (char*)malloc(yyleng*sizeof(char) + 1); - snprintf(val, yyleng - 1, "%s", yytext + 1); - yylval.str = val; - return STRING; - }; - -[()[\]=,] return *yytext; - -[ \t\n] ; /* ignore white space */ - -. fprintf(stderr, "Invalid character '%s'\n", yytext); - -%% - -void set_input_file(FILE* in) { - yyin = in; -} - -int yyerror(char *s, ...) { - fprintf(stderr, "Tril lexer error on line %d: %s\n", yylineno, s); - return 1; -} - -int yywrap(void) { - return 1; -} diff --git a/fvtest/tril/tril/tril.y b/fvtest/tril/tril/tril.y deleted file mode 100644 index f99e64eb812..00000000000 --- a/fvtest/tril/tril/tril.y +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ - -%{ - #include "ast.h" - #include - - static ASTNode* trees; -%} - -%union { - ASTNode* node; - ASTNodeArg* arg; - char* str; - uint64_t integer; - double f64; - ASTValue* value; -}; - -%token IDENTIFIER STRING -%token INTEGER -%token DOUBLE - -%type node nodeList -%type arg argList -%type value valueList - -%% - -nodeList: - node - { - //printf("Generating tree\n"); - $$ = trees = $1; - } - | nodeList node - { - //printf("Generating tree list\n"); - appendSiblingNode($1, $2); - $$ = trees = $1; - } - ; - -node: - '(' IDENTIFIER ')' - { - //printf("Generating leaf node") - $$ = createNode($2, NULL, NULL, NULL); - } - | '(' IDENTIFIER nodeList ')' - { - //printf("Generating tree node") - $$ = createNode($2, NULL, $3, NULL); - } - | '(' IDENTIFIER argList ')' - { - //printf("Generating node with argument") - $$ = createNode($2, $3, NULL, NULL); - } - | '(' IDENTIFIER argList nodeList ')' - { - //printf("Generating tree node with argument") - $$ = createNode($2, $3, $4, NULL); - } - ; - -argList: - arg - { - $$ = $1; - } - | argList arg - { - appendSiblingArg($1, $2); - $$ = $1; - } - ; - -arg: - value - { - $$ = createNodeArg("", $1, NULL); - } - | IDENTIFIER '=' value - { - $$ = createNodeArg($1, $3, NULL); - } - | IDENTIFIER '=' '[' valueList ']' - { - $$ = createNodeArg($1, $4, NULL); - } - ; - -valueList: - value - { - $$ = $1; - } - | valueList ',' value - { - appendSiblingValue($1, $3); - $$ = $1; - } - ; - -value: - INTEGER - { - //printf("Generating value %d\n", $1); - $$ = createIntegerValue($1); - } - | DOUBLE - { - $$ = createFloatingPointValue($1); - } - | STRING - { - //printf("Generating value \"%s\"\n", $1); - $$ = createStrValue($1); - } - | IDENTIFIER - { - //printf("Generating value \"%s\"\n", $1); - $$ = createStrValue($1); - } - ; - -%% - -ASTNode* parseFile(FILE* in) { - set_input_file(in); - yyparse(); - return trees; -} - -ASTNode* parseString(const char* in) { - FILE* pf = tmpfile(); - if (pf != NULL) { - if(fputs(in, pf) >= 0) { - fflush(pf); - fseek(pf, 0, SEEK_SET); - parseFile(pf); - } else { - fprintf(stderr, "Tril parser error: Could not write to temporary file \n"); - } - } else { - fprintf(stderr, "Tril parser error: Could not create temporary file for writing \n"); - } - fclose(pf); - return trees; -}