blob: 89eb63871e1148becf08016244833aeae8df6f88 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#include "Common.h"
#include "Grammar.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
typedef struct Rule Rule;
struct Rule {
char *name;
Expression *expr;
Rule *next;
};
struct Grammar {
Rule **nextRule;
Rule *ruleList;
};
Rule *RuleNew(const char *name, Expression *expr)
{
Rule *rule = (Rule *)calloc(1,sizeof(Rule));
rule->name = strdup(name);
rule->expr = expr;
return rule;
}
void RuleFree(Rule *rule)
{
free(rule->name);
ExpressionFree(rule->expr);
free(rule);
}
Grammar *GrammarNew(void)
{
Grammar *gram = (Grammar *)calloc(1,sizeof(Grammar));
gram->nextRule = &gram->ruleList;
return gram;
}
void GrammarFree(Grammar *gram)
{
Rule *next;
for (Rule *rule = gram->ruleList; rule != NULL; rule = next) {
next = rule->next;
RuleFree(rule);
}
free(gram);
}
void GrammarDefine(Grammar *gram, const char *name, Expression *expr)
{
Rule *rule = RuleNew(name,expr);
*gram->nextRule = rule;
gram->nextRule = &rule->next;
}
Expression *GrammarLookup(Grammar *gram, const char *name)
{
for (Rule *rule = gram->ruleList; rule != NULL; rule = rule->next) {
if (!strcmp(rule->name,name))
return rule->expr;
}
return NULL;
}
static void GrammarResolveRecursive(Grammar *gram, Expression *expr, const char *ruleName)
{
if (ExpressionKind(expr) == IdentExpr) {
const char *targetName = ExprIdentValue(expr);
Expression *targetExpr = GrammarLookup(gram,targetName);
if (targetExpr == NULL) {
fprintf(stderr,"%s: Cannot resolve reference %s\n",ruleName,targetName);
exit(1);
}
ExprIdentSetTarget(expr,targetExpr);
}
else {
for (int i = 0; i < ExpressionCount(expr); i++)
GrammarResolveRecursive(gram,ExpressionChildAt(expr,i),ruleName);
}
}
void GrammarResolve(Grammar *gram)
{
for (Rule *rule = gram->ruleList; rule != NULL; rule = rule->next)
GrammarResolveRecursive(gram,rule->expr,rule->name);
}
void GrammarPrint(Grammar *gram, int exprAsTree)
{
int maxNameLen = 0;
for (Rule *rule = gram->ruleList; rule != NULL; rule = rule->next) {
int nameLen = strlen(rule->name);
if (maxNameLen < nameLen)
maxNameLen = nameLen;
}
char *prefix = malloc(maxNameLen+2);
memset(prefix,' ',maxNameLen+1);
prefix[maxNameLen+1] = '\0';
for (Rule *def = gram->ruleList; def != NULL; def = def->next) {
int nameLen = strlen(def->name);
printf("%s",def->name);
if (exprAsTree) {
// Print the expression in tree format, with one line per node
printf("\n");
printf("\n");
printf(" ");
ExpressionPrintTree(def->expr," ",4);
printf("\n");
}
else {
// Print the expression in compact format, with one line per alternative
for (int i = nameLen; i < maxNameLen+1; i++)
printf(" ");
printf(": ");
ExpressionPrint(def->expr,0,prefix);
printf(";\n");
}
}
free(prefix);
}
const char *GrammarFirstRuleName(Grammar *gram)
{
if (gram->ruleList == NULL)
return NULL;
else
return gram->ruleList->name;
}