Skip to content

Instantly share code, notes, and snippets.

@antonijn
Created July 27, 2017 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antonijn/5a941f0799fce9727351b9a010598472 to your computer and use it in GitHub Desktop.
Save antonijn/5a941f0799fce9727351b9a010598472 to your computer and use it in GitHub Desktop.

Typical Usage of groc

The example presented here shows how one would use groc to create an internationalized die-roll application:

$ roll
You rolled a one
$ roll
You rolled a six

Or in Dutch:

$ roll
Je hebt een één gegooid
$ roll
Je hebt een zes gegooid

The project directory is as follows:

├── Makefile
├── lang
│   ├── App.grok
│   ├── en_US.grok
│   └── nl_NL.grok
└── src
    └── main.c

The interface file is there simply to specify which functions should be implemented in each language. In this case, just a simple youRolled() function:

-- App.grok
interface App

youRolled :: Int -> String

The interface is implemented in two languages: American English (en_US) and Netherlandic Dutch (nl_NL). The standard library modules "std/English" and "std/Dutch" provide several very basic helper functions. Neither module provides a lexicon of any kind.

English:

-- en_US.grok
lang "en_US"
implements "App"

import "std/English"

App.youRolled(n) = "You rolled " + English.indef(English.spellInt(n))

Dutch:

-- nl_NL.grok
lang "nl_NL"
implements "App"

import "std/Dutch"

App.youRolled(n) = "Je hebt een " + Dutch.spellInt(n) + " gegooid"

The C program implements the main logic. The correct language is automatically selected based on system locale variables.

/* main.c */
#include <grok/rt.h>
#include <rand.h>
#include <stdio.h>
#include <time.h>

int main(void)
{
	char *s;
	
	srand(time(NULL));

	s = groks("App.youRolled", 1, (rand() % 6) + 1);
	printf("%s\n", s);
	free(s);

	return 0;
}

The grok files are built in the same way C files are built, except using groc as the compiler. libgrok-rt is the grok runtime library.

# Makefile
CC = cc
CFLAGS = -c $(shell pkg-config --cflags grok-rt)
LD = $(CC)
LDFLAGS = $(shell pkg-config --libs grok-rt)
GROC = groc
GROCFLAGS = -c

OBJECTS = src/main.o lang/en_US.o lang/nl_NL.o
TARGET = roll

all: $(TARGET)

$(TARGET): $(OBJECTS)
	$(LD) $(LDFLAGS) -o $@ $^

%.o: %.c
	$(CC) $(CFLAGS) -o $@ $^

%.o: %.grok
	$(GROC) $(GROCFLAGS) -o $@ $^
@finnoleary
Copy link

finnoleary commented Jul 28, 2017

[copied from private communique]
It might be convenient to stick translations into different files, which allows multiple contributors to aid with translation (It works better with things like git) and allows for a greater seperation of concerns. It also cuts down loading a huge file for each translation on init[¿] -- you have a tiny to mediocre-sized file that you can load, parse, and run really quickly on the fly. Meaning that you only load what you use.

Say, you have the following layout:

├── lang/
   ├── App.grok
   ├── en_US.grok/
      └── App.yourolled
   └── nl_NL.grok/
       └── App.yourolled

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment