Skip to content

Commit

Permalink
DOE-2 support (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchpaulus committed Feb 20, 2022
1 parent d1a4778 commit 3d58144
Show file tree
Hide file tree
Showing 59 changed files with 9,304 additions and 305 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Simple Windows GUI for compiling.

## 0.7.0 - 2022-02-20

### Added

- DOE-2 support added. Can now parse input file in the Building Description Language (BDL) format.

### Changed

- Release binaries are not trimmed, due to compiler warnings about possible behavior changes.

## 0.6.1 - 2022-02-13

### Changed
Expand Down
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Neobem

Neobem is a preprocessor programming language primarily targeted for the
idf input files for EnergyPlus.
idf input files for [EnergyPlus](https://energyplus.net). It also
support the Building Description Language used for
[DOE-2](https://www.doe2.com/).

You can view the entire user manual in PDF form at
[neobem.io/neobem.pdf](https://neobem.io/neobem.pdf).
[here](https://neobem.io/neobem.pdf) and online at
[neobem.io](https://neobem.io).

# Introduction

Expand Down Expand Up @@ -73,8 +76,8 @@ that file from the zip file to a location that you will want the program
to live. It doesn’t really matter where you put it, but recommended
places would be:

- `C:\Program Files\neobem` on Windows
- `/usr/local/neobem` or `~/.local/neobem` on Linux
- `C:\Program Files\neobem\neobem.exe` on Windows
- `/usr/local/bin/nbem` or `~/.local/bin/nbem` on Linux

Neobem is a console or command line application. It is meant to be run
from a shell environment, that could be anything like[2]:
Expand Down Expand Up @@ -184,19 +187,22 @@ If things are working correctly, you should see help text like:

``` console
mp@mp-computer:~$ nbem -h
Usage: nbem [options..] [input file]
Compile Neobem file to idf output
USAGE: nbem [options..] [input file]
Compile Neobem file to EnergyPlus or DOE-2 input files.

With no [input file], input is read from file named 'in.nbem' in the
current directory. If the input file is '-', input is read from standard
input rather than from a file.

OPTIONS:

-h, --help show this help and exit
-f, --fmt format file instead of compiling
-o, --output <filename> output file name, default is standard output
-v, --version print version number and exit
--doe2 Parse input file in DOE-2 Building Description Language format
-h, --help Show this help and exit
-f, --fmt Format file instead of compiling
-o, --output <filename> Output file name. Output is printed to standard output by default.
--tokens Print lexed tokens for debugging
--tree Print parse tree in Lisp format for debugging
-v, --version Print version number and exit
```

In general, you will call the execute the program `nbem`, passing in
Expand Down
6 changes: 4 additions & 2 deletions README.template
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Neobem

Neobem is a preprocessor programming language primarily targeted for the idf input files for EnergyPlus.
Neobem is a preprocessor programming language primarily targeted for the idf input files for [EnergyPlus](https://energyplus.net).
It also support the Building Description Language used for [DOE-2](https://www.doe2.com/).

You can view the entire user manual in PDF form at [neobem.io/neobem.pdf](https://neobem.io/neobem.pdf).
You can view the entire user manual in PDF form at
[here](https://neobem.io/neobem.pdf) and online at [neobem.io](https://neobem.io).

INCLUDE doc/intro.md

Expand Down
4 changes: 2 additions & 2 deletions antlr/compile_grammer
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh

java -jar /usr/local/lib/antlr-4.8-complete.jar NeobemLexer.g4
java -jar /usr/local/lib/antlr-4.8-complete.jar -visitor NeobemParser.g4
java -jar /usr/local/lib/antlr-4.8-complete.jar -o ../src/antlr/ NeobemLexer.g4
java -jar /usr/local/lib/antlr-4.8-complete.jar -o ../src/antlr/ -visitor NeobemParser.g4
2 changes: 1 addition & 1 deletion antlr/excelrange/compile.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh

java -jar /usr/local/lib/antlr-4.8-complete.jar ./*.g4
java -jar /usr/local/lib/antlr-4.8-complete.jar -o ../../src/antlr/ ./*.g4
5 changes: 1 addition & 4 deletions doc/doc.tex
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\setcounter{secnumdepth}{-\maxdimen} % remove section numbering
\ifluatex
\usepackage{selnolig} % disable illegal ligatures
\fi
%\usepackage[defaultmono]{droidmono}
\usepackage{fontspec}
\setmonofont{iosevka}
Expand All @@ -103,7 +100,7 @@

\author{Mitchell T. Paulus}
\title{Neobem}
\date{Version 0.6.0, \today}
\date{Version 0.7.0, \today}

\begin{document}
\maketitle
Expand Down
4 changes: 2 additions & 2 deletions doc/getting_started.inc.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ Extract that file from the zip file to a location that you will want the program
live. It doesn't really matter where you put it, but recommended places
would be:

- `C:\Program Files\neobem` on Windows
- `/usr/local/neobem` or `~/.local/neobem` on Linux
- `C:\Program Files\neobem\neobem.exe` on Windows
- `/usr/local/bin/nbem` or `~/.local/bin/nbem` on Linux

Neobem is a console or command line application. It is meant to be run
from a shell environment, that could be anything like[^Shells]:
Expand Down
2 changes: 1 addition & 1 deletion doc/html_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h2 class="sansserif">Neobem</h2>
</nav>
<section style="flex-grow: 1; overflow-y: auto">
<div style="width: 50em; padding-left: 4%">
<h1>Neobem User Manual - 0.6.0</h1>
<h1>Neobem User Manual - 0.7.0</h1>
INCLUDE contents.html
</div>
</section>
Expand Down
47 changes: 47 additions & 0 deletions src/Doe2Keywords.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace src;

public static class Doe2Keywords
{

public static HashSet<string> Keywords = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"INPUT", "TITLE", "DIAGNOSTIC", "ABORT", "RUN-PERIOD", "SCHEDULE", "WEEK-SCHEDULE", "DAY-SCHEDULE",
"SITE-PARAMETERS", "BUILD-PARAMETERS", "LAYERS", "CONSTRUCTION", "GLASS-TYPE", "SPACE", "EXTERIOR-WALL", "ROOF", "WINDOW", "DOOR", "INTERIOR-WALL", "UNDERGROUND-WALL", "UNDERGROUND-FLOOR", "LOADS-REPORT",
"SYSTEM", "ZONE", "DAY-RESET-SCH", "RESET-SCHEDULE", "SYSTEMS-REPORT",
"ELEC-METER", "FUEL-METER", "MASTER-METERS", "PUMP", "CIRCULATION-LOOP", "BOILER", "CHILLER", "HEAT-REJECTION", "DW-HEATER",
"UTILITY-RATE", "BLOCK-CHARGE", "ECONOMICS-REPORT",
};
}

public class Doe2Printer
{
private readonly ObjectVariableReplacer _replacer;
private readonly List<Dictionary<string, Expression>> _environments;
private readonly FileType _fileType;

public Doe2Printer(ObjectVariableReplacer replacer, List<Dictionary<string, Expression>> environments, FileType fileType)
{
_replacer = replacer;
_environments = environments;
_fileType = fileType;
}

public string PrettyPrint(NeobemParser.Doe2objectContext context)
{
string replaced = _replacer.Replace(context.GetText(), _environments, _fileType);

return replaced;

bool firstWordIsCommand;

firstWordIsCommand = context.DOE2STRING_UNAME() == null && Doe2Keywords.Keywords.Contains(context.DOE2IDENTIFIER().GetText());

var items = context.children.Select(tree => _replacer.Replace(tree.GetText(), _environments, _fileType));

return $"{items.Join(" ")}";
}
}
24 changes: 16 additions & 8 deletions src/Expression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public PartialApplicationFunctionExpression(
FunctionExpression original,
List<Dictionary<string, Expression>> environments,
List<string> remainingParameters,
Dictionary<int, Expression> partiallyAppliedParameters) : base(environments, remainingParameters)
Dictionary<int, Expression> partiallyAppliedParameters) : base(environments, remainingParameters, FileType.Any)
{
_original = original;
_partiallyAppliedParameters = partiallyAppliedParameters;
Expand Down Expand Up @@ -101,6 +101,7 @@ public class FunctionExpression : Expression
{
private readonly NeobemParser.LambdaExpContext _context;
private readonly List<Dictionary<string, Expression>> _environments;
private readonly FileType _fileType;

public readonly List<string> Parameters;

Expand All @@ -109,17 +110,19 @@ public class FunctionExpression : Expression

public override string TypeName() => "function";

public FunctionExpression(NeobemParser.LambdaExpContext lambdaDefContext, List<Dictionary<string, Expression>> environments, string baseDirectory = null)
public FunctionExpression(NeobemParser.LambdaExpContext lambdaDefContext, List<Dictionary<string, Expression>> environments, FileType fileType, string baseDirectory = null)
{
_context = lambdaDefContext;
_environments = environments;
_fileType = fileType;
Parameters = lambdaDefContext.lambda_def().IDENTIFIER().Select(node => node.GetText()).ToList();
}

public FunctionExpression(List<Dictionary<string, Expression>> environments, List<string> parameters, string baseDirectory = null)
public FunctionExpression(List<Dictionary<string, Expression>> environments, List<string> parameters, FileType fileType, string baseDirectory = null)
{
_environments = environments;
Parameters = parameters;
_fileType = fileType;
}

public virtual (string, Expression) Evaluate(List<Expression> inputs, string baseDirectory)
Expand All @@ -138,7 +141,7 @@ public virtual (string, Expression) Evaluate(List<Expression> inputs, string bas
var updatedEnvironments = new List<Dictionary<string, Expression>>(_environments);
updatedEnvironments.Insert(0, locals);

IdfPlusExpVisitor visitor = new(updatedEnvironments, baseDirectory);
IdfPlusExpVisitor visitor = new(updatedEnvironments, _fileType, baseDirectory);

StringBuilder builder = new StringBuilder();

Expand All @@ -160,16 +163,21 @@ public virtual (string, Expression) Evaluate(List<Expression> inputs, string bas
switch (item)
{
case NeobemParser.FunctionIdfCommentContext commentContext:
var replacedComment = replacer.Replace(commentContext.GetText(), updatedEnvironments);
var replacedComment = replacer.Replace(commentContext.GetText(), updatedEnvironments, _fileType);
builder.Append(replacedComment);
break;
case NeobemParser.FunctionObjectDeclarationContext objectDeclarationContext:
string objectText = objectDeclarationContext.GetText();
if (objectText.EndsWith("$")) objectText = objectText.Remove(objectText.Length - 1);
var replacedObject = replacer.Replace(objectText, updatedEnvironments);
var replacedObject = replacer.Replace(objectText, updatedEnvironments, _fileType);
var prettyPrinted = prettyPrinter.ObjectPrettyPrinter(replacedObject, 0, Consts.IndentSpaces);
builder.AppendLine(prettyPrinted);
break;
case NeobemParser.FunctionDoe2ObjectDeclarationContext doe2ObjectDeclarationContext:
Doe2Printer printer = new(replacer, updatedEnvironments, _fileType);
string prettyPrintedDoe2 = printer.PrettyPrint(doe2ObjectDeclarationContext.doe2object());
builder.Append($"{prettyPrintedDoe2}\n\n");
break;
case NeobemParser.FunctionVariableDeclarationContext variableDeclarationContext:
var expressionResult = visitor.Visit(variableDeclarationContext.variable_declaration().expression());
var identifier = variableDeclarationContext.variable_declaration().IDENTIFIER().GetText();
Expand All @@ -181,12 +189,12 @@ public virtual (string, Expression) Evaluate(List<Expression> inputs, string bas
case NeobemParser.FunctionPrintStatementContext printStatmentContext:
// Need a clean visitor, so that only the output from evaluating the single expression
// is appended.
IdfPlusExpVisitor printStatementExpressionVisitor = new(updatedEnvironments, baseDirectory);
IdfPlusExpVisitor printStatementExpressionVisitor = new(updatedEnvironments, _fileType, baseDirectory);
printStatementExpressionVisitor.Visit(printStatmentContext.print_statment().expression());
builder.Append(printStatementExpressionVisitor.output.ToString());
break;
case NeobemParser.FunctionLogStatementContext logStatementContext:
IdfPlusExpVisitor logStatementVisitor = new(updatedEnvironments, baseDirectory);
IdfPlusExpVisitor logStatementVisitor = new(updatedEnvironments, _fileType, baseDirectory);
Expression resultingExpression = logStatementVisitor.Visit(logStatementContext.log_statement().expression());
Console.Error.Write(resultingExpression.AsString() + "\n");
break;
Expand Down
63 changes: 60 additions & 3 deletions src/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ namespace src
{
public static class Extensions
{
public static NeobemParser ToParser(this string input)
public static NeobemParser ToParser(this string input, FileType fileType)
{
AntlrInputStream inputStream = new AntlrInputStream(input);
NeobemLexer lexer = new NeobemLexer(inputStream);
lexer.FileType = fileType;
CommonTokenStream tokens = new CommonTokenStream(lexer);
return new NeobemParser(tokens);
}

public static NeobemParser ToIdfParser(this string input) => ToParser(input, FileType.Idf);

public static string Format(this string input)
{
AntlrInputStream inputStream = new(input);
Expand All @@ -30,8 +33,6 @@ public static string Format(this string input)
return visitor.Visit(idfTree);
}

public static IParseTree ToIdfTree(this string input) => ToParser(input).idf();

public static ExcelRangeParser ToExcelRangeParser(this string input)
{
AntlrInputStream inputStream = new AntlrInputStream(input);
Expand Down Expand Up @@ -97,6 +98,7 @@ public static List<string> SplitLines(this string input)
return output;
}
public static string JoinNull(this IEnumerable<string> strings) => string.Join("", strings);
public static string Join(this IEnumerable<string> strings, string join = "") => string.Join(join, strings);

public static int NumLines(this StringBuilder builder) => builder.ToString().SplitLines().Count;
public static int NumLines(this string input) => input.SplitLines().Count;
Expand Down Expand Up @@ -193,6 +195,61 @@ public static string ToSigFigs(this double value, int sigFigs)
// The 'G' format will take care of trailing zeros for numbers with decimals.
return rounded.ToString(digits == 0 ? "F0" : $"G{sigFigs}");
}

public static int NumNewLinesRequired(this string input, int numNewLines = 2)
{
int newLinesFound = 0;
for (int i = input.Length - 1; i > -1; i--)
{
if (input[i] == '\n') newLinesFound++;
else break;
}
return numNewLines - newLinesFound;
}

public static string AddNewLines(this string input, int numNewLines = 2)
{
int additionalNewLineCount = input.NumNewLinesRequired(numNewLines);
if (additionalNewLineCount == 0) return input;
if (additionalNewLineCount < 0) return input[..(input.Length + additionalNewLineCount)];
string additionalNewLines = new('\n', additionalNewLineCount);
return $"{input}{additionalNewLines}";
}

public static string ParagraphJoin(this IEnumerable<string> items)
{
StringBuilder builder = new();
bool firstItem = true;
int newLinesRequired = 0;
foreach (string item in items)
{
if (firstItem)
{
builder.Append(item);
firstItem = false;
}
else
{
if (newLinesRequired == 0) builder.Append(item);
else builder.Append($"{new string('\n', newLinesRequired)}{item}");
}
newLinesRequired = item.NumNewLinesRequired(2);
}
return builder.ToString();
}

public static string ToString(this IToken token, NeobemLexer lexer)
{
string tokenTypeDisplayName = lexer.Vocabulary.GetDisplayName(token.Type);

string replacedText = token.Text.Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r");

string channelString = token.Channel == 0 ? "" : $"channel={token.Channel}";

return
$"[@{token.TokenIndex},{token.StartIndex}:{token.StopIndex}='{replacedText}',<{tokenTypeDisplayName}>{channelString},{token.Line},{token.Column}";
}

}

public class SplitIdfLine
Expand Down
Loading

0 comments on commit 3d58144

Please sign in to comment.